Docker學習筆記四:進入容器&刪除容器

使容器在後臺運行

有些時候,需要讓容器在後臺運行而不是直接把“啓動命令”的結果輸出在當前宿主機下。此時,可以通過添加-d參數來實現。

舉個例子,假如不使用-d參數執行下面這條命令:

docker run ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

那麼會一直在控制檯輸出hello world,如下所示:

docker run ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
hello world
hello world
hello world
...

但是如果使用了-d參數,此時容器會在後臺運行並且不會將輸出結果輸出到控制檯。如下所示:

docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
ccd644424bffed71747e2a36977d70745cc211e7dac71006437ca52914c1b743

進入一個docker容器的幾種方法

  1. 使用ssh登陸進容器;
  2. 使用nsenter、nsinit等第三方工具;
  3. 使用docker本身提供的工具。

爲什麼不使用SSH進入Docker
oschina文章
使用nsenter進入Docker容器
關於什麼是nsenter請參考如下文章:
Github–nsenter介紹

在瞭解了什麼是nsenter之後,系統默認將我們需要的nsenter安裝到主機中

如果沒有安裝的話,按下面步驟安裝即可(注意是主機而非容器或鏡像)

具體的安裝命令如下:

$ wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz  
$ tar -xzvf util-linux-2.24.tar.gz  
$ cd util-linux-2.24/  
$ ./configure --without-ncurses  
$ make nsenter  
$ sudo cp nsenter /usr/local/bin

nsenter可以訪問另一個進程的名稱空間。所以爲了連接到某個容器我們還需要獲取該容器的第一個進程的PID。可以使用docker inspect命令來拿到該PID。
docker inspect命令使用如下:

$ sudo docker inspect --help   

inspect命令可以分層級顯示一個鏡像或容器的信息。比如我們當前有一個正在運行的容器

如果要顯示該容器第一個進行的PID可以使用如下方式

$ sudo docker inspect -f {{.State.Pid}} 44fc0f0582d9 

在拿到該進程PID之後我們就可以使用nsenter命令訪問該容器了。

$ sudo nsenter --target 3326 --mount --uts --ipc --net --pid  

其中的3326即剛纔拿到的進程的PID

Docker目前主要提供了docker exec和docker attach兩個命令。

docker attach進入一個容器內部

docker attach containerId|containerName

如下所示,首先使用docker run創建了一個容器,爲其分配了僞終端,打開了它的標準輸入流,並且讓它在後臺執行。

然後使用docker attach進入了該容器內部,實際上就是進入容器“啓動命令”的終端。(containerId可以不用輸全,只要能代表容器即可。例如下面的0539就是代表容器ID以0539開頭的容器,一般情況下,前4位就能唯一標識一個容器了)

[root@localhost Desktop]# docker run -itd ubuntu /bin/bash
0539852938cdb9538f67750d07ed8c7fa072de742d5c0c02128576f2d227ec46
[root@localhost Desktop]# docker attach 0539
root@0539852938cd:/# 
root@0539852938cd:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
root@0539852938cd:/# exit
exit
[root@localhost Desktop]#

docker exec進入一個容器內部

 docker exec [options] containerName|containerId command [arg]

如下所示,首先使用docker run創建了一個容器,並使它在後臺運行。

docker exec命令可以在一個運行的容器內部執行一條命令,例如下圖中執行docker exec aec0 mkdir dir1後,就在容器中創建了一個dir1的文件夾。除此以外,還可以在容器中啓動一個新的bash,例如下圖執行了docker exec -it aec0 /bin/bash,在容器內部啓動了一個新的bash終端,並使用-it爲其分配一個僞終端綁定到標準輸出上。

[root@localhost Desktop]# docker run -itd ubuntu /bin/bash
aec040300549f95a8c4b37fecd3059122f08cb5422673640bd0bd9e641d0644c
[root@localhost Desktop]# docker exec aec0 mkdir dir1
[root@localhost Desktop]# docker exec -it aec0 /bin/bash
root@aec040300549:/# ls
bin   dev   etc   lib    media  opt   root  sbin  sys  usr
boot  dir1  home  lib64  mnt    proc  run   srv   tmp  var
root@aec040300549:/# exit
exit
[root@localhost Desktop]# 

