亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

docker容器如何優(yōu)雅的終止詳解

 更新時(shí)間:2016年11月06日 15:50:15   投稿:daisy  
最近公司在試驗(yàn)如何將項(xiàng)目部署到docker容器中去,這其中涉及到一個(gè)技術(shù)環(huán)節(jié),那就是如何讓docker容器優(yōu)雅的終止。所謂優(yōu)雅終止,指的就是程序在退出前有清理資源,保存必要中間狀態(tài),持久化內(nèi)存數(shù)據(jù)的機(jī)會(huì)。下面通過這篇大家一起由簡單到復(fù)雜逐一考量一下。

前言

在Docker大行其道的今天,我們能夠非常方便的使用容器打包我們的應(yīng)用程序,并且將它在我們的服務(wù)器上部署并運(yùn)行起來。但是,談?wù)摰饺绾瓮5暨\(yùn)行中的docker容器并正確的終止其中的程序,這就成為一個(gè)非常值得討論的話題了。

事實(shí)上,在我們?nèi)粘5捻?xiàng)目當(dāng)中,這是我們經(jīng)常需要面對和處理的問題:

     場景A:假如我們打包在容器中的程序,提供HTTP方式的服務(wù),負(fù)責(zé)處理各種HTTP requests并返回結(jié)果,我們必然希望在容器被停掉的時(shí)候,能夠讓程序有時(shí)間把已經(jīng)在處理中的請求繼續(xù)處理完畢,并返回結(jié)果給客戶端。

     場景B:又比如我們打包在容器中的程序,負(fù)責(zé)寫入數(shù)據(jù)到某個(gè)數(shù)據(jù)文件中,我們希望程序能夠在容器被停掉的時(shí)候,有時(shí)間把內(nèi)存中緩存的數(shù)據(jù)持久化到存儲(chǔ)設(shè)備中,以防數(shù)據(jù)丟失。

     場景C:再比如現(xiàn)在流行的微服務(wù)架構(gòu)中,一般會(huì)有服務(wù)發(fā)現(xiàn)的機(jī)制,也即每一個(gè)微服務(wù)在啟動(dòng)之后,都會(huì)主動(dòng)把自己的地址信息注冊到服務(wù)發(fā)現(xiàn)模塊當(dāng)中,讓其他的服務(wù)可以知道自己的存在。而在容器被停掉的時(shí)候,微服務(wù)需要即時(shí)從服務(wù)發(fā)現(xiàn)模塊中注銷自己,以防止從API Gateway而來的請求被錯(cuò)誤的路由到了已經(jīng)被停止掉的微服務(wù)。

如上的各種場景中,都要求打包在容器中的應(yīng)用程序能夠被優(yōu)雅的終止(也即gracefully shutdown),這種gracefully shutdown的方式,允許程序在容器被停止的時(shí)候,有一定時(shí)間做一些后續(xù)處理操作,這也是我們需要進(jìn)一步探討的話題。

docker stop 與 docker kill 的區(qū)別

Docker本身提供了兩種終止容器運(yùn)行的方式,即docker stopdocker kill。

docker stop

先來說說docker stop吧,當(dāng)我們用docker stop命令來停掉容器的時(shí)候,docker默認(rèn)會(huì)允許容器中的應(yīng)用程序有10秒的時(shí)間用以終止運(yùn)行。所以我們查看docker stop命令幫助的時(shí)候,會(huì)有如下的提示:

→ docker stop --help
Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
Stop one or more running containers
Options:
  --help  Print usage
 -t, --time int Seconds to wait for stop before killing it (default 10)

docker stop命令執(zhí)行的時(shí)候,會(huì)先向容器中PID為1的進(jìn)程發(fā)送系統(tǒng)信號SIGTERM,然后等待容器中的應(yīng)用程序終止執(zhí)行,如果等待時(shí)間達(dá)到設(shè)定的超時(shí)時(shí)間,或者默認(rèn)的10秒,會(huì)繼續(xù)發(fā)送SIGKILL的系統(tǒng)信號強(qiáng)行kill掉進(jìn)程。在容器中的應(yīng)用程序,可以選擇忽略和不處理SIGTERM信號,不過一旦達(dá)到超時(shí)時(shí)間,程序就會(huì)被系統(tǒng)強(qiáng)行kill掉,因?yàn)镾IGKILL信號是直接發(fā)往系統(tǒng)內(nèi)核的,應(yīng)用程序沒有機(jī)會(huì)去處理它。在使用docker stop命令的時(shí)候,我們唯一能控制的是超時(shí)時(shí)間,比如設(shè)置為20秒超時(shí):

