您好,登錄后才能下訂單哦!
利用Docker怎么構建一個Dockerfile鏡像?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
構建鏡像
構建鏡像主要有兩種方式:
使用docker commit命令從運行中的容器提交為鏡像;
使用docker build命令從 Dockerfile 構建鏡像。
首先介紹下如何從運行中的容器提交為鏡像。我依舊使用 busybox 鏡像舉例,使用以下命令創建一個名為 busybox 的容器并進入 busybox 容器。
$ docker run --rm --name=busybox -it busybox sh
執行完上面的命令后,當前窗口會啟動一個 busybox 容器并且進入容器中。在容器中,執行以下命令創建一個文件并寫入內容:
/ # touch hello.txt && echo "I love Docker. " > hello.txt
此時在容器的根目錄下,已經創建了一個 hello.txt 文件,并寫入了 "I love Docker. "。
下面,我們新打開另一個命令行窗口,運行以下命令提交鏡像:
$ docker commit busybox busybox:hello
sha256:cbc6406aaef080d1dd3087d4ea1e6c6c9915ee0ee0f5dd9e0a90b03e2215e81c
然后使用上面講到的docker image ls命令查看鏡像:
$ docker image ls busybox REPOSITORY TAG IMAGE ID CREATED SIZE busybox hello cbc6406aaef0 2 minutes ago 1.22MB busybox latest 018c9d7b792b 4 weeks ago 1.22MB
此時我們可以看到主機上新生成了 busybox:hello 這個鏡像。
通過對比顯然使用Dockerfile的docker build更好。docker commit的缺點如下:
需要在容器內操作麻煩,效率低。
這一點也是最重要的,其他人或者過一段時間后自己也不知道這個鏡像是怎么做出來的,但是使用Dockerfile構建的鏡像,我們看到是執行了apt-get install命令。
第二種方式是最重要也是最常用的鏡像構建方式:Dockerfile。Dockerfile 是一個包含了用戶所有構建命令的文本。通過docker build命令可以從 Dockerfile 生成鏡像。
使用 Dockerfile 構建鏡像具有以下特性:
Dockerfile 的每一行命令都會生成一個獨立的鏡像層,并且擁有唯一的 ID
Dockerfile 的命令是完全透明的,通過查看 Dockerfile 的內容,就可以知道鏡像是如何一步步構建的
Dockerfile 是純文本的,方便跟隨代碼一起存放在代碼倉庫并做版本管理
看到使用 Dockerfile 的方式構建鏡像有這么多好的特性,你是不是已經迫不及待想知道如何使用了。別著急,我們先學習下 Dockerfile 常用的指令。
Dockerfile 指令 | 指令簡介 |
---|---|
FROM | Dockerfile 除了注釋第一行必須是 FROM ,FROM 后面跟鏡像名稱,代表我們要基于哪個基礎鏡像構建我們的容器。 |
RUN | RUN 后面跟一個具體的命令,類似于 Linux 命令行執行命令。 |
ADD | 拷貝本機文件或者遠程文件到鏡像內 |
COPY | 拷貝本機文件到鏡像內 |
USER | 指定容器啟動的用戶 |
ENTRYPOINT | 容器的啟動命令 |
CMD | CMD 為 ENTRYPOINT 指令提供默認參數,也可以單獨使用 CMD 指定容器啟動參數 |
ENV | 指定容器運行時的環境變量,格式為 key=value |
ARG | 定義外部變量,構建鏡像時可以使用 build-arg = 的格式傳遞參數用于構建 |
EXPOSE | 指定容器監聽的端口,格式為 [port]/tcp 或者 [port]/udp |
WORKDIR | 為 Dockerfile 中跟在其后的所有 RUN、CMD、ENTRYPOINT、COPY 和 ADD 命令設置工作目錄。 |
看了這么多指令,感覺有點懵?別擔心,我通過一個實例讓你來熟悉它們。這是一個 Dockerfile:
FROM centos:7 COPY nginx.repo /etc/yum.repos.d/nginx.repo RUN yum install -y nginx EXPOSE 80 ENV HOST=mynginx CMD ["nginx","-g","daemon off;"]
第一行表示我要基于 centos:7 這個鏡像來構建自定義鏡像。這里需要注意,每個 Dockerfile 的第一行除了注釋都必須以 FROM 開頭。
第二行表示拷貝本地文件 nginx.repo 文件到容器內的 /etc/yum.repos.d 目錄下。這里拷貝 nginx.repo 文件是為了添加 nginx 的安裝源。
第三行表示在容器內運行yum install -y nginx命令,安裝 nginx 服務到容器內,執行完第三行命令,容器內的 nginx 已經安裝完成。
第四行聲明容器內業務(nginx)使用 80 端口對外提供服務。
第五行定義容器啟動時的環境變量 HOST=mynginx,容器啟動后可以獲取到環境變量 HOST 的值為 mynginx。
第六行定義容器的啟動命令,命令格式為 json 數組。這里設置了容器的啟動命令為 nginx ,并且添加了 nginx 的啟動參數 -g 'daemon off;' ,使得 nginx 以前臺的方式啟動。
鏡像的實現原理
其實 Docker 鏡像是由一系列鏡像層(layer)組成的,每一層代表了鏡像構建過程中的一次提交。下面以一個鏡像構建的 Dockerfile 來說明鏡像是如何分層的。
FROM busybox
COPY test /tmp/test
RUN mkdir /tmp/testdir
上面的 Dockerfile 由三步組成:
第一行基于 busybox 創建一個鏡像層;
第二行拷貝本機 test 文件到鏡像內;
第三行在 /tmp 文件夾下創建一個目錄 testdir。
這里我的 Docker 使用的是 overlay2 文件驅動,進入到/var/lib/docker/overlay2目錄下使用tree .命令查看產生的鏡像文件:
$ tree . # 以下為 tree . 命令輸出內容 |-- 3e89b959f921227acab94f5ab4524252ae0a829ff8a3687178e3aca56d605679 | |-- diff # 這一層為基礎層,對應上述 Dockerfile 第一行,包含 busybox 鏡像所有文件內容,例如 /etc,/bin,/var 等目錄 ... 此次省略部分原始鏡像文件內容 | `-- link |-- 6591d4e47eb2488e6297a0a07a2439f550cdb22845b6d2ddb1be2466ae7a9391 | |-- diff # 這一層對應上述 Dockerfile 第二行,拷貝 test 文件到 /tmp 文件夾下,因此 diff 文件夾下有了 /tmp/test 文件 | | `-- tmp | | `-- test | |-- link | |-- lower | `-- work |-- backingFsBlockDev |-- bec6a018080f7b808565728dee8447b9e86b3093b16ad5e6a1ac3976528a8bb1 | |-- diff # 這一層對應上述 Dockerfile 第三行,在 /tmp 文件夾下創建 testdir 文件夾,因此 diff 文件夾下有了 /tmp/testdir 文件夾 | | `-- tmp | | `-- testdir | |-- link | |-- lower | `-- work ...
通過上面的目錄結構可以看到,Dockerfile 的每一行命令,都生成了一個鏡像層,每一層的 diff 夾下只存放了增量數據,如圖 2 所示。
分層的結構使得 Docker 鏡像非常輕量,每一層根據鏡像的內容都有一個唯一的 ID 值,當不同的鏡像之間有相同的鏡像層時,便可以實現不同的鏡像之間共享鏡像層的效果。
總結一下, Docker 鏡像是靜態的分層管理的文件組合,鏡像底層的實現依賴于聯合文件系統(UnionFS)。充分掌握鏡像的原理,可以幫助我們在生產實踐中構建出最優的鏡像,同時也可以幫助我們更好地理解容器和鏡像的關系。
總結
到此,相信你已經對 Docker 鏡像這一核心概念有了較深的了解,并熟悉了 Docker 鏡像的常用操作(拉取、查看、“重命名”、刪除和構建自定義鏡像)及底層實現原理。
鏡像操作命令:
拉取鏡像,使用 docker pull 命令拉取遠程倉庫的鏡像到本地 ;
重命名鏡像,使用 docker tag 命令“重命名”鏡像 ;
查看鏡像,使用 docker image ls 或 docker images 命令查看本地已經存在的鏡像;
刪除鏡像,使用 docker rmi 命令刪除無用鏡像 ;
構建鏡像,構建鏡像有兩種方式。第一種方式是使用 docker build 命令基于 Dockerfile 構建鏡像,也是我比較推薦的鏡像構建方式;第二種方式是使用 docker commit 命令基于已經運行的容器提交為鏡像。
鏡像的實現原理:
鏡像是由一系列的鏡像層(layer )組成,每一層代表了鏡像構建過程中的一次提交,當我們需要修改鏡像內的某個文件時,只需要在當前鏡像層的基礎上新建一個鏡像層,并且只存放修改過的文件內容。分層結構使得鏡像間共享鏡像層變得非常簡單和方便。
看完上述內容,你們掌握利用Docker怎么構建一個Dockerfile鏡像的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。