attach與exec的比較

使用docker run -d ubuntu "while true ; do sleep 1 ; echo hello; done"創建並在後臺啓動容器,每隔一秒打印一個hello。

[root@localhost Desktop]# docker run -d ubuntu /bin/sh -c "while true ; do sleep 1 ; echo hello; done"
a695e721e324f11cc958867d13c9c6707018e359c747ba103554d4d8e9e7750f

使用docker attach 5719進入容器內部後,會在控制檯每隔一秒打印了一個hello。

[root@localhost Desktop]# docker attach a695
hello
hello
...

但是使用docker exec –it 5719 /bin/bash進入容器後,並沒有打印“hello”,因爲docker exec執行後,在容器中打開一個新的終端,該終端與“啓動命令”的終端不是同一個。

[root@localhost Desktop]# docker exec -it a695 /bin/bash
root@a695e721e324:/#

attach與exec的主要區別

  1. attach直接進入容器“啓動命令”的終端,不會啓動新的進程;
  2. exec則是在容器中打開新的終端,並且可以啓動新的進程;
  3. 如果想直接在終端中查看容器“啓動命令”的輸出,用attach;其他情況使用exec。

刪除容器

刪除一個處於終止狀態的容器

我們使用docker rm containName|containId來刪除一個處於終止狀態的容器。 請留意,在不加任何參數的情況下,docker rm只能刪除處於終止狀態的容器。
docker rm實例
執行docker ps –a查看所有的容器,如下圖所示,其中容器名爲dist\fracted_wright的容器STATUS對應爲Exited,也就意味着它處於終止狀態。

[root@localhost Desktop]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                     PORTS               NAMES
21d9ad4beeec        busybox             "echo hello"        6 seconds ago        Exited (0) 5 seconds ago                       dist\fracted_wright
70b35ab2219f        ubuntu              "/bin/bash"         28 seconds ago       Up 20 seconds                                  container1
e70fa4917b69        ubuntu              "/bin/bash"     

執行docker rm 21d9,我們可以將該容器刪除,再次執行docker ps –a,如下圖所以,從圖中可以看出,該容器已經被不存在了,說明刪除成功了。

[root@localhost Desktop]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
70b35ab2219f        ubuntu              "/bin/bash"         About a minute ago   Up About a minute                       container1
e70fa4917b69        ubuntu              "/bin/bash"         2 minutes ago        Up 2 minutes                            admiring_heise

使用docker rm 刪除一個正在運行的容器,失敗了
從上圖我們可以看到containId=70b35ab2219f 的容器正在運行狀態,當我執行docker rm 70b3,如下圖所示,提示不能刪除一個正在運行的容器。從下圖可以看出該容器並沒有被刪除。

[root@localhost Desktop]# docker rm 70b3
Error response from daemon: You cannot remove a running container 70b35ab2219f9c610053ffc65b0a961bd2bc87b6a849fe52253da5dffdc80508. Stop the container before attempting removal or use -f

刪除一個正在運行的容器

刪除一個正在運行的容器,有兩種方式:

  • 第一種,先執行docker stop停止該容器,然後使用docker rm刪除掉;
  • 第二種,執行docker rm –f命令,強制刪除。
[root@localhost Desktop]# docker stop 70b3
70b3
[root@localhost Desktop]# docker rm 70b3
70b3
[root@localhost Desktop]# docker rm -f e70f
e70f
[root@localhost Desktop]# docker ps -a
CONTAINER ID        IMAGE               COMMAND     

刪除所有處於終止狀態的容器

可以執行docker rm $(docker ps -a -q),用來刪除所有處於終止狀態的容器。

我們知道docker ps –a命令可以查看所有容器的信息。而docker ps –a –q只查看所有容器的containerId。在Linux中,將命令放在$()中,會執行命令並返回命令的執行結果。因此$( docker ps -a -q)會返回所有容器的container id,而docker rm只能幹掉終止的容器,而如果用docker rm刪除正在運行的容器時,將不能刪除掉。所以可以使用docker rm $(docker ps -a -q)來刪除所有處於終止狀態的容器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章