如何從單獨的容器調試運行中的Docker容器

容器很是適合封裝軟件,可是有時一味地改造容器鏡像以使其儘量小時,您可能走得太遠。咱們須要在「簡潔」的鏡像和沒法調試的鏡像之間找到很好的平衡。docker

看到人們調試正在運行的容器的正常方法是docker exec -it $ CONTAINER sh並根據須要在容器中安裝調試工具。可是,若是您的容器沒有/ bin / sh怎麼辦?若是沒有包管理器怎麼辦?您可使用docker cp將實用程序複製到容器中,而後將exec複製到正在運行的容器中,但這也很麻煩。shell

所以,一個朋友最近沒有詢問如何從容器中進行調試,而是詢問如何從其餘容器中進行調試。我沒有那麼聰明,因此我在網上問了不少聰明的人,並獲得了很好的答覆。bash

咱們建立一個只有caddy的精簡容器。網絡

首先下載/提取caddy二進制文件curl

$: curl https://getcaddy.com | bash -s personal && mv /usr/local/bin/caddy .

而後建立一個Dockerfile將二進制文件複製到臨時容器中。工具

FROM scratch
ADD caddy /

構建容器並運行caddyui

$: docker build -t caddy .
<output trimmed>

如今運行這個容器url

$: docker run -d --name caddy -p 2015:2015 caddy /caddy

如今caddy正在運行發佈端口2015(目前提供404頁面,由於沒有內容,但沒有關係)。您如何調試容器?caddy並無bug,這不是您所須要的。 :)但出於假設的緣由。調試

許多人建議使用--link,但這隻會將容器放在同一網絡上。不是相同的名稱空間,而是在同一虛擬網絡上彼此鏈接。code

$: docker run -it --rm --link caddy:caddy alpine sh
/ # ping caddy -c 1
PING caddy (172.30.238.2): 56 data bytes
64 bytes from 172.30.238.2: seq=0 ttl=64 time=0.075 ms
/ # ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 sh
    8 root       0:00 ps aux

其餘人建議使用--volumes-from,但這不能使您將工具安裝到現有的運行容器中,除非該運行容器正在導出卷而且該卷已經在$ PATH中。

相反,咱們將使用所需的全部工具(在本例中爲strace)構建一個單獨的容器,並在與原始容器相同的pid和網絡名稱空間中運行它。

首先使用strace建立一個調試容器

FROM alpine
RUN apk update && apk add strace
CMD ["strace", "-p", "1"]

構建容器

$: docker build -t strace .
<output trimmed>

如今,在相同的pid和網絡名稱空間中運行strace容器。

$: docker run -t --pid=container:caddy \
  --net=container:caddy \
  --cap-add sys_admin \
  --cap-add sys_ptrace \
  strace
strace: Process 1 attached
futex(0xd72e90, FUTEX_WAIT, 0, NULL

附加的strace到caddy進程,並在執行時跟隨它。

很好,但咱們也可使用遠程容器的根文件系統(不是不少)。此次,咱們將使用alpine 鏡像並再次在相同的pid和網絡名稱空間中啓動一個shell。

$: docker run -it --pid=container:caddy \
  --net=container:caddy \
  --cap-add sys_admin \
  alpine sh

咱們如今能夠看到caddy 運行以下:

/ # ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 /caddy
   13 root       0:00 strace -p 1
   34 root       0:00 sh
   40 root       0:00 ps aux

caddy容器文件系統位於/ proc / 1 / root中

/ # ls -l /proc/1/root/caddy 
-rwxr-xr-x    1 root     root      16099400 Jan 24 15:30 /proc/1/root/caddy

將此容器附加到原始容器後,咱們能夠進行更多調試。您仍然能夠調試網絡,但請確保使用localhost,由於新的sh進程正在同一網絡名稱空間中運行

/ # apk update && apk add curl lsof
/ # curl localhost:2015
404 Not Found
/ # lsof -i TCP
COMMAND PID USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
caddy     1 root    4u  IPv6 330044347      0t0  TCP *:2015 (LISTEN)

您全部的標準調試工具都應在第二個容器中運行,而不會污染原始容器。若是遇到錯誤,請確保檢查內核權限(注意strace須要如何--cap-add sys_ptrace但sh容器僅須要sys_admin)

這顯然對於go容器或您只須要在不更改容器自己的狀況下將一些額外的調試工具引入的任何其餘容器頗有用。

相關文章
相關標籤/搜索