Docker是Go語言開發實現的容器。2013年發佈至今,備受推崇。相關文檔、學習資料十分詳盡。近期公司docker項目要推動,得從新學習一下。博客以筆記。python
(1)軟件開發和運維中,環境部署、配置,不勝其煩。舉例說明,Python開發和部署都必須配置Python解釋器;運維過程當中,有時測試環境能經過,可是到線上卻報錯,究其緣由,是環境不一致。
傳統運維過程當中,線上有十臺機器,每增長一臺都須要從新部署一次,簡直就是「體力勞動」。
(2)虛擬機在必定程度能夠解決這些問題,可是存在幾個缺點:
- 資源佔用多 虛機啓動須要佔用幾百M的內存。
- 冗餘步驟多 系統級別的操做步驟,每每沒法跳過,好比用戶登陸。
- 啓動慢,每每幾分鐘 啓動操做系統須要多久,啓動虛擬機就須要多久。linux
(3)容器優點
容器不是模擬一個操做系統,而是對進程進行隔離。屬於進程級別。
- 啓動快, 至關於啓動本機底層系統的一個進程,而不是虛擬機內部的進程,速度快不少。
- 佔用資源少,容器只佔用須要的資源,不佔用那些沒有用到的資源;多個容器能夠共享資源,虛擬機是獨享資源。
- 體積小,容器只要包含用到的組件便可,而虛擬機是整個操做系統的打包,因此容器文件比虛擬機文件要小不少。nginx
傳統虛擬化示意圖:redis
docker虛擬化示意圖:docker
(1)鏡像imageshell
Docker 把應用程序及其依賴,打包在 image 文件裏面。只有經過這個文件,才能生成 Docker 容器。image 文件能夠看做是容器的模板。Docker 根據 image 文件生成容器的實例。同一個 image 文件,能夠生成多個同時運行的容器實例。
image 是二進制文件。實際開發中,一個 image 文件每每經過繼承另外一個 image 文件,加上一些個性化設置而生成。舉例來講,你能夠在 Ubuntu 的 image 基礎上,往裏面加入 Apache 服務器,造成你的 image。ubuntu
image 文件是通用的,一臺機器的 image 文件拷貝到另外一臺機器,照樣可使用。通常來講,爲了節省時間,咱們應該儘可能使用別人製做好的 image 文件,而不是本身製做。即便要定製,也應該基於別人的 image 文件進行加工,而不是從零開始製做。
爲了方便共享,image 文件製做完成後,能夠上傳到網上的倉庫。Docker 的官方倉庫 Docker Hub 是最重要、最經常使用的 image 倉庫。此外,出售本身製做的 image 文件也是能夠的。centos
(2)容器Container安全
image 文件生成的容器實例,自己也是一個文件,稱爲容器文件。也就是說,一旦容器生成,就會同時存在兩個文件: image 文件和容器文件。並且關閉容器並不會刪除容器文件,只是容器中止運行而已。bash
(3)倉庫Repository
鏡像構建完成後,能夠很容易的在當前宿主機上運行,可是,若是須要在其它服務器上使用這個鏡像,咱們就須要一個集中的存儲、分發鏡像的服務,Docker Registry 就是這樣的服務。
一個 Docker Registry 中能夠包含多個倉庫(Repository);每一個倉庫能夠包含多個標籤(Tag);每一個標籤對應一個鏡像。
一般,一個倉庫會包含同一個軟件不一樣版本的鏡像,而標籤就經常使用於對應該軟件的各個版本。咱們能夠經過 <倉庫名>:<標籤> 的格式來指定具體是這個軟件哪一個版本的鏡像。若是不給出標籤,將以 latest 做爲默認標籤。
以CentOS爲例:
Docker CE 支持 64 位版本 CentOS 7,而且要求內核版本不低於 3.10。 CentOS 7 知足最低內核的要求,但因爲內核版本比較低,部分功能(如 overlay2
存儲層驅動)沒法使用,而且部分功能可能不太穩定。
(1)卸載舊版本
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
(2)安裝依賴包
yum install -y yum-utils device-mapper-persistent-data lvm2
(3)安裝國內源
yum-config-manager --add-repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
(4)安裝docker-ce
yum makecache fast yum install docker-ce
也可使用腳本自動安裝:
curl -fsSL get.docker.com -o get-docker.sh sh get-docker.sh --mirror Aliyun
(5)啓動docker-ce
systemctl enable docker systemctl start docker
示例:
(6)建立docker用戶組
默認狀況下,docker 命令會使用 Unix socket 與 Docker 引擎通信。而只有 root 用戶和 docker 組的用戶才能夠訪問 Docker 引擎的 Unix socket。出於安全考慮,通常 Linux 系統上不會直接使用 root 用戶。
所以,更好地作法是將須要使用 docker 的用戶加入 docker 用戶組。
# 創建 docker 組: sudo groupadd docker # 將當前用戶加入 docker 組: sudo usermod -aG docker $USER # 退出當前終端並從新登陸,進行以下測試
注意:本次使用的是root用戶。
(7)測試docker是否安裝成功
docker run hello-world
若是出現以下信息代表安裝成功了:
Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world ca4f61b1923c: Pull complete Digest: sha256:97ce6fa4b6cdc0790cda65fe7290b74cfebd9fa0c9b8c38e979330d547d22ce1 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://cloud.docker.com/ For more examples and ideas, visit: https://docs.docker.com/engine/userguide/
(8)配置內核參數
默認配置下,若是在 CentOS 使用 Docker CE 看到下面的這些警告信息:
WARNING: bridge-nf-call-iptables is disabled WARNING: bridge-nf-call-ip6tables is disabled
添加內核配置參數以啓用這些功能:
tee -a /etc/sysctl.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF
從新加載內核配置
sysctl -p
從 Docker 鏡像倉庫獲取鏡像的命令是 docker pull
。其命令格式爲:
docker pull [選項] [Docker Registry 地址[:端口號]/]倉庫名[:標籤]
具體的選項能夠經過 docker pull --help
命令看到,這裏咱們說一下鏡像名稱的格式。
<域名/IP>[:端口號]
。默認地址是 Docker Hub。<用戶名>/<軟件名>
。對於 Docker Hub,若是不給出用戶名,則默認爲 library
,也就是官方鏡像。例如,從鏡像倉庫獲取nginx:
[@sjs_123_183 ~]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx 2a72cbf407d6: Pull complete e19f9e910af9: Pull complete 2f3d26a87e79: Pull complete Digest: sha256:e36d7f5dabf1429d84135bb8a8086908e1150f1a178c75719a9e0e53ebb90353 Status: Downloaded newer image for nginx:latest
(1)上訴命令中沒有指定 Docker 鏡像倉庫地址,所以將會從 Docker Hub 獲取鏡像。
(2)而鏡像名稱是 nginx,所以將會獲取官方鏡像 library/nginx 倉庫中標籤爲 latest 的鏡像。
(3)從下載過程當中能夠看到咱們以前說起的分層存儲的概念,鏡像是由多層存儲所構成。下載也是一層層的去下載,並不是單一文件。
下載過程當中給出了每一層的 ID 的前 12 位。而且下載結束後,給出該鏡像完整的 sha256 的摘要,以確保下載一致性。
(4)官方鏡像是一直在維護,你所看到的層 ID 以及 sha256 的摘要可能和此處不同。
咱們再獲取一個官方的Ubuntu鏡像看看:
[@sjs_123_183 ~]# docker pull ubuntu:16.04 16.04: Pulling from library/ubuntu 22dc81ace0ea: Pull complete 1a8b3c87dba3: Pull complete 91390a1c435a: Pull complete 07844b14977e: Pull complete b78396653dae: Pull complete Digest: sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6 Status: Downloaded newer image for ubuntu:16.04
以ubuntu鏡像爲例,運行鏡像
docker run -it --rm ubuntu:16.04 bash
(1)docker run 就是運行容器的命令,具體格式可在後面闡述。
(2)-it:這是兩個參數,一個是 -i:交互式操做,一個是 -t 終端。咱們這裏打算進入 bash 執行一些命令並查看返回結果,所以咱們須要交互式終端。
(3)--rm:這個參數是說容器退出後隨之將其刪除。默認狀況下,爲了排障需求,退出的容器並不會當即刪除,除非手動 docker rm。咱們這裏只是隨便執行個命令,看看結果,不須要排障和保留結果,所以使用 --rm 能夠避免浪費空間。
(4)ubuntu:16.04:這是指用 ubuntu:16.04 鏡像爲基礎來啓動容器。
(5)bash:放在鏡像名後的是命令,這裏咱們但願有個交互式 Shell,所以用的是 bash。
運行上訴命令後會進入ubuntu鏡像示例的的shell界面,咱們查看系統,結果以下:
root@a1318dadbea3:/# cat /etc/os-release NAME="Ubuntu" VERSION="16.04.4 LTS (Xenial Xerus)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 16.04.4 LTS" VERSION_ID="16.04" HOME_URL="http://www.ubuntu.com/" SUPPORT_URL="http://help.ubuntu.com/" BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/" VERSION_CODENAME=xenial UBUNTU_CODENAME=xenial root@a1318dadbea3:/#
exit退出當前容器。
列出鏡像的命令:
docker image ls
示例:
[@sjs_123_183 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest c5c4e8fa2cf7 6 days ago 109MB ubuntu 16.04 f975c5035748 4 weeks ago 112MB hello-world latest f2a91732366c 4 months ago 1.85kB
每列的含義:
REPOSITORY:倉庫名 TAG:標籤, 一個鏡像能夠對應多個標籤 IMAGE ID:鏡像 ID,是鏡像的惟一標識 CREATED:建立時間 SIZE:所佔用的空間
注意:此處看到所佔用空間與Docker Hub 上看到的鏡像大小不一樣。
好比,ubuntu:16.04 鏡像大小,在這裏是 112 MB,可是在 Docker Hub 顯示的倒是 43 MB。這是由於:
(1)Docker Hub 中顯示的體積是壓縮後的體積。減少網絡傳輸流量。
(2)docker image ls 顯示的是鏡像下載到本地後,展開的大小,準確說,是展開後的各層所佔空間的總和,由於鏡像到本地後,查看空間的時候,更關心的是本地磁盤空間佔用的大小。
(3)docker image ls 列表中的鏡像體積總和並不是是全部鏡像實際硬盤消耗。因爲 Docker 鏡像是多層存儲結構,而且能夠繼承、複用,所以不一樣鏡像可能會由於使用相同的基礎鏡像,從而擁有共同的層。
因爲 Docker 使用 Union FS,相同的層只須要保存一份便可,所以實際鏡像硬盤佔用空間極可能要比這個列表鏡像大小的總和要小的多。
命令:
docker system df
示例:
[@sjs_123_183 ~]# docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 3 2 221.4MB 112.4MB (50%) Containers 2 0 0B 0B Local Volumes 0 0 0B 0B Build Cache 0B 0B
倉庫名和標籤均爲 <none>,這類無標籤、無倉庫名鏡像被稱 虛懸鏡像(dangling image) 。
鏡像本來是有鏡像名和標籤的,好比原來爲 mongo:3.2,隨着官方鏡像維護,發佈了新版本後,從新 docker pull mongo:3.2 時,mongo:3.2 這個鏡像名被轉移到了新下載的鏡像身上,而舊的鏡像上的這個名稱則被取消,從而成爲了 <none>。
除了 docker pull 可能致使這種狀況,docker build 也一樣能夠致使這種現象。因爲新舊鏡像同名,舊鏡像名稱被取消,從而出現倉庫名、標籤均爲 <none> 的鏡像。
虛懸鏡像示例:
<none> <none> 00285df0df87 5 days ago 342 MB
顯示虛懸鏡像命令:
docker image ls -f dangling=true
刪除虛懸鏡像:
docker image prune
爲了加速鏡像構建、重複利用資源,Docker 會利用 中間層鏡像。因此在使用一段時間後,可能會看到一些依賴的中間層鏡像。默認的 docker image ls 列表中只會顯示頂層鏡像,若是但願顯示包括中間層鏡像在內的全部鏡像的話,須要加 -a 參數。
docker image ls -a
這樣會看到不少無標籤的鏡像,與以前的虛懸鏡像不一樣,這些無標籤的鏡像不少都是中間層鏡像,是其它鏡像所依賴的鏡像。這些無標籤鏡像不該該刪除,不然會致使上層鏡像由於依賴丟失而出錯。
實際上,這些鏡像也不必刪除,由於以前說過,相同的層只會存一遍,而這些鏡像是別的鏡像的依賴,所以並不會由於它們被列出來而多存了一份,不管如何你也會須要它們。只要刪除那些依賴它們的鏡像後,這些依賴的中間層鏡像也會被連帶刪除。
(1)列出部分鏡像
命令:
docker image ls redis 按倉庫名過濾 docker image ls redis:3.2 按倉庫名和標籤過濾 docker image ls -f since=redis:3.2.11 列出redis:3.2.11以後創建的鏡像 docker image ls -f before=redis:3.2 列出redis:3.2以前創建的鏡像
示例:
[@sjs_123_183 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest c5c4e8fa2cf7 2 weeks ago 109MB redis latest c5355f8853e4 3 weeks ago 107MB redis 3.2 b05c3d76c8b3 5 weeks ago 99.7MB redis 3.2.11 b05c3d76c8b3 5 weeks ago 99.7MB ubuntu 16.04 f975c5035748 6 weeks ago 112MB hello-world latest f2a91732366c 5 months ago 1.85kB [@sjs_123_183 ~]# docker image ls redis REPOSITORY TAG IMAGE ID CREATED SIZE redis latest c5355f8853e4 3 weeks ago 107MB redis 3.2 b05c3d76c8b3 5 weeks ago 99.7MB redis 3.2.11 b05c3d76c8b3 5 weeks ago 99.7MB [@sjs_123_183 ~]# docker image ls redis:3.2 REPOSITORY TAG IMAGE ID CREATED SIZE redis 3.2 b05c3d76c8b3 5 weeks ago 99.7MB [@sjs_123_183 ~]# docker image ls -f since=redis:3.2.11 REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest c5c4e8fa2cf7 2 weeks ago 109MB redis latest c5355f8853e4 3 weeks ago 107MB [@sjs_123_183 ~]# docker image ls -f before=redis:3.2 REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 16.04 f975c5035748 6 weeks ago 112MB hello-world latest f2a91732366c 5 months ago 1.85kB
(2)自定義輸出格式
docker images --filter "條件" 按條件過濾
示例:
[@sjs_123_183 ~]# docker images --filter "since=redis:3.2" REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest c5c4e8fa2cf7 2 weeks ago 109MB redis latest c5355f8853e4 3 weeks ago 107MB
(3)使用go語言模板語法
docker images --format "{{.ID}} <--> {{.Repository}}" # 按 ID <--> 倉庫名格式列出 docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}" # 按ID 倉庫 標籤的格式列出
示例:
[@sjs_123_183 ~]# docker images --format "{{.ID}} <--> {{.Repository}}" c5c4e8fa2cf7 <--> nginx c5355f8853e4 <--> redis b05c3d76c8b3 <--> redis b05c3d76c8b3 <--> redis f975c5035748 <--> ubuntu f2a91732366c <--> hello-world [@sjs_123_183 ~]# docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}" IMAGE ID REPOSITORY TAG c5c4e8fa2cf7 nginx latest c5355f8853e4 redis latest b05c3d76c8b3 redis 3.2 b05c3d76c8b3 redis 3.2.11 f975c5035748 ubuntu 16.04 f2a91732366c hello-world latest
經常使用go語言模板:
.ID # 鏡像ID .Repository # 鏡像倉庫名 .Tag # 鏡像標籤 .Digest # 鏡像摘要 .CreatedSince # 鏡像建立到如今的耗時 .CreatedAt # 鏡像建立時間 .Size # 鏡像大小
10.1 單臺刪除
刪除本地鏡像的命令是docker image rm,用法以下:
docker image rm [選項] <鏡像1> [<鏡像2> ...]
(1)<鏡像> 能夠是 鏡像短 ID、鏡像長 ID、鏡像名 或者 鏡像摘要。
(2)也可使用鏡像名,即 <倉庫名>:<標籤> 刪除鏡像。
(3)更精確的是使用 鏡像摘要 刪除鏡像。
注意:刪除行爲分爲兩類,一類是 Untagged,另外一類是 Deleted。
鏡像的惟一標識是其 ID 和摘要,而一個鏡像能夠有多個標籤。
所以當咱們使用上面命令刪除鏡像的時候,其實是在要求刪除某個標籤的鏡像。
(1)因此首先須要作的是將知足咱們要求的全部鏡像標籤都取消,這就是咱們看到的 Untagged 的信息。由於一個鏡像能夠對應多個標籤,所以當咱們刪除了所指定的標籤後,可能還有別的標籤指向了這個鏡像,若是是這種狀況,那麼 Delete 行爲就不會發生。因此並不是全部的 docker rmi 都會產生刪除鏡像的行爲,有可能僅僅是取消了某個標籤而已。
(2)當該鏡像全部的標籤都被取消了,該鏡像極可能會失去了存在的意義,所以會觸發刪除行爲。鏡像是多層存儲結構,所以在刪除的時候也是從上層向基礎層方向依次進行判斷刪除。鏡像的多層結構讓鏡像複用變更很是容易,所以頗有可能某個其它鏡像正依賴於當前鏡像的某一層。這種狀況,依舊不會觸發刪除該層的行爲。直到沒有任何層依賴當前層時,纔會真實的刪除當前層。這就是爲何,有時候會奇怪,爲何明明沒有別的標籤指向這個鏡像,可是它仍是存在的緣由,也是爲何有時候會發現所刪除的層數和本身 docker pull 看到的層數不同的源。
(3)除了鏡像依賴之外,還須要注意的是容器對鏡像的依賴。若是有用這個鏡像啓動的容器存在(即便容器沒有運行),那麼一樣不能夠刪除這個鏡像。以前講過,容器是以鏡像爲基礎,再加一層容器存儲層,組成這樣的多層存儲結構去運行的。所以該鏡像若是被這個容器所依賴的,那麼刪除必然會致使故障。若是這些容器是不須要的,應該先將它們刪除,而後再來刪除鏡像。
示例:
[@sjs_123_183 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest c5c4e8fa2cf7 2 weeks ago 109MB redis latest c5355f8853e4 3 weeks ago 107MB redis 3.2 b05c3d76c8b3 5 weeks ago 99.7MB redis 3.2.11 b05c3d76c8b3 5 weeks ago 99.7MB ubuntu 16.04 f975c5035748 6 weeks ago 112MB hello-world latest f2a91732366c 5 months ago 1.85kB [@sjs_123_183 ~]# [@sjs_123_183 ~]# [@sjs_123_183 ~]# docker image rm redis:3.2.11 Untagged: redis:3.2.11 [@sjs_123_183 ~]# [@sjs_123_183 ~]# [@sjs_123_183 ~]# docker image rm f97 Untagged: ubuntu:16.04 Untagged: ubuntu@sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6 Deleted: sha256:f975c50357489439eb9145dbfa16bb7cd06c02c31aa4df45c77de4d2baa4e232 Deleted: sha256:0bd983fc698ee9453dd7d21f8572ea1016ec9255346ceabb0f9e173b4348644f Deleted: sha256:08fe90e1a1644431accc00cc80f519f4628dbf06a653c76800b116d3333d2b6d Deleted: sha256:5dc5eef2b94edd185b4d39586e7beb385a54b6bac05d165c9d47494492448235 Deleted: sha256:14a40a140881d18382e13b37588b3aa70097bb4f3fb44085bc95663bdc68fe20 Deleted: sha256:a94e0d5a7c404d0e6fa15d8cd4010e69663bd8813b5117fbad71365a73656df9
10.2 批量刪除
用 docker image ls 命令來配合批量刪除本地鏡像。
docker image rm $(docker image ls -q redis) # 刪除全部倉庫名爲 redis 的鏡像 docker image rm $(docker image ls -q -f before=mongo:3.2) # 刪除全部在 mongo:3.2 以前的鏡像
示例:
[@sjs_123_183 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest c5c4e8fa2cf7 2 weeks ago 109MB redis latest c5355f8853e4 3 weeks ago 107MB redis 3.2 b05c3d76c8b3 5 weeks ago 99.7MB hello-world latest f2a91732366c 5 months ago 1.85kB [@sjs_123_183 ~]# docker image rm $(docker image ls -q redis) Untagged: redis:latest Untagged: redis@sha256:6b9f935e89af002225c0dcdadf1fd74245b4cc1e3e91222f7e4769c236cf80d4 Deleted: sha256:c5355f8853e4174a55144edfec23ac37f5bb2200ed838dab53c13c7cc835ab15 Deleted: sha256:65f4f6d6a5f66e424046ccfe359ba5668f2905ec688a8ca62079dfd7946bb989 Deleted: sha256:3f490bf3919344e7ba4acd58824bd24a9479374d6b1d67b59bab7cda118572cf Deleted: sha256:678c0094f27aa1100c30946b9d55981537a107639e71527b5f54ff3de54c12d7 Untagged: redis:3.2 Untagged: redis@sha256:fd310669f5f1be3d96cfe560264cacd5067d6b03b35764b608ada2db98be6208 Deleted: sha256:b05c3d76c8b3ef3af8974edda3941a4a028d244681cc420e5304a3829519f1b6 Deleted: sha256:c7310f74bc14105a3f09a921aeec7feb031f70a95be81ceacc42690efcdc146d Deleted: sha256:7d7786b85eeb28eba62636c3088e535ddbe1640a9632aab550f9a58c0c011faa Deleted: sha256:635b643d26091e3396661ab3b2e08d59110d5ecec236eb100168ced03cf7630b Deleted: sha256:05ffc1bd56d27d29a8a9c36c77dca93ba19dabc77adaf9d3a1ff44c760c3690d Deleted: sha256:1df131a973126fb31c35ca41b2071da4bffcbed7ab8456635b699772e9ad0d8b Deleted: sha256:43efe85a991cac5894f91ee8f45b328bbacd14966d89a8a00b0d06060c64b5ad [@sjs_123_183 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest c5c4e8fa2cf7 2 weeks ago 109MB hello-world latest f2a91732366c 5 months ago 1.85kB