docker stop --time=20 container_name

docker kill

接著我們來看看docker kill命令,默認(rèn)情況下,docker kill命令不會(huì)給容器中的應(yīng)用程序有任何gracefully shutdown的機(jī)會(huì)。它會(huì)直接發(fā)出SIGKILL的系統(tǒng)信號,以強(qiáng)行終止容器中程序的運(yùn)行。通過查看docker kill命令的幫助,我們可以看到,除了默認(rèn)發(fā)送SIGKILL信號外,還允許我們發(fā)送一些自定義的系統(tǒng)信號:

→ docker kill --help
Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...]
Kill one or more running containers
Options:
  --help   Print usage
 -s, --signal string Signal to send to the container (default "KILL")

比如,如果我們想向docker中的程序發(fā)送SIGINT信號,我們可以這樣來實(shí)現(xiàn):

docker kill --signal=SIGINT container_name

與docker stop命令不一樣的地方在于,docker kill沒有任何的超時(shí)時(shí)間設(shè)置,它會(huì)直接發(fā)送SIGKILL信號,以及用戶通過signal參數(shù)指定的其他信號。

其實(shí)不難看出,docker stop命令,更類似于Linux系統(tǒng)中的kill命令,二者都是發(fā)送系統(tǒng)信號SIGTERM。而docker kill命令,更像是Linux系統(tǒng)中的kill -9或者是kill -SIGKILL命令,用來發(fā)送SIGKILL信號,強(qiáng)行終止進(jìn)程。

在程序中接收并處理信號

了解了docker stopdocker kill的區(qū)別,我們能夠知道,docker kill適合用來強(qiáng)行終止程序并實(shí)現(xiàn)快速停止容器。而如果希望程序能夠gracefully shutdown的話,docker stop才是不二之選。這樣,我們可以讓程序在接收到SIGTERM信號后,有一定的時(shí)間處理、保存程序執(zhí)行現(xiàn)場,優(yōu)雅的退出程序。

接下來我們可以寫一個(gè)簡單的Go程序來實(shí)現(xiàn)信號的接收與處理,程序在啟動(dòng)過后,會(huì)一直阻塞并監(jiān)聽系統(tǒng)信號,直到監(jiān)測到對應(yīng)的系統(tǒng)信號后,輸出控制臺(tái)并退出執(zhí)行。

// main.go
package main
import (
 "fmt"
 "os"
 "os/signal"
 "syscall"
)
func main() {
 fmt.Println("Program started...")
 ch := make(chan os.Signal, 1)
 signal.Notify(ch, syscall.SIGTERM)
 s := <-ch
 if s == syscall.SIGTERM {
 fmt.Println("SIGTERM received!")
 //Do something...
 }
 fmt.Println("Exiting...")
}

接下來使用交叉編譯的方式來編譯程序,讓程序可以在Linux下運(yùn)行:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o graceful

編譯好之后,我們還需要打包程序到容器中運(yùn)行。于是,我們還得有個(gè)Dockerfile。在這里,我們選擇使用體積小又輕盈的alpine鏡像作為基礎(chǔ)鏡像,打包這個(gè)Go程序:

from alpine:latest
MAINTAINER Timothy
ADD graceful /graceful
CMD ["/graceful"]

這里需要避開的一個(gè)坑,是Dockerfile中CMD命令的用法。

CMD命令有兩種方式:

CMD /graceful

使用 CMD command param1 param2 這種方式,其實(shí)是以shell的方式運(yùn)行程序。最終程序被執(zhí)行時(shí),類似于/bin/sh -c的方式運(yùn)行了我們的程序,這樣會(huì)導(dǎo)致/bin/sh以PID為1的進(jìn)程運(yùn)行,而我們的程序只不過是它fork/execs出來的子進(jìn)程而已。前面我們提到過docker stop的SIGTERM信號只是發(fā)送給容器中PID為1的進(jìn)程,而這樣,我們的程序就沒法接收和處理到信號了。

CMD [“/graceful”]

使用 CMD [“executable”,”param1”,”param2”] 這種方式啟動(dòng)程序,才是我們想要的,這種方式執(zhí)行和啟動(dòng)時(shí),我們的程序會(huì)被直接啟動(dòng)執(zhí)行,而不是以shell的方式,這樣我們的程序就能以PID=1的方式開始執(zhí)行了。

