一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

信號的理念以及Dockerfile中ENTRYPOINT和CMD指令

馬哥Linux運維 ? 來源:CSDN技術(shù)社區(qū) ? 作者:CSDN技術(shù)社區(qū) ? 2022-06-12 16:42 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

最近把 Docker 官方的 Docker Reference 文檔又讀了一遍,發(fā)現(xiàn)有些細(xì)節(jié)深究起來,還是有很多可挖的。針對寫 Dockerfile ,大部分時候只要照葫蘆畫瓢,基本也不會有什么大的問題,但是如果再深入理解一下那就更有意思了。要說如何優(yōu)雅的關(guān)閉容器,那就不得不提到信號(Signal)的理念,以及 Dockerfile 中 ENTRYPOINT 和 CMD 指令了。在具體說優(yōu)雅關(guān)閉之前,先了解一下信號這個 Linux 中的基礎(chǔ)概念。

1 信號

信號是事件發(fā)生時對進程的通知機制,有時也稱之為軟件中斷。

信號有不同的類型,Linux 對標(biāo)準(zhǔn)信號的編號為 1~31,可以通過 kill -l 獲取信號名稱:
# kill -l 1) SIGHUP       2) SIGINT       3) SIGQUIT       4) SIGILL       5) SIGTRAP      6) SIGABRT       7) SIGBUS       8) SIGFPE       9) SIGKILL 10) SIGUSR1    11) SIGSEGV     12) SIGUSR2 13) SIGPIPE    14) SIGALRM     15) SIGTERM... ...
實際列出的信號超過了 31 個,有些是其它名稱的同義詞,有些則是定義但未使用的。以下介紹幾個常用的信號:
  • 1) SIGHUP當(dāng)終端斷開(掛機)時,將發(fā)送該信號給終端控制進程。SIGHUP 信號還可用于守護進程(比如,init 等)。許多守護進程會在收到 SIGHUP 信號時重新進行初始化并重讀配置文件。

  • 2) SIGINT當(dāng)用戶鍵入終端中斷字符(通常為Control-C) 時,終端驅(qū)動程序?qū)l(fā)送該信號給前臺進程組。該信號的默認(rèn)行為是終止進程。

  • 3) SIGQUIT當(dāng)用戶在鍵盤上鍵入退出字符(通常為Control-)時,該信號將發(fā)往前臺進程組。默認(rèn)情況下,該信號終止進程,并生成用于調(diào)試的核心轉(zhuǎn)儲文件。進程如果陷入無限循環(huán),或者不再響應(yīng)時,使用 SIGQUIT 信號就很合適。

  • 9) SIGKILL此信號為 “必殺(sure kill)” 信號,處理器程序無法將其阻塞、忽略或者捕獲,故而 “一擊必殺”,總能終止程序。

  • 15) SIGTERM這是用來終止進程的標(biāo)準(zhǔn)信號,也是kill、killall、pkill命令所發(fā)送的默認(rèn)信號。精心設(shè)計的應(yīng)用程序應(yīng)當(dāng)為 SIGTERM 信號設(shè)置處理器程序,以便其能夠預(yù)先清除臨時文件和釋放其它資源,從而全身而退。因此,總是應(yīng)該先嘗試使用SIGTERM信號來終止進程,而把SIGKILL作為最后手段,去對付那些不響應(yīng)SIGTERM信號的失控進程。

  • 20) SIGTSTP這是作業(yè)控制的停止信號,當(dāng)用戶在鍵盤上輸入掛起字符(通常為 Control-Z )時,將該信號給前臺進程組,使其停止運行。

值得注意的是,Control-D不會發(fā)起信號,它表示 EOF(End-Of-File),關(guān)閉標(biāo)準(zhǔn)輸入(stdin)管道(比如可以通過Control-D退出當(dāng)前 shell)。如果程序不讀取當(dāng)前輸入的話,是不受 Control-D 影響的。

程序可以針對信號捕捉,然后執(zhí)行相應(yīng)函數(shù):

