在 docker 中,鏡像的結構是以層次划分的,也就是可以在每一層上添加自己的修改,變成新的鏡像。
docker 兩種打包方式如下:
- commit
- build
docker commit
注意: docker commit
命令除了學習之外,還有一些特殊的應用場合,比如被入侵后保存現場等。但是,不要使用 docker commit
定制鏡像,定制鏡像應該使用 Dockerfile
來完成。
鏡像是容器的基礎,每次執行 docker run
的時候都會指定哪個鏡像作為容器運行的基礎。比如我們所使用的都是來自於 Docker Hub 的鏡像,比如不同的linux系統版本有不同的官方基礎鏡像,如 CentOs,Ubuntu。直接使用這些鏡像是可以滿足一定的需求,而當這些鏡像無法直接滿足需求時,我們就需要定制這些鏡像。接下來看看 docker run 如何定制鏡像。
以基礎的 centos 鏡像為例,我們想在這個鏡像上安裝 vim。
docker image ls -a
進入容器內安裝
$ docker exec -it centos bash root@3729b97e8226:/# yum install vim exit
bash
命令,也就是獲得一個可操作的 Shell。
要知道,當我們運行一個容器的時候(如果不使用卷的話),我們做的任何文件修改都會被記錄於容器存儲層里。而 Docker 提供了一個 docker commit 命令,可以將容器的存儲層保存下來成為鏡像。換句話說,就是在原有鏡像的基礎上,再疊加上容器的存儲層,並構成新的鏡像。以后我們運行這個新鏡像的時候,就會擁有原有容器最后的文件變化。
docker commit 的語法格式為:
docker commit [選項] <容器ID或容器名> [<倉庫名>[:<標簽>]]
我們可以用下面的命令來保存新修改的鏡像:
$ docker commit \ --author "Nobody <nobody@gmail.com>" \ --message "安裝了vim" \ centos \ centos:v2 sha256:07e33465974800ce65751acc279adc6ed2dc5ed4e0838f8b86f0c87aa1795214
我們可以在 docker image ls
中看到這個新定制的鏡像:
$ docker image ls centos REPOSITORY TAG IMAGE ID CREATED SIZE centos v2 07e334659748 9 seconds ago 272.5 MB centos latest e43d811ce2f4 4 weeks ago 272 MB
我們還可以用 docker history
具體查看鏡像內的歷史記錄,如果比較 nginx:latest
的歷史記錄
docker build
相比 docker commit,此命令就簡單很多。直接新建 DockerFile 文件:
touch DockerFile vim ./DockerFile
添加以下內容:
FROM centos RUN yum install -y vim
docker build -t blackbinbin/docker-centos-vim ./
打包過程也非常有意思
step1 是直接使用 centos 鏡像。step2 是創建一個臨時的容器來執行 yum install
這里是符合我們上面所說的 docker 鏡像是層次結構的結論,在之后的文章我們會詳細闡述為什么 docker 會使用這樣的文件結構形式。
最后移除臨時的容器
Dockerfile 是一個文本文件,其內包含了一條條的 指令(Instruction),每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。這種描述性語言,比 commit 更符合工程化的思想,因為只要確定 DockerFile 任何人都可以構建出來一樣的鏡像,便於迭代,這也是為什么搞 docker 和 k8s 的經常會被認為是面向 yaml 編程,描述性語言的利用,讓構建和運維的流程更清晰,便於溝通和迭代。