Docker 常用管理命令
本文只記錄 docker 命令在大部分情境下的使用,如果想了解每一個選項的細節,請參考官方文檔,這裡只作為自己以後的備忘記錄下來。
根據自己的理解,總的來說分為以下幾種:
- 容器生命週期管理 — docker [run|start|stop|restart|kill|rm|pause|unpause]
- 容器操作運維 — docker [ps|inspect|top|attach|events|logs|wait|export|port]
- 容器rootfs命令 — docker [commit|cp|diff]
- 鏡像倉庫 — docker [login|pull|push|search]
- 本地鏡像管理 — docker [images|rmi|tag|build|history|save|import]
- 其他命令 — docker [info|version]
看一個變遷圖
列出機器上的鏡像(images)
# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 14.10 2185fd50e2ca 13 days ago 236.9 MB
…
其中我們可以根據REPOSITORY來判斷這個鏡像是來自哪個伺服器,如果沒有 / 則表示官方鏡像,類似於username/repos_name表示Github的個人公共庫,類似於http://regsistory.example.com:5000/repos_name則表示的是私服。
IMAGE ID列其實是縮寫,要顯示完整則帶上—no-trunc選項。
在docker index中搜索image(search)
Usage: docker search TERM
# docker search seanloNAME DESCRIPTION STARS OFFICIAL AUTOMATED
seanloook/centos6 seans docker repos 0
搜索的範圍是官方鏡像和所有個人公共鏡像。NAME列的 / 後面是倉庫的名字。
從docker registry server 中下拉 image 或 repository(pull)
Usage: docker pull [OPTIONS] NAME[:TAG]
# docker pull centos
上面的命令需要注意,在 docker v1.2 版本以前,會下載官方鏡像的 centos 倉庫裏的所有鏡像,而從 v.13 開始官方文檔裏的說明變了:will pull the centos:latest image, its intermediate layers and any aliases of the same id,也就是隻會下載tag為latest的鏡像(以及同一 images id 的其他 tag )。
也可以明確指定具體的鏡像:
# docker pull centos:centos6
當然也可以從某個人的公共倉庫(包括自己是私人倉庫)拉取,形如 docker pull username/repository<:tag_name> :
# docker pull seanlook/centos:centos6
如果你沒有網路,或者從其他私服獲取鏡像,形如 docker pull http://registry.domain.com:5000/repos:
# docker pull dl.dockerpool.com:5000/mongo:latest
推送一個 image 或 repository 到 registry(push)
與上面的 pull 對應,可以推送到 Docker Hub 的 Public、Private 以及私服,但不能推送到 Top Level Repository。
# docker push seanlook/mongo# docker push registry.tp-link.net:5000/mongo:2014-10-27
http://registry.tp-link.net 也可以寫成IP,172.29.88.222。
在 repository 不存在的情況下,命令行下 push 上去的會為我們創建為私有庫,然而通過瀏覽器創建的默認為公共庫。
從 image 啟動一個 container(run)
docker run 命令首先會從特定的 image 創之上 create 一層可寫的 container ,然後通過 start 命令來啟動它。停止的 container 可以重新啟動並保留原來的修改。run 命令啟動參數有很多,以下是一些常規使用說明,更多部分請參考http://www.cnphp6.com/archives/24899
當利用 docker run 來創建容器時,Docker 在後臺運行的標準操作包括:
- 檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載
- 利用鏡像創建並啟動一個容器
- 分配一個文件系統,並在只讀的鏡像層外面掛載一層可讀寫層
- 從宿主主機配置的網橋介面中橋接一個虛擬介面到容器中去
- 從地址池配置一個 ip 地址給容器
- 執行用戶指定的應用程序
- 執行完畢後容器被終止
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG…]
1. 使用 image 創建 container 並執行相應命令,然後停止
# docker run ubuntu echo "hello world"hello word
這是最簡單的方式,跟在本地直接執行 echo 『hello world』 幾乎感覺不出任何區別,而實際上它會從本地 ubuntu:latest 鏡像啟動到一個容器,並執行列印命令後退出(docker ps -l可查看)。需要注意的是,默認有一個 —rm=true 參數,即完成操作後停止容器並從文件系統移除。因為 Docker 的容器實在太輕量級了,很多時候用戶都是隨時刪除和新創建容器。
容器啟動後會自動隨機生成一個 CONTAINER ID,這個 ID 在後面 commit 命令後可以變為 IMAGE ID 。
使用 image 創建 container 並進入交互模式, login shell 是 /bin/bash
# docker run -i -t --name mytest centos:centos6 /bin/bashbash-4.1#
上面的 —name 參數可以指定啟動後的容器名字,如果不指定則 docker 會幫我們取一個名字。鏡像 centos:centos6 也可以用 IMAGE ID (68edf809afe7) 代替),並且會啟動一個偽終端,但通過 ps 或 top 命令我們卻只能看到一兩個進程,因為容器的核心是所執行的應用程序,所需要的資源都是應用程序運行所必需的,除此之外,並沒有其它的資源,可見 Docker 對資源的利用率極高。此時使用 exit 或 Ctrl+D 退出後,這個容器也就消失了(消失後的容器並沒有完全刪除?)。
那麼多個 TAG 不同而 IMAGE ID 相同的的鏡像究竟會運行以哪一個 TAG 啟動呢?
2. 運行出一個 container 放到後臺運行
# docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 2; done"
ae60c4b642058fefcc61ada85a610914bed9f5df0e2aa147100eab85cea785dc
它將直接把啟動的 container 掛起放在後臺運行(這才叫 saas ),並且會輸出一個 CONTAINER ID,通過 docker ps 可以看到這個容器的信息,可在 container 外面查看它的輸出 docker logs ae60c4b64205,也可以通過 docker attach ae60c4b64205 連接到這個正在運行的終端,此時在 Ctrl+C 退出 container 就消失了,按 ctrl-p ctrl-q 可以退出到宿主機,而保持 container 仍然在運行。
另外,如果 -d 啟動但後面的命令執行完就結束了,如 /bin/bash、echo test,則 container 做完該做的時候依然會終止。而且 -d 不能與 —rm 同時使用。
可以通過這種方式來運行 memcached、apache 等。
3. 映射 host 到 container 的埠和目錄
映射主機到容器的埠是很有用的,比如在 container 中運行 memcached ,埠為 11211,運行容器的 host 可以連接 container 的 internel_ip:11211 訪問,如果有從其他主機訪問 memcached 需求那就可以通過 -p 選項,形如 -p ,存在以下幾種寫法:
-p 11211:11211 這個即是默認情況下,綁定主機所有網卡(0.0.0.0)的11211埠到容器的11211埠上-p 127.0.0.1:11211:11211 只綁定localhost這個介面的11211埠-p 127.0.0.1::5000-p 127.0.0.1:80:8080
目錄映射其實是「綁定掛載」 host 的路徑到 container 的目錄,這對於內外傳送文件比較方便,在搭建私服那一節,為了避免私服 container 停止以後保存的 images 不被刪除,就要把提交的 images 保存到掛載的主機目錄下。使用比較簡單,-v ,綁定多個目錄時再加 -v。
-v /tmp/docker:/tmp/docker
另外在兩個 container 之間建立聯繫可用 —link,詳見高級部分或官方文檔。
下面是一個例子:
# docker run --name nginx_test > -v /tmp/docker:/usr/share/nginx/html:ro > -p 80:80 -d > nginx:1.7.6
在主機的 /tmp/docker 下建立 index.html ,就可以通過 http://localhost:80/ 或 http://host-ip:80 訪問了。
將一個 container 固化為一個新的 image(commit)
當我們在製作自己的鏡像的時候,會在 container 中安裝一些工具、修改配置,如果不做 commit 保存起來,那麼 container 停止以後再啟動,這些更改就消失了。
docker commit <container> [repo:tag]後面的 repo:tag 可選。
只能提交正在運行的 container,即通過 docker ps 可以看見的容器。
查看剛運行過的容器# docker ps -lCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c9fdf26326c9 nginx:1 nginx -g.. 3 hours ago Exited (0).. nginx_test啟動一個已存在的容器(run是從image新建容器後再啟動),以下也可以使用docker start nginx_test代替
[root@hostname docker]# docker start c9fdf26326c9c9fdf26326c9
docker run -i -t --sig-proxy=false 21ffe545748baf /bin/bash
nginx服務沒有啟動# docker commit -m "some tools installed" fcbd0a5348ca seanlook/ubuntu:14.10_tutorialfe022762070b09866eaab47bc943ccb796e53f3f416abf3f2327481b446a9503
-a 「[email protected]」
請注意,當你反覆去 commit 一個容器的時候,每次都會得到一個新的 IMAGE ID,假如後面的 repository:tag 沒有變,通過 docker images 可以看到,之前提交的那份鏡像的repository:tag 就會變成 :,所以盡量避免反覆提交。
另外,觀察以下幾點:
commit container 只會 pause 住容器,這是為了保證容器文件系統的一致性,但不會 stop 。如果你要對這個容器繼續做其他修改:
- 你可以重新提交得到新 image2,刪除次新的 image1
- 也可以關閉容器用新 image1 啟動,繼續修改,提交 image2 後刪除 image1
- 當然這樣會很痛苦,所以一般是採用 Dockerfile 來 build 得到最終 image
雖然產生了一個新的 image,並且你可以看到大小有 100MB,但從 commit 過程很快就可以知道實際上它並沒有獨立佔用 100MB 的硬碟空間,而只是在舊鏡像的基礎上修改,它們共享大部分公共的「片」。
開啟/停止/重啟 container(start/stop/restart)
容器可以通過 run 新建一個來運行,也可以重新 start 已經停止的 container ,但 start 不能夠再指定容器啟動時運行的指令,因為 docker 只能有一個前臺進程。
容器 stop(或 Ctrl+D)時,會在保存當前容器的狀態之後退出,下次 start 時保有上次關閉時更改。而且每次進入 attach 進去的界面是一樣的,與第一次 run 啟動或 commit 提交的時刻相同。CONTAINER_ID=$(docker start <containner_id>)
docker stop $CONTAINER_IDdocker restart $CONTAINER_ID
關於這幾個命令可以通過一個完整的實例使用:docker 如何創建一個運行後臺進程的容器並同時提供 shell 終端。
連接到正在運行中的 container(attach)
要 attach 上去的容器必須正在運行,可以同時連接上同一個 container 來共享屏幕(與screen 命令的 attach 類似)。
官方文檔中說 attach 後可以通過 CTRL-C 來 detach,但實際上經過我的測試,如果 container 當前在運行 bash,CTRL-C 自然是當前行的輸入,沒有退出;如果 container當前正在前臺運行進程,如輸出 nginx 的 access.log 日誌,CTRL-C 不僅會導致退出容器,而且還 stop 了。這不是我們想要的, detach 的意思按理應該是脫離容器終端,但容器依然運行。好在 attach 是可以帶上 —sig-proxy=false 來確保 CTRL-D 或 CTRL-C 不會關閉容器。
# docker attach --sig-proxy=false $CONTAINER_ID
查看 image 或 container 的底層信息(inspect)
inspect 的對象可以是 image、運行中的 container 和停止的 container。
刪除一個或多個 container、image(rm、rmi)
你可能在使用過程中會 build 或 commit 許多鏡像,無用的鏡像需要刪除。但刪除這些鏡像是有一些條件的:
- 同一個 IMAGE ID 可能會有多個 TAG(可能還在不同的倉庫),首先你要根據這些 image names 來刪除標籤,當刪除最後一個 tag 的時候就會自動刪除鏡像;
- 承上,如果要刪除的多個 IMAGE NAME 在同一個 REPOSITORY ,可以通過 docker rmi 來同時刪除剩下的 TAG;若在不同 Repo 則還是需要手動逐個刪除 TAG;
- 還存在由這個鏡像啟動的 container 時(即便已經停止),也無法刪除鏡像;
TO-DO
如何查看鏡像與容器的依存關係
刪除容器
docker rm
刪除所有停止的容器
docker rm $(docker ps -a -q)
刪除鏡像
docker rmi
下面是一個完整的示例:
# docker images <==ubuntu 13.10 195eb90b5349 4 months ago 184.6 MB
ubuntu saucy 195eb90b5349 4 months ago 184.6 MB
seanlook/ubuntu rm_test 195eb90b5349 4 months ago 184.6 MB
使用195eb90b5349啟動、停止一個容器後,刪除這個鏡像# docker rmi 195eb90b5349Error response from daemon: Conflict, cannot delete image 195eb90b5349 because it is tagged in multiple repositories, use -f to force2014/11/04 14:19:00 Error: failed to remove one or more images
刪除seanlook倉庫中的tag <==# docker rmi seanlook/ubuntu:rm_testUntagged: seanlook/ubuntu:rm_test
現在刪除鏡像,還會由於container的存在不能rmi# docker rmi 195eb90b5349Error response from daemon: Conflict, cannot delete 195eb90b5349 because the
container eef3648a6e77 is using it, use -f to force2014/11/04 14:24:15 Error: failed to remove one or more images
先刪除由這個鏡像啟動的容器 <==# docker rm eef3648a6e77刪除鏡像 <==# docker rmi 195eb90b5349Deleted: 195eb90b534950d334188c3627f860fbdf898e224d8a0a11ec54ff453175e081Deleted: 209ea56fda6dc2fb013e4d1e40cb678b2af91d1b54a71529f7df0bd867adc961Deleted: 0f4aac48388f5d65a725ccf8e7caada42f136026c566528a5ee9b02467dac90aDeleted: fae16849ebe23b48f2bedcc08aaabd45408c62b531ffd8d3088592043d5e7364Deleted: f127542f0b6191e99bb015b672f5cf48fa79d974784ac8090b11aeac184eaaff
注意,上面的刪除過程我所舉的例子比較特殊——鏡像被 tag 在多個倉庫,也有啟動過的容器。按照?指示的順序進行即可。
docker build 使用此配置生成新的image
build 命令可以從 Dockerfile 和上下文來創建鏡像:
docker build [OPTIONS] PATH | URL | -
上面的 PATH 或 URL 中的文件被稱作上下文,build image 的過程會先把這些文件傳送到 docker 的服務端來進行的。
如果 PATH 直接就是一個單獨的 Dockerfile 文件則可以不需要上下文;如果 URL 是一個 Git 倉庫地址,那麼創建 image 的過程中會自動 git clone 一份到本機的臨時目錄,它就成為了本次 build 的上下文。無論指定的 PATH 是什麼,Dockerfile 是至關重要的,請參考 Dockerfile Reference。
請看下面的例子:
上面的 PATH 為.,所以在當前目錄下的所有文件(不包括.dockerignore中的)將會被 tar 打包並傳送到 docker daemon(一般在本機),從輸出我們可以到 Sending build context…,最後有個 Removing intermediate container 的過程,可以通過 —rm=false 來保留容器。
TO-DO
docker build http://github.com/creack/docker-firefox失敗。
給鏡像打上標籤(tag)
tag 的作用主要有兩點:一是為鏡像起一個容易理解的名字,二是可以通過 docker tag 來重新指定鏡像的倉庫,這樣在 push 時自動提交到倉庫。
將同一IMAGE_ID的所有tag,合併為一個新的# docker tag 195eb90b5349 seanlook/ubuntu:rm_test新建一個tag,保留舊的那條記錄# docker tag Registry/Repos:Tag New_Registry/New_Repos:New_Tag
查看容器的信息 container(ps)
- docker ps命令可以查看容器的 CONTAINER ID、NAME、IMAGE NAME、埠開啟及綁定、容器啟動後執行的 COMMNAD 。經常通過 ps 來找到 CONTAINER_ID 。
- docker ps 默認顯示當前正在運行中的 container
- docker ps -a 查看包括已經停止的所有容器
- docker ps -l 顯示最新啟動的一個容器(包括已停止的)
查看容器中正在運行的進程(top)
容器運行時不一定有 /bin/bash 終端來交互執行 top 命令,查看 container 中正在運行的進程,況且還不一定有 top 命令,這是 docker top 就很有用了。實際上在 host 上使用 ps -ef|grep docker 也可以看到一組類似的進程信息,把 container 裏的進程看成是 host 上啟動 docker 的子進程就對了。
其他命令
docker 還有一些如 login、cp、logs、export、import、load、kill 等不是很常用的命令,比較簡單,請參考官網cSphere - 頂尖的容器私有雲。
推薦閱讀: