本文只記錄 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的個人公共庫,類似於regsistory.example.com:5000則表示的是私服。


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 registry.domain.com:5000


# 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

registry.tp-link.net 也可以寫成IP,172.29.88.222。


在 repository 不存在的情況下,命令行下 push 上去的會為我們創建為私有庫,然而通過瀏覽器創建的默認為公共庫。

從 image 啟動一個 container(run)

docker run 命令首先會從特定的 image 創之上 create 一層可寫的 container ,然後通過 start 命令來啟動它。停止的 container 可以重新啟動並保留原來的修改。run 命令啟動參數有很多,以下是一些常規使用說明,更多部分請參考cnphp6.com/archives/248


當利用 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 ,就可以通過 localhost:80/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 github.com/creack/docke失敗。

給鏡像打上標籤(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 - 頂尖的容器私有雲。

推薦閱讀:

相關文章