這是本專欄的第二部分:容器篇,共 6 篇,幫助你們由淺入深地認識和掌握容器。這一篇和下一篇,我會爲你介紹容器生命週期管理相關的內容,帶你掌握容器生命週期。下面咱們一塊兒進入第一篇的內容,主要涉及容器狀態的變化。redis
在第一部分第二篇《Docker 的基本使用》中,我爲你介紹了 Docker 的基本使用,包括使用 docker run
啓動一個容器,使用 docker exec
進入一個正在運行的容器。那你有沒有考慮過容器的整個生命週期是什麼樣的?當咱們不使用它的時候,它是什麼狀態?docker
咱們啓動一個 Redis 的容器做爲示例。shell
(MoeLove) ➜ ~ docker run -d redis cf56a27e94f6142e7f69eb34de837b9bc091986006b1a7b563750317185376ea
使用 docker ps
命令查看容器當前的狀態,在輸出結果中包含一列 STATUS 狀態信息,咱們以此狀態做爲本篇的切入點。tcp
(MoeLove) ➜ ~ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cf56a27e94f6 redis "docker-entrypoint.s…" 5 seconds ago Up 4 seconds 6379/tcp cranky_yonath
使用 docker container create
或者 docker create
命令可建立一個處於 Created 狀態的容器,可是該容器並無真正運行,咱們是不能經過 docker exec 進入該容器的。學習
# 建立一個容器 (MoeLove) ➜ ~ docker container create redis 2017ecbb4da676069ce0f57583765a7f2562475bb0f7dfab12de8d1e0a93f322 # 查詢容器的狀態 (MoeLove) ➜ ~ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2017ecbb4da6 redis "docker-entrypoint.s…" 11 seconds ago Created condescending_cray # 嘗試進入容器內部 (MoeLove) ➜ ~ docker exec -it 2017ecbb4da6 sh Error response from daemon: Container 2017ecbb4da676069ce0f57583765a7f2562475bb0f7dfab12de8d1e0a93f322 is not running
雖然它沒有真正運行,可是它運行所需的相關文件卻已經都建立好了,而且你也能夠在 create 的時候給它傳遞各類可用於配置容器運行時的參數;這種方式一般是用來預配置容器,由於在執行完 docker create 命令後,會直接輸出容器的 ID。你能夠在一切準備就緒後,隨時啓動它。spa
另外一種使用場景是,你能夠用它來預掛載一個或多個存儲卷,後續其餘其餘容器可藉助此容器直接使用這些存儲卷(在存儲篇會詳細介紹)。code
前面已經提到了咱們可使用 docker create
命令建立一個處於 Created 狀態的容器,那咱們如何能讓它真正地開始運行呢?orm
# 建立容器 (MoeLove) ➜ ~ docker create redis b41a77be2fd9624824cc5b00b786f0236eba8d952f79b665a500fb7e649bb813 # 查詢容器的狀態 (MoeLove) ➜ ~ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b41a77be2fd9 redis "docker-entrypoint.s…" 2 seconds ago Created awesome_hofstadter
咱們可使用 docker start
命令,讓剛纔 Created 狀態的容器真正啓動(運行)。server
# 啓動該容器 (MoeLove) ➜ ~ docker start b41a77be2fd9 b41a77be2fd9 # 查詢容器的狀態 (MoeLove) ➜ ~ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b41a77be2fd9 redis "docker-entrypoint.s…" 33 seconds ago Up 3 seconds 6379/tcp awesome_hofstadter # 進入容器執行命令 (MoeLove) ➜ ~ docker exec b41a77be2fd9 redis-cli ping PONG
能夠看到容器此時已經處於正在運行的狀態了。那咱們是否還有其餘辦法能夠運行一個容器?blog
想必聰明的你已經想到了,咱們也可使用 docker run 命令直接運行一個容器。
# 在後臺運行一個容器 (MoeLove) ➜ ~ docker run -d redis b566506f243bf22275397d5d73194e72a94775a0c5673240f60ac30539c276e5 # 查詢容器狀態 (MoeLove) ➜ ~ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b566506f243b redis "docker-entrypoint.s…" 4 seconds ago Up 2 seconds 6379/tcp hopeful_chaum
docker run
是運行容器最經常使用的一個命令,由於咱們不少時候經過傳入參數的方式即可完成大多數預期的配置了,而且使用 docker run 也更加直接一些。
你可能也發現了 docker run -d
和 docker create
在命令執行後,都會將容器 ID 輸出,咱們能夠利用此 ID 完成後續對容器操做的需求。
容器在運行時,是否有辦法讓其暫停?或者讓它暫時不提供服務?
答案是使用 docker pause,咱們先來個實際例子再逐步進行解釋。
# 在後臺運行一個容器 (MoeLove) ➜ ~ docker run -d redis 074322e2467c1f280d8f1dfe90be45a1fa0673ec7f97220ec2c695e812179e30 # 查看容器狀態 (MoeLove) ➜ ~ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 074322e2467c redis "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 6379/tcp musing_mclean # 暫停容器 (MoeLove) ➜ ~ docker pause 074322e2467c 074322e2467c # 查看容器狀態 (MoeLove) ➜ ~ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 074322e2467c redis "docker-entrypoint.s…" 19 seconds ago Up 19 seconds (Paused) 6379/tcp musing_mclean
能夠看到容器已經處於 Paused 狀態,但請同時注意 Running (或者說 Up)與 Paused 並不互斥,或者說 Paused 是 Running 的一個分支。
# 嘗試進入容器執行命令 (MoeLove) ➜ ~ docker exec 074322e2467c redis-cli ping Error response from daemon: Container 074322e2467c is paused, unpause the container before exec
能夠看處處於 Paused 狀態的容器是沒法 docker exec
進入其中的。
咱們能夠查看一下當前容器進程的狀態:
# 使用 docker inspect 可獲取容器進程的 ID (MoeLove) ➜ ~ docker inspect --format "{{.State.Pid}}" 074322e2467c 9599 # 使用 ps 命令查看進程的狀態 (MoeLove) ➜ ~ ps -eo pid,state,command |grep 9599 |grep -v grep 9599 D redis-server *:6379
能夠看到當前進程狀態是 D,表示進程確實是在休眠狀態了。
那咱們是否有辦法讓它恢復正常呢?
固然有,使用 docker unpause
便可。
# 將容器從 Paused 狀態恢復 (MoeLove) ➜ ~ docker unpause 074322e2467c 074322e2467c # 進入容器內執行命令 (MoeLove) ➜ ~ docker exec 074322e2467c redis-cli ping PONG # 使用 ps 命令查看進程的狀態 (MoeLove) ➜ ~ ps -eo pid,state,command |grep 9599 |grep -v grep 9599 S redis-server *:6379
能夠看到已經恢復正常。
若是想要將一個運行中的容器中止該如何操做?
使用 docker stop
操做便可。咱們來看個具體例子:
# 啓動一個容器 (MoeLove) ➜ ~ docker run -d redis fffb13b75e22ca4eb035721df1660d25b9ef8379b8fd9a90c4a0258ea54c560c # 查詢容器狀態 (MoeLove) ➜ ~ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fffb13b75e22 redis "docker-entrypoint.s…" 2 seconds ago Up 1 second 6379/tcp jolly_cohen # 中止一個容器 # docker ps -ql 用於獲取最近一個容器的 ID (MoeLove) ➜ ~ docker stop $(docker ps -ql) fffb13b75e22 # 查詢容器狀態 (MoeLove) ➜ ~ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fffb13b75e22 redis "docker-entrypoint.s…" 17 seconds ago Exited (0) 2 seconds ago jolly_cohen
能夠看到使用 docker stop
能夠將一個容器從 Running 狀態變爲 Exited 狀態。通常狀況下處於 Exited 狀態的容器仍存在於機器上。
將容器從 Exited 狀態到 Running,想必你已經猜到了,使用 docker start 便可。
# 啓動一個容器 (MoeLove) ➜ ~ docker start $(docker ps -ql) fffb13b75e22 # 查詢容器狀態 (MoeLove) ➜ ~ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fffb13b75e22 redis "docker-entrypoint.s…" 36 seconds ago Up 2 seconds 6379/tcp jolly_cohen
本篇介紹了容器生命週期的基本管理操做,經過實際的實驗來加深印象。
這裏我總結了一張容器狀態的概覽圖,供你參考。
其中 Dead 和 Removing 狀態本篇未涉及,我將在下篇與你分享容器生命週期管理的剩餘部分。
本篇的內容相對簡單,但須要很是熟悉,建議多實踐,會更利於後續專欄內容的學習。