51df66c8-de8c-11ec-ba43-dac502259ad0.png

以上知識大部分都來自 《Linux/UNIX 系統(tǒng)編程手冊》,想要了解更多的,可以查看該書上冊的 20、21、22 章節(jié)。

2 ENTRYPOINT 、 CMD

可能有人會問,說了半天,那信號和優(yōu)雅的關(guān)閉容器有半毛錢的關(guān)系???話說,這和錢確實沒關(guān)系,但是和如何優(yōu)雅關(guān)閉容器卻關(guān)系密切。接著說 Dockerfile 中的 ENTRYPOINT 和 CMD 指令,它們的主要功能是指定容器啟動時執(zhí)行的程序。

CMD有三種格式:

  • CMD ["executable","param1","param2"](exec 格式, 推薦使用這種格式)

  • CMD ["param1","param2"](作為 ENTRYPOINT 指令參數(shù))

  • CMD command param1 param2(shell 格式,默認(rèn) /bin/sh -c )

ENTRYPOINT有兩種格式:

  • ENTRYPOINT ["executable", "param1", "param2"](exec 格式,推薦優(yōu)先使用這種格式)

  • ENTRYPOINT command param1 param2(shell 格式)

其中,不管你Dockerfile用其中哪個指令,兩個指令都推薦使用 exec 格式,而不是 shell 格式。原因就是因為使用 shell 格式之后,程序會以/bin/sh -c的子命令啟動,并且 shell 格式下不會傳遞任何信號給程序。這也就導(dǎo)致,在docker stop容器的時候,以這種格式運行的程序捕捉不到發(fā)送的信號,也就談不上優(yōu)雅的關(guān)閉了。

?  ~ 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停掉容器的時候,默認(rèn)會發(fā)送一個SIGTERM的信號,默認(rèn) 10s 后容器沒有停止的話,就SIGKILL強制停止容器。通過-t選項可以設(shè)置等待時間。
?  ~ 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 kill-s選項還可以指定給容器發(fā)送的信號。

所以,說了那么多,只要Dockerfile中通過 exec 格式執(zhí)行容器啟動命令就相安無事了?那當(dāng)然是,沒有那么簡單的了,接下來我們通過實例來看看具體的效果是怎么樣的。

3 實例

通過 Go 寫一個簡單的信號處理器:

?  ~ cat signals.gopackage main
import (    "fmt"    "os"    "os/signal"    "syscall")
func main() {    sigs := make(chan os.Signal, 1)    done := make(chan bool, 1)
    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
    go func() {        sig := <-sigs        fmt.Println()        fmt.Println(sig)        done <- true    }()
    fmt.Println("awaiting signal")    <-done    fmt.Println("exiting")}

3.1 實例 1

?  ~ GOOS=linux GOARCH=amd64 go build signals.go?  ~ lsDockerfile signals    signals.go?  ~ cat DockerfileFROM busybox
COPY signals /signals
CMD ["/signals"]    # exec 格式執(zhí)行?  ~ docker build -t signals .
通過 tmux 開啟兩個面板,一個運行容器,一個執(zhí)行 docker stop :
?  ~ docker run -it --rm --name signals signalsawaiting signal
terminatedexiting
?  ~ time docker stop signalssignalsdocker stop signals  0.01s user 0.02s system 4% cpu 0.732 total?  ~

可以發(fā)現(xiàn),容器停止之前,程序接收到信號并輸出相應(yīng)信息,并且停止總耗時為 0.732 s,達(dá)到了優(yōu)雅的效果。

修改 Dockerfile 中 CMD 執(zhí)行格式,執(zhí)行相同操作:

?  ~ cat DockerfileFROM busybox
COPY signals /signals
CMD /signals        # shell 格式執(zhí)行?  ~ docker build -t signals .
?  ~ docker run -it --rm --name signals signalsawaiting signal?  ~
?  ~ time docker stop signalssignalsdocker stop signals  0.01s user 0.01s system 0% cpu 10.719 total

