鏡像做爲 Docker 三大核心概念中,最重要的一個關鍵詞,它有不少操做,是您想學習容器技術不得不掌握的。本文將帶您一步一步,圖文並重,上手操做來學習它。python
若是咱們想要在本地運行容器,就必須保證本地存在對應的鏡像。因此,第一步,咱們須要下載鏡像。當咱們嘗試下載鏡像時,Docker 會嘗試先從默認的鏡像倉庫(默認使用 Docker Hub 公共倉庫)去下載,固然了,用戶也能夠自定義配置想要下載的鏡像倉庫。mysql
鏡像是運行容器的前提,咱們可使用 docker pull[IMAGE_NAME]:[TAG]
命令來下載鏡像,其中 IMAGE_NAME
表示的是鏡像的名稱,而 TAG
是鏡像的標籤,也就是說咱們須要經過 「鏡像 + 標籤」 的方式來下載鏡像。git
注意: 您也能夠不顯式地指定 TAG, 它會默認下載 latest 標籤,也就是下載倉庫中最新版本的鏡像。這裏並不推薦您下載 latest 標籤,由於該鏡像的內容會跟蹤鏡像的最新版本,並隨之變化,因此它是不穩定的。在生產環境中,可能會出現莫名其妙的 bug, 推薦您最好仍是顯示的指定具體的 TAG。github
舉個例子,如咱們想要下載一個 Mysql 5.7 鏡像,能夠經過命令來下載:sql
docker pull mysql:5.7
會看到控制檯輸出內容以下:docker
注意: 因爲官方 DockerHub 倉庫服務器在國外,下載速度較慢,因此我將倉庫的地址更改爲了國內的 docker.io
的鏡像倉庫,因此在上圖中,鏡像前面會有 docker.io
出現。shell
當有 Downloaded 字符串輸出的時候,說明下載成功了!!ubuntu
讓咱們來驗證一下,本地是否存在 Mysql5.7 的鏡像,運行命令:bash
docker images
能夠看到本地的確存在該鏡像,確實是下載成功了!服務器
再說說上面下載鏡像的過程:
經過下載過程,能夠看到,一個鏡像通常是由多個層( layer
) 組成,相似 f7e2b70d04ae
這樣的串表示層的惟一 ID(實際上完整的 ID 包括了 256 個 bit, 64 個十六進制字符組成)。
您可能會想,若是多個不一樣的鏡像中,同時包含了同一個層( layer),這樣重複下載,豈不是致使了存儲空間的浪費麼?
實際上,Docker 並不會這麼傻會去下載重複的層( layer
),Docker 在下載以前,會去檢測本地是否會有一樣 ID 的層,若是本地已經存在了,就直接使用本地的就行了。
另外一個問題,不一樣倉庫中,可能也會存在鏡像重名的狀況發生, 這種狀況咋辦?
嚴格意義上,咱們在使用 docker pull
命令時,還須要在鏡像前面指定倉庫地址( Registry
), 若是不指定,則 Docker 會使用您默認配置的倉庫地址。例如上面,因爲我配置的是國內 docker.io
的倉庫地址,我在 pull
的時候,docker 會默認爲我加上 docker.io/library
的前綴。
如:當我執行 docker pull mysql:5.7
命令時,實際上至關於 docker pull docker.io/mysql:5.7
,若是您未自定義配置倉庫,則默認在下載的時候,會在鏡像前面加上 DockerHub 的地址。
Docker 經過前綴地址的不一樣,來保證不一樣倉庫中,重名鏡像的惟一性。
命令行中輸入:
docker pull --help
會獲得以下信息:
[root@iZbp1j8y1bab0djl9gdp33Z ~]# 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) --help Print usage
咱們能夠看到主要支持的子命令有:
-a,--all-tags=true|false
: 是否獲取倉庫中全部鏡像,默認爲否;--disable-content-trust
: 跳過鏡像內容的校驗,默認爲 true;經過使用以下兩個命令,列出本機已有的鏡像:
docker images
或:
docker image ls
以下圖所示:
對上述紅色標註的字段作一下解釋:
注意:圖中的鏡像大小信息只是邏輯上的大小信息,由於一個鏡像是由多個鏡像層(
layer
)組成的,而相同的鏡像層本地只會存儲一份,因此,真實狀況下,佔用的物理存儲空間大小,可能會小於邏輯大小。
一般狀況下,爲了方便在後續工做中,快速地找到某個鏡像,咱們可使用 docker tag
命令,爲本地鏡像添加一個新的標籤。以下圖所示:
爲 docker.io/mysql
鏡像,添加新的鏡像標籤 allen_mysql:5.7
。而後使用 docker images
命令,查看本地鏡像:
能夠看到,本地多了一個 allen_mysql:5.7
的鏡像。細心的你必定還會發現, allen_mysql:5.7
和 docker.io/mysql:5.7
的鏡像 ID 是如出一轍的,說明它們是同一個鏡像,只是別名不一樣而已。
docker tag
命令功能更像是, 爲指定鏡像添加快捷方式同樣。
經過 docker inspect
命令,咱們能夠獲取鏡像的詳細信息,其中,包括建立者,各層的數字摘要等。
docker inspect docker.io/mysql:5.7
docker inspect
返回的是 JSON
格式的信息,若是您想獲取其中指定的一項內容,能夠經過 -f
來指定,如獲取鏡像大小:
docker inspect -f {{".Size"}} docker.io/mysql:5.7
前面的小節中,咱們知道了,一個鏡像是由多個層(layer)組成的,那麼,咱們要如何知道各個層的具體內容呢?
經過 docker history
命令,能夠列出各個層(layer)的建立信息,如咱們查看 docker.io/mysql:5.7
的各層信息:
docker history docker.io/mysql:5.7
能夠看到,上面過長的信息,爲了方便展現,後面都省略了,若是您想要看具體信息,能夠經過添加 --no-trunc
選項,以下面命令:
docker history --no-trunc docker.io/mysql:5.7
您能夠經過下面命令進行搜索:
docker search [option] keyword
好比,您想搜索倉庫中 mysql
相關的鏡像,能夠輸入以下命令:
docker search mysql
命令行輸入 docker search--help
, 輸出以下:
Usage: docker search [OPTIONS] TERM Search the Docker Hub for images Options: -f, --filter filter Filter output based on conditions provided --help Print usage --limit int Max number of search results (default 25) --no-index Don't truncate output --no-trunc Don't truncate output
能夠看到 search
支持的子命令有:
-f,--filter filter
: 過濾輸出的內容;--limitint
:指定搜索內容展現個數;--no-index
: 不截斷輸出內容;--no-trunc
:不截斷輸出內容;舉個列子,好比咱們想搜索官方提供的 mysql 鏡像,命令以下:
docker search --filter=is-offical=true mysql
再好比,咱們想搜索 Stars 數超過 100 的 mysql 鏡像:
docker search --filter=stars=100 mysql
經過以下兩個均可以刪除鏡像:
docker rmi [image]
或者:
docker image rm [image]
支持的子命令以下:
-f,-force
: 強制刪除鏡像,即使有容器引用該鏡像;-no-prune
: 不要刪除未帶標籤的父鏡像;例如,咱們想刪除上章節建立的 allen_mysql:5.7
鏡像,命令以下:
docker rmi allen_mysql:5.7
從上面章節中,咱們知道 allen_mysql:5.7
和 docker.io/mysql:5.7
實際上指向的是同一個鏡像,那麼,您能夠能會有疑問,我刪除了 allen_mysql:5.7
, 會不會將 docker.io/mysql:5.7
鏡像也給刪除了?
實際上,當同一個鏡像擁有多個標籤時,執行 docker rmi
命令,只是會刪除了該鏡像衆多標籤中,您指定的標籤而已,並不會影響原始的那個鏡像文件。
不信的話,咱們能夠執行 docker images
命令,來看下 docker.io/mysql:5.7
鏡像還在不在:
能夠看到, docker.io/mysql:5.7
鏡像依然存在!
那麼,若是某個鏡像不存在多個標籤,當且僅當只有一個標籤時,執行刪除命令時,您就要當心了,這會完全刪除鏡像。
例如,這個時候,咱們再執行 docker rmi docker.io/mysql:5.7
命令:
從上圖能夠看到,咱們已經刪除了 docker.io/mysql:5.7
鏡像的全部文件層。該鏡像在本地已不復存在了!
除了經過標籤名稱來刪除鏡像,咱們還能夠經過制定鏡像 ID, 來刪除鏡像,如:
docker rmi ee7cbd482336
一旦制定了經過 ID 來刪除鏡像,它會先嚐試刪除全部指向該鏡像的標籤,而後在刪除鏡像自己。
刪除鏡像很簡單,但也不是咱們什麼時候何地都能刪除的,它存在一些限制條件。
當經過該鏡像建立的容器未被銷燬時,鏡像是沒法被刪除的。爲了驗證這一點,咱們來作個試驗。首先,咱們經過 docker pull alpine
命令,拉取一個最新的 alpine
鏡像, 而後啓動鏡像,讓其輸出 hello,docker!
:
接下來,咱們來刪除這個鏡像試試:
能夠看到提示信息,沒法刪除該鏡像,由於有容器正在引用他!同時,這段信息還告訴咱們,除非經過添加 -f
子命令,也就是強制刪除,才能移除掉該鏡像!
docker rmi -f docker.io/alpine
可是,咱們通常不推薦這樣暴力的作法,正確的作法應該是:
也就是,根據上圖中提示的,引用該鏡像的容器 ID ( 9d59e2278553
), 執行刪除命令:
docker rm 9d59e2278553
而後,再執行刪除鏡像的命令:
docker rmi 5cb3aa00f899
這個時候,就能正常刪除了!
咱們在使用 Docker 一段時間後,系統通常都會殘存一些臨時的、沒有被使用的鏡像文件,能夠經過如下命令進行清理:
docker image prune
它支持的子命令有:
-a,--all
: 刪除全部沒有用的鏡像,而不只僅是臨時文件;-f,--force
:強制刪除鏡像文件,無需彈出提示確認;此小節中,您將學習 Docker 如何建立鏡像?Docker 建立鏡像主要有三種:
咱們將主要介紹經常使用的 1,2 兩種。
經過以下命令來建立:
docker container commit
支持的子命令以下:
-a,--author
="": 做者信息;-c,--change
=[]: 能夠在提交的時候執行 Dockerfile 指令,如 CMD、ENTRYPOINT、ENV、EXPOSE、LABEL、ONBUILD、USER、VOLUME、WORIR 等;-m,--message
="": 提交信息;-p,--pause
=true: 提交時,暫停容器運行。接下來,基於本地已有的 Ubuntu 鏡像,建立一個新的鏡像:
首先,讓我將它運行起來,並在其中建立一個 test.txt 文件:
命令以下:
docker run -it docker.io/ubuntu:latest /bin/bashroot@a0a0c8cfec3a:/# touch test.txtroot@a0a0c8cfec3a:/# exit
建立完 test.txt 文件後,須要記住標註的容器 ID: a0a0c8cfec3a
, 用它來提交一個新的鏡像(PS: 你也能夠經過名稱來提交鏡像,這裏只演示經過 ID 的方式)。
執行命令:
docker container commit -m "Added test.txt file" -a "Allen" a0a0c8cfec3a test:0.1
提交成功後,會返回新建立的鏡像 ID 信息,以下圖所示:
再次查看本地鏡像信息,能夠看到新建立的 test:0.1
鏡像了:
經過 Dockerfile 的方式來建立鏡像,是最多見的一種方式了,也是比較推薦的方式。Dockerfile 是一個文本指令文件,它描述了是如何基於一個父鏡像,來建立一個新鏡像的過程。
下面讓咱們來編寫一個簡單的 Dockerfile 文件,它描述了基於 Ubuntu 父鏡像,安裝 Python3 環境的鏡像:
FROM docker.io/ubuntu:latest LABEL version="1.0" maintainer="Allen <weiwosuo@github>" RUN apt-get update && \ apt-get install -y python3 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/*
建立完成後,經過這個 Dockerfile 文件,來構建新的鏡像,執行命令:
docker image build -t python:3 .
注意: 命令的最後有個點,若是不加的話,會構建不成功 !
編譯成功後,再次查看本地鏡像信息,就能夠看到新構建的 python:3 鏡像了。
此小節中,您將學習 Docker 如何導出&加載鏡像。
一般咱們會有下面這種需求,須要將鏡像分享給別人,這個時候,咱們能夠將鏡像導出成 tar 包,別人直接經過加載這個 tar 包,快速地將鏡像引入到本地鏡像庫。
要想使用這兩個功能,主要是經過以下兩個命令:
docker save
docker load
查看本地鏡像以下:
例如,咱們想要將 python:3 鏡像導出來,執行命令:
docker save -o python_3.tar python:3
執行成功後,查看當前目錄:
能夠看到 python_3.tar
鏡像文件已經生成。接下來,你能夠將它經過複製的方式,分享給別人了!
別人拿到了這個 tar
包後,要如何導入到本地的鏡像庫呢?
經過執行以下命令:
docker load -i python_3.tar
或者:
docker load < python_3.tar
導入成功後,查看本地鏡像信息,你就能夠得到別人分享的鏡像了!怎麼樣,是否是很方便呢!
咱們將以上傳到 Docker Hub 上爲示例,演示 Docker 如何上傳鏡像。
想要上傳鏡像到 Docker Hub 上,首先,咱們須要註冊 Docker Hub 帳號。打開 Docker Hub 網址 https://hub.docker.com,開始註冊:
填寫您的 Docker ID (也就是帳號),以及密碼,Email, 點擊繼續。
接下來,Docker Hub 會發送驗證郵件,到您填寫的郵箱當中:
點擊驗證便可,接下來,再次返回 Docker Hub 官網,用您剛剛註冊的 Docker ID 和密碼來登陸帳號!
登陸成功後,會出現以下頁面:
選擇建立一個鏡像倉庫:
填寫倉庫名稱、描述信息、是否公開後,點擊建立。
咱們看到,倉庫已經建立成功了,可是裏面尚未任何鏡像,接下來開始上傳鏡像,到此新建立的倉庫中。
進入命令行,用咱們剛剛獲取的 Docker ID 以及密碼登陸,執行命令:
docker login
登陸成功後,咱們開始準備上傳本地的 python:3
鏡像:
首先,咱們對其打一個新的標籤,前綴與咱們新建立的 Docker ID 、倉庫名保持一致:
docker tag python:3 weiwosuoai1991/python:3
查看本地信息,能夠看到,標籤打成功了。接下開,開始上傳!執行命令:
docker push weiwosuoai1991/python:3
上傳成功!去 Docker Hub 官網,新建立的倉庫的信息頁面驗證一下,是否真的成功了:
大工告成!!!
本文中,咱們着重學習了 Docker 中下載鏡像,、查看鏡像信息、搜索鏡像、刪除鏡像,、建立鏡像、導出&加載鏡像以及向 Docker Hub 上傳鏡像的相關操做。
出處:https://github.com/Snailclimb/JavaGuide/blob/master/docs/tools/Docker-Image.md