使容器在後臺運行
有些時候,需要讓容器在後臺運行而不是直接把“啓動命令”的結果輸出在當前宿主機下。此時,可以通過添加-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容器的幾種方法
- 使用ssh登陸進容器;
- 使用nsenter、nsinit等第三方工具;
- 使用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的主要區別
- attach直接進入容器“啓動命令”的終端,不會啓動新的進程;
- exec則是在容器中打開新的終端,並且可以啓動新的進程;
- 如果想直接在終端中查看容器“啓動命令”的輸出,用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)
來刪除所有處於終止狀態的容器。