通過 shell 格式之后,可以發(fā)現(xiàn)容器停止之前,程序并未接收到任何信號,并且停止時間為 10.719s,說明該容器是被強制停止的。

結(jié)論很明顯,為了優(yōu)雅的退出容器,我們應(yīng)該采用 exec 這種格式。

3.2 實例 2

通過實例 1 我們都會在 Dockerfile 中都會通過 exec 這種格式來執(zhí)行程序了,那如果執(zhí)行的程序本身也是一個 shell 腳本呢?
?  ~ lsDockerfile signals    signals.go start.sh?  ~ cat DockerfileFROM busybox
COPY signals /signalsCOPY start.sh /start.sh     # 引入 shell 腳本啟動
CMD ["/start.sh"]?  ~ cat start.sh#!/bin/sh
/signals?  ~

測試依然引用實例 1 中的方法:

?  ~ docker run -it --rm --name signals signalsawaiting signal?  ~
?  ~ time docker stop signalssignalsdocker stop signals  0.01s user 0.02s system 0% cpu 10.765 total?  ~
可以發(fā)現(xiàn),即使 Dockerfile 中的 CMD 指令使用的是 exec 格式,容器中的程序依然沒有接收到信號,最后被強制關(guān)閉。因為 shell 腳本中執(zhí)行的原因,導(dǎo)致信號依然沒有被傳遞,我們需要針對 shell 腳本做一些改造:
?  ~ cat start.sh#!/bin/sh
exec /signals   # 加入 exec 執(zhí)行?  ~ docker build -t signals .
?  ~ docker run -it --rm --name signals signalsawaiting signal
terminatedexiting
?  ~ time docker stop signalssignalsdocker stop signals  0.02s user 0.02s system 4% cpu 0.744 total?  ~

可以看到,加入 exec 命令之后,程序又可以接收到信號正常退出了。當(dāng)然,如果你 Dockerfile 中的 CMD 是以 shell 格式運行的,即使啟動腳本中加入 exec 也是無效的。再者,如果你的程序本身不能針對信號做一些處理,也就談不上優(yōu)雅關(guān)閉了。

原文標(biāo)題:如何優(yōu)雅的關(guān)閉容器

文章出處:【微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11511

    瀏覽量

    213879
  • 信號
    +關(guān)注

    關(guān)注

    11

    文章

    2853

    瀏覽量

    78310
  • 容器
    +關(guān)注

    關(guān)注

    0

    文章

    511

    瀏覽量

    22459
  • Docker
    +關(guān)注

    關(guān)注

    0

    文章

    515

    瀏覽量

    12975