話題轉(zhuǎn)回來,我們開始執(zhí)行容器構(gòu)建操作,打包程序:

docker build -t registry.xiaozhou.net/graceful:latest .

打包過后的鏡像,才6MB左右:

λ Timothy [workspace/src/graceful] → docker images
REPOSITORY            TAG     IMAGE ID   CREATED    SIZE
registry.xiaozhou.net/graceful       latest    b2210a85ca55  20 hours ago  6.484 MB

啟動(dòng)并運(yùn)行容器:

λ Timothy [workspace/src/graceful] → docker run -d --name graceful b2210a85

查看容器運(yùn)行狀態(tài):

λ Timothy [workspace/src/graceful] → docker ps -a
CONTAINER ID  IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES
fd18eedafd16  b221    "/graceful"   3 seconds ago  Up 2 seconds       graceful

查看容器輸出,能看到程序已經(jīng)正常啟動(dòng):

λ Timothy [workspace/src/graceful] → docker logs graceful
Started...

接著我們要使用docker stop大法,看程序能否響應(yīng)SIGTERM信號:

λ Timothy [workspace/src/graceful] → docker stop graceful
graceful

最后,查看容器的日志,檢驗(yàn)輸出:

λ Timothy [workspace/src/graceful] → docker logs graceful
Started...
SIGTERM received!
Exiting...

總結(jié)

以上就是這篇文章的全部內(nèi)容了,用docker kill命令,可以簡單粗暴的終止docker容器中運(yùn)行的程序,但是想要優(yōu)雅的終止掉的話,我們需要使用docker stop命令,并且在程序中多花一些功夫來處理系統(tǒng)信號,這樣能保證程序不被粗暴的終止掉,從而實(shí)現(xiàn)gracefully shutdown。希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能有所幫助,如果有疑問大家可以留言交流。

相關(guān)文章

  • Docker nacos集群部署的實(shí)現(xiàn)

    Docker nacos集群部署的實(shí)現(xiàn)

    本文將深入探討如何使用Docker來部署Nacos集群,從而實(shí)現(xiàn)服務(wù)的快速擴(kuò)展、高可用性和可維護(hù)性,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • 詳解MAC OSX Docker開發(fā)環(huán)境搭建

    詳解MAC OSX Docker開發(fā)環(huán)境搭建

    本篇文章主要介紹了詳解MAC OSX Docker開發(fā)環(huán)境搭建,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • docker清理大殺器/docker的overlay文件占用磁盤太大的解決

    docker清理大殺器/docker的overlay文件占用磁盤太大的解決

    這篇文章主要介紹了docker清理大殺器/docker的overlay文件占用磁盤太大的解決操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • 使用Docker安裝Nginx并配置端口轉(zhuǎn)發(fā)問題及解決方法

    使用Docker安裝Nginx并配置端口轉(zhuǎn)發(fā)問題及解決方法

    這篇文章主要介紹了使用Docker安裝Nginx并配置端口轉(zhuǎn)發(fā),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • pipework docker無法使用ip netns命令解決辦法

    pipework docker無法使用ip netns命令解決辦法

    這篇文章主要介紹了pipework docker無法使用ip netns命令解決辦法的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Docker(黑馬spring?cloud筆記)詳解

    Docker(黑馬spring?cloud筆記)詳解

    這篇文章主要介紹了Docker(黑馬spring?cloud筆記)詳解,本文章內(nèi)容詳細(xì),具有很好的參考價(jià)值,希望對大家有所幫助,需要的朋友可以參考下<BR>
    2023-01-01
  • 在宿主機(jī)上執(zhí)行docker容器內(nèi)部的shell或程序方式

    在宿主機(jī)上執(zhí)行docker容器內(nèi)部的shell或程序方式

    這篇文章主要介紹了在宿主機(jī)上執(zhí)行docker容器內(nèi)部的shell或程序方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • 嵌入式移植docker報(bào)錯(cuò)問題(匯總)

    嵌入式移植docker報(bào)錯(cuò)問題(匯總)

    這篇文章主要介紹了嵌入式移植docker報(bào)錯(cuò)問題(匯總),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 基于docker搭建selenium分布式環(huán)境

    基于docker搭建selenium分布式環(huán)境

    這篇文章主要介紹了基于docker搭建selenium分布式環(huán)境,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • docker搭建etcd集群方式 bitnami/etcd

    docker搭建etcd集群方式 bitnami/etcd

    這篇文章主要介紹了docker搭建etcd集群方式 bitnami/etcd,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06

最新評論