
前言
本文主要對Docker的三大組件鏡像、容器、倉庫基礎『常用』命令進行整理。
依據命令的用途對其進行分類(來源:《Docker:容器與容器雲(第2版)》):

從docker命令使用出發,梳理出如圖所示的命令結構圖:

一、Docker鏡像
操作系統分為 內核 和 用戶空間。對於 Linux 而言,內核啟動后,會掛載 root 文件系統為其提供用戶空間支持。而 Docker 鏡像(Image),就相當於是一個 root 文件系統。比如官方鏡像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系統的 root 文件系統。
Docker 鏡像 是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時准備的一些配置參數(如匿名卷、環境變量、用戶等)。鏡像 不包含 任何動態數據,其內容在構建之后也不會被改變。
1、從倉庫獲取鏡像
從 Docker 鏡像倉庫獲取鏡像的命令是 docker pull。其命令格式為:
$ docker pull [選項] [Docker Registry 地址[:端口號]/]倉庫名[:標簽]
通過 docker pull --help 命令來看一下具體的『選項』命令:
$ docker pull --help
Usage: docker pull [OPTIONS] NAME[:TAG|@DIGEST]
Pull an image or a repository from a registry
Options:
-a, --all-tags Download all tagged images in the repository
--disable-content-trust Skip image verification (default true)
--platform string Set platform if server is multi-platform capable
-q, --quiet Suppress verbose output
示例:
# 從官方倉庫獲取ubuntu18.04的鏡像
$ docker pull ubuntu:18.04
# 從網易鏡像倉庫獲取mysql最新版本鏡像
$ docker pull hub.c.163.com/library/mysql:latest
2、列出鏡像
要想列出本地已經下載下來的鏡像,可以使用 docker image ls 或 docker images命令。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 5f515359c7f8 5 days ago 183 MB
nginx latest 05a60462f8ba 5 days ago 181 MB
mongo 3.2 fe9198c04d62 5 days ago 342 MB
<none> <none> 00285df0df87 5 days ago 342 MB
ubuntu 18.04 329ed837d508 3 days ago 63.3MB
ubuntu bionic 329ed837d508 3 days ago 63.3MB
列表包含了 倉庫名、標簽、鏡像 ID、創建時間 以及 所占用的空間。
鏡像 ID 則是鏡像的唯一標識,一個鏡像可以對應多個 標簽。因此,在上面的例子中,可以看到 ubuntu:18.04 和 ubuntu:bionic 擁有相同的 ID,因為它們對應的是同一個鏡像。
鏡像體積
仔細觀察,注意到, docker images 這里標識的所占用空間和在 Docker Hub 上看到的鏡像大小不同。比如,ubuntu:18.04 鏡像大小,在這里是 63.3MB,但是在 Docker Hub 顯示的卻是 25.47 MB。
因為倉庫中的鏡像是壓縮過的,在上傳和下載過程中都是保持壓縮狀態,節省網絡傳輸流量。
而本地通過 docker images 看到的是展開后的體積。
虛懸鏡像
docker images 列出來的鏡像,發現有一個特殊的鏡像,這個鏡像既沒有倉庫名,也沒有標簽,均為 <none>
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 00285df0df87 5 days ago 342 MB
這個鏡像原本是有鏡像名和標簽的,原來為 mongo:3.2,隨着官方鏡像維護,發布了新版本后,重新 docker pull mongo:3.2 時,mongo:3.2 這個鏡像名被轉移到了新下載的鏡像身上,而舊的鏡像上的這個名稱則被取消,從而成為了 <none>。除了 docker pull 可能導致這種情況,docker build 也同樣可以導致這種現象。
由於新舊鏡像同名,舊鏡像名稱被取消,從而出現倉庫名、標簽均為 <none> 的鏡像。這類無標簽鏡像也被稱為 虛懸鏡像(dangling image) ,可以用下面的命令專門顯示這類鏡像:
$ docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 00285df0df87 5 days ago 342 MB
一般來說,虛懸鏡像已經失去了存在的價值,是可以隨意刪除的,可以用下面的命令刪除。
$ docker image prune
中間層鏡像
為了加速鏡像構建、重復利用資源,Docker 會利用 中間層鏡像。列出中間層鏡像:
$ docker image ls -a
這樣會看到很多無標簽的鏡像,與之前的虛懸鏡像不同,這些無標簽的鏡像很多都是中間層鏡像,是其它鏡像所依賴的鏡像。
不應該刪除,被其他鏡像所依賴;不用管,刪除依賴對象后會連帶刪除。
列出部分鏡像
根據倉庫名列出鏡像:
$ docker images ubuntu
指定倉庫名和標簽
$ docker images ubuntu:18.04
過濾器參數 --filter,簡寫 -f ,示例:
# 列出虛懸鏡像
$ docker images -f dangling=true
# mongo:3.2之后建立的鏡像
$ docker images -f since=mongo:3.2
# mongo:3.2之前建立的鏡像
$ docker images -f before=mongo:3.2
# 通過lable過濾
$ docker images -f label=com.example.version=0.1
以特定格式顯示
僅列出ID列,-q 參數
$ docker images -q
另外一些時候,我們可能只是對表格的結構不滿意,希望自己組織列;或者不希望有標題,這樣方便其它程序解析結果等,這就用到了 Go 的模板語法。
$ docker image ls --format "{{.ID}}: {{.Repository}}"
5f515359c7f8: redis
05a60462f8ba: nginx
fe9198c04d62: mongo
00285df0df87: <none>
329ed837d508: ubuntu
329ed837d508: ubuntu
$ docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID REPOSITORY TAG
5f515359c7f8 redis latest
05a60462f8ba nginx latest
fe9198c04d62 mongo 3.2
00285df0df87 <none> <none>
329ed837d508 ubuntu 18.04
329ed837d508 ubuntu bionic
3、刪除鏡像
要刪除本地的鏡像,可以使用 docker image rm 命令,其格式為:
$ docker image rm [選項] <鏡像1> [<鏡像2> ...]
其中,<鏡像> 可以是 鏡像短 ID、鏡像長 ID、鏡像名 或者 鏡像摘要。
示例:比如我們有如下鏡像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 0584b3d2cf6d 3 weeks ago 196.5 MB
redis alpine 501ad78535f0 3 weeks ago 21.03 MB
docker latest cf693ec9b5c7 3 weeks ago 105.1 MB
nginx latest e43d811ce2f4 5 weeks ago 181.5 MB
刪除
# 長ID
$ docker image rm 501ad78535f0
# 短ID,即只輸入部分ID 一般取前3個字符以上,只要足夠區分於別的鏡像就可以了。
$ docker image rm 501
# 鏡像名刪除
$ docker image rm centos
# 鏡像摘要刪除
$ docker images --digests
$ docker image rm node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228
# 用docker images命令配合
$ docker image rm $(docker images -q redis)
# 刪除mongo:3.2之前創建的鏡像
$ docker image rm $(docker images -q -f before=mongo:3.2)
4、構建鏡像
鏈接(下篇整理通過Dockerfile構建鏡像)--待完善
二、Docker容器
簡單的說,容器是獨立運行的一個或一組應用,以及它們的運行態環境。對應的,虛擬機可以理解為模擬運行的一整套操作系統(提供了運行態環境和其他系統環境)和跑在上面的應用。
1、啟動容器
新建啟動
$ docker run ubuntu:18.04 /bin/echo 'Hello world'
啟動一個 bash 終端,允許用戶進行交互.其中,-t 選項讓Docker分配一個偽終端(pseudo-tty)並綁定到容器的標准輸入上, -i 則讓容器的標准輸入保持打開。
$ docker run -t -i ubuntu:18.04 /bin/bash
當利用 docker run 來創建容器時,Docker 在后台運行的標准操作包括:
- 檢查本地是否存在指定的鏡像,不存在就從 registry 下載
- 利用鏡像創建並啟動一個容器
- 分配一個文件系統,並在只讀的鏡像層外面掛載一層可讀寫層
- 從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中去
- 從地址池配置一個 ip 地址給容器
- 執行用戶指定的應用程序
- 執行完畢后容器被終止
啟動已終止容器
可以利用 docker container start 命令,直接將一個已經終止(exited)的容器啟動運行。
$ docker container start b9198ea30925
容器的核心為所執行的應用程序,所需要的資源都是應用程序運行所必需的。除此之外,並沒有其它的資源。可以在偽終端中利用 ps 或 top 來查看進程信息。
root@ba267838cc1b:/# ps
PID TTY TIME CMD
1 ? 00:00:00 bash
11 ? 00:00:00 ps
可見,容器中僅運行了指定的 bash 應用。這種特點使得 Docker 對資源的利用率極高,是貨真價實的輕量級虛擬化。
2、后台運行
使用 -d 參數運行容器。
$ docker run -d ubuntu:18.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
77b2dc01fe0f3f1265df143181e7b9af5e05279a884f4776ee75350ea9d8017a
此時容器會在后台運行並不會把輸出的結果 (STDOUT) 打印到宿主機上面(輸出結果可以用 docker logs 查看)。
$ docker logs 77b
查看容器信息
# 查看正在運行的容器
$ docker container ls
$ docker ps
# 查看所有運行過的容器
$ docker ps -a
3、終止容器
可以使用 docker container stop 或者 docker stop 來終止一個運行中的容器。
處於終止狀態的容器,可以通過 docker container start 命令來重新啟動。
此外,docker container restart 命令會將一個運行態的容器終止,然后再重新啟動它。
4、進入容器
在使用 -d 參數時,容器啟動后會進入后台。需要進入容器進行操作,包括使用 docker attach 命令或 docker exec 命令,推薦使用 docker exec 命令。
attach命令
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
218a71b508bf base:v1 "/bin/bash" 2 months ago Up 6 seconds 0.0.0.0:2333->22/tcp, :::2333->22/tcp distracted_robinson
$ docker attach 218
[root@218a71b508bf /]# ls
bin data dev etc home lib lib64 media mnt nas opt proc root run sbin srv sys tmp Users usr var
[root@218a71b508bf /]#
注意: 如果從這個 stdin 中 exit,會導致容器的停止。
exec命令
docker exec 后邊可以跟多個參數,這里主要說明 -i -t 參數。
只用 -i 參數時,由於沒有分配偽終端,界面沒有我們熟悉的 Linux 命令提示符,但命令執行結果仍然可以返回。
當 -i -t 參數一起使用時,則可以看到我們熟悉的 Linux 命令提示符。
$ docker exec -i 218a bash
ls
bin
data
dev
etc
home
lib
lib64
media
mnt
nas
opt
proc
root
run
sbin
srv
sys
tmp
Users
usr
var
exit
$ docker exec -it 218a bash
[root@218a71b508bf /]# ls
8e13963c663a4bfe9fe4b873ffe35d47-6696_decode.py_ anaconda-post.log bin data dev etc home lib lib64 media mnt nas opt proc root run sbin srv sys tmp Users usr var
[root@218a71b508bf /]#
如果從這個 stdin 中 exit,不會導致容器的停止。這就是為什么推薦使用 docker exec 的原因。
5、導入和導出容器
導出容器
導出本地某個容器,可以使用 docker export 命令。
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7691a814370e ubuntu:18.04 "/bin/bash" 36 hours ago Exited (0) 21 hours ago test
$ docker export 7691a814370e > ubuntu.tar
這樣將導出容器快照到本地文件。
導入容器
使用 docker import 從容器快照文件中再導入為鏡像,例如:
$ cat ubuntu.tar | docker import - test/ubuntu:v1.0
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB
此外,也可以通過指定 URL 或者某個目錄來導入,例如:
$ docker import http://example.com/exampleimage.tgz example/imagerepo
注:用戶既可以使用 docker load 來導入鏡像存儲文件到本地鏡像庫,也可以使用 docker import 來導入一個容器快照到本地鏡像庫。這兩者的區別在於容器快照文件將丟棄所有的歷史記錄和元數據信息(即僅保存容器當時的快照狀態),而鏡像存儲文件將保存完整記錄,體積也要大。此外,從容器快照文件導入時可以重新指定標簽等元數據信息。
6、刪除容器
使用 docker container rm 來刪除一個處於終止狀態的容器。例如:
$ docker container rm mysql
mysql
如果要刪除一個運行中的容器,可以添加 -f 參數。Docker 會發送 SIGKILL 信號給容器。
$ docker container rm -f mysql
清除所有終止狀態的容器
$ docker container prune
三、Docker倉庫
倉庫(Repository)是集中存放鏡像的地方。
一個容易混淆的概念是注冊服務器(Registry)。實際上注冊服務器是管理倉庫的具體服務器,每個服務器上可以有多個倉庫,而每個倉庫下面有多個鏡像。從這方面來說,倉庫可以被認為是一個具體的項目或目錄。例如對於倉庫地址 docker.io/ubuntu 來說,docker.io 是注冊服務器地址,ubuntu 是倉庫名。
大部分時候,並不需要嚴格區分這兩者的概念。
1、Docker Hub
目前 Docker 官方維護了一個公共倉庫 Docker Hub (opens new window),其中已經包括了數量超過 8,250,000 (opens new window)的鏡像。大部分需求都可以通過在 Docker Hub 中直接下載鏡像來實現。
注冊
登錄
可以通過執行 docker login 命令交互式的輸入用戶名及密碼來完成在命令行界面登錄 Docker Hub。
通過 docker logout 退出登錄。
拉取鏡像
以通過 docker search 命令來查找官方倉庫中的鏡像,並利用 docker pull 命令來將它下載到本地。
例如以 centos 為關鍵詞進行搜索:
$ docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos The official build of CentOS. 6449 [OK]
ansible/centos7-ansible Ansible on Centos7 132 [OK]
consol/centos-xfce-vnc Centos container with "headless" VNC session… 126 [OK]
jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - … 117 [OK]
centos/systemd systemd enabled base container. 96 [OK]
推送鏡像
用戶也可以在登錄后通過 docker push 命令來將自己的鏡像推送到 Docker Hub。
以下命令中的 username 請替換為你的 Docker 賬號用戶名。
$ docker tag ubuntu:18.04 username/ubuntu:18.04
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 275d79972a86 6 days ago 94.6MB
username/ubuntu 18.04 275d79972a86 6 days ago 94.6MB
$ docker push username/ubuntu:18.04
$ docker search username
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
username/ubuntu
2、私有倉庫
鏈接(下篇整理通過搭建私有倉庫)--待完善