原文標(biāo)題:如何優(yōu)雅的關(guān)閉容器

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    11.Dockerfile配置之CMDENTRYPOINT

    前端編程語言
    電子學(xué)習(xí)
    發(fā)布于 :2023年02月01日 21:52:51

    Dockerfile的最佳實踐

    ”微服務(wù)一條龍“最佳指南-“最佳實踐”篇:Dockerfile
    發(fā)表于 07-11 16:22

    Dockerfile使用規(guī)則

    Dockerfile編寫規(guī)范
    發(fā)表于 08-12 14:30

    一文詳解DockerFile基礎(chǔ)知識

    # 當(dāng)構(gòu)建一個被繼承Dockerfile 這個時候運行ONBUILD指定,觸發(fā)指令COPY # 將文件拷貝到鏡像ENV # 構(gòu)建的時候設(shè)置環(huán)境變量構(gòu)建自己的Centos鏡像Docker hub
    發(fā)表于 09-15 15:54

    DSP28335—CMD文件的各個段解釋

    cmd以下代碼如何解釋?請看本文
    發(fā)表于 12-26 17:26 ?18次下載

    系統(tǒng)之上的進程級別虛擬化技術(shù)——Docker

    的正常代碼的區(qū)別。而且后者在一個 Dockerfile 文件只能有一個存在。CMD/ENTRYPOINT 的區(qū)別除了在寫法上有區(qū)別之外,還有在docker run命令后增加
    的頭像 發(fā)表于 05-02 14:55 ?5256次閱讀
    系統(tǒng)之上的進程級別虛擬化技術(shù)——Docker

    全面詳解Dockerfile文件

    Docker 可以通過讀取 Dockerfile 指令自動構(gòu)建鏡像。Dockerfile 是一個文本文檔,其中包含了用戶創(chuàng)建鏡像的所有命令和說明。 一、 變量 變量用
    的頭像 發(fā)表于 09-22 15:38 ?2122次閱讀

    鏡像構(gòu)建Dockerfile的介紹

    Dockerfile 是一個用來構(gòu)建鏡像的文本文件,文本內(nèi)容包含了一條條構(gòu)建鏡像所需的指令和說明。
    的頭像 發(fā)表于 09-06 09:36 ?1458次閱讀

    Dockerfile的最佳實踐

    隨著應(yīng)用的容器化、上云后,將伴隨著 Docker 鏡像的構(gòu)建,構(gòu)建 Docker 鏡像成為了最基本的一步,其中 Dockerfile 便是用來構(gòu)建鏡像的一種文本文件,鏡像的優(yōu)劣全靠
    的頭像 發(fā)表于 01-20 10:59 ?1287次閱讀
    <b class='flag-5'>Dockerfile</b>的最佳實踐

    使用匿名管道技術(shù)獲取CMD命令的執(zhí)行結(jié)果

    遠(yuǎn)程 CMD 是指惡意程序接收到控制端發(fā)送的 CMD 指令后,在本地執(zhí)行 CMD 命令,并將執(zhí)行結(jié)果回傳至控制端。本文將演示使用匿名管道技術(shù)獲取 C
    的頭像 發(fā)表于 04-03 18:04 ?4738次閱讀

    Dockerfile定義Docker鏡像的構(gòu)建過程

    了解Dockerfile Dockerfile 是一個文本文件,用于定義 Docker 鏡像的構(gòu)建過程。它以指令的形式描述了如何構(gòu)建鏡像,從基礎(chǔ)鏡像開始逐步添加配置、文件和依賴,最終形成我們所需
    的頭像 發(fā)表于 09-30 10:22 ?2928次閱讀

    如何使用dockerfile創(chuàng)建鏡像

    如何使用Dockerfile創(chuàng)建鏡像,包括Dockerfile的語法和常用指令,以及具體操作步驟。 編寫Dockerfile
    的頭像 發(fā)表于 11-23 09:52 ?1111次閱讀

    提升DevOps效率,從基礎(chǔ)到進階的Dockerfile編寫技巧

    目錄 Dockerfile 基本結(jié)構(gòu) 指令 創(chuàng)建鏡像(centos版) 創(chuàng)建鏡像(alpine版) 基本結(jié)構(gòu) Dockerfile 是一個文本格式的配置文件,用戶可以使用 Dockerfile
    的頭像 發(fā)表于 11-26 09:44 ?395次閱讀
    提升DevOps效率,從基礎(chǔ)到進階的<b class='flag-5'>Dockerfile</b>編寫技巧

    Dockerfile鏡像制作與Docker-Compose容器編排

    Dockerfile鏡像制作 docker/podman, 鏡像是容器的基礎(chǔ),每次執(zhí)行docker run的時候都會指定哪個基本鏡像作為容器運行的基礎(chǔ)。我們之前的docker的操作都是使用來
    的頭像 發(fā)表于 01-07 11:01 ?787次閱讀
    <b class='flag-5'>Dockerfile</b>鏡像制作與Docker-Compose容器編排

    基于Docker鏡像逆向生成Dockerfile

    在本文中, 我們將通過理解Docker鏡像如何存儲數(shù)據(jù), 以及如何使用工具查看鏡像方方面面的信息來逆向工程一個Docker鏡像; 以及如何使用Python的Docker API來構(gòu)建一個類似Dedockify的工具來創(chuàng)建Dockerfi
    的頭像 發(fā)表于 03-10 09:45 ?610次閱讀
    基于Docker鏡像逆向生成<b class='flag-5'>Dockerfile</b>