我们都知道使用docker pull
命令可以从 Docker Hub 或其他仓库中拉取镜像。那么同样我们也可以推送自己的镜像到远程仓库中,这一点跟 Git 比较类似。
Docker CLI 提供了两组命令来完成这个操作。
docker build/commit
:构建镜像docker pull/push
:拉取和推送镜像
整个过程如下图所示。通过docker build/commit
命令构建完镜像后,再使用docker push
推送到远程仓库。
构建镜像
前面讲到,在Docker CLI
中构建镜像有两个命令:docker build
与docker commit
。虽然它们的目的都是构建镜像,但实现的方式却不太一样。而且,很重要的一点是,在实际的使用中,是非常不推荐使用docker commit
来构建镜像的。
那我们下面就来介绍一下docker commit
以及为什么不推荐使用它来构建镜像。
docker commit 构建镜像步骤
docker commit 的语法格式为:
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
它是基于容器的修改去创建一个镜像的。所以用这种方式去构建镜像,我们首先得有一个容器。下面我们通过一个ubuntu
镜像作为一个例子来演示:
Step 1:拉取一个镜像
$ docker pull ubuntu
Step 2: 运行并进入容器
$ docker run --name ubuntu -it ubuntu:latest /bin/bash
Step 3: 对容器做一些修改
$ apt-get update
$ apt-get install vim
$ mkdir /home/test && cd /home/test
$ touch README.md
$ exit
Step 4: 提交修改到镜像
docker commit ubuntu jerrymei/ubuntu:v1
到这里,我们就用docker commit
命令构建了一个我们自己的ubuntu
镜像,可以使用docker images
查看一下。
为什么不推荐使用 docker commit 来构建镜像
为什么说实际使用过程中不推荐使用docker commit
来构建镜像呢。就拿刚才的ubuntu
作为例子吧,我们使用docker diff ubuntu
来对比一下对容器做了哪些修改,结果发现由于命令的执行,很多文件都被改动了:新增(A)、删除(D)、修改(C)。
大家都知道,Linux作为一个文件系统,所有对它进行的操作最终都以文件的改变体现出来。但是根据这些信息,我们是很难知道在容器里面到底执行了什么操作。
使用docker commit
意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像。换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。
另外,后期对镜像修改的话,每一次修改都会让镜像更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形地跟着这个镜像,即使根本无法访问到。这会让镜像更加臃肿。
所以在实际的使用中,我们更多地是用docker build
来构建镜像的。下面就介绍一下docker build
构建镜像的步骤。
docker build 构建镜像步骤
docker build 的语法格式为:
docker build [OPTIONS] PATH | URL | -
docker build
是利用Dockerfile
来构建镜像。Dockerfile
是一个文本文件,里面包含了一条条指令,比如前面在容器内部做的那些操作。所以它带来了很多好处,比如镜像的透明性。我们对镜像所有的操作都是在Dockerfile
中以指令的形式呈现,任何人去看这个描述文件就知道做了什么事情。
另一个好处就是可以进行版本管理。我们通常会把Dockerfile
作为项目的一部分放到源码管理库中,也就是说对镜像的操作我们可以随时回溯。它解决了传统运维的不透明性和难以管理性。
在这里我们就不过多介绍Dockerfile
了,我们来讲一下刚才的ubuntu
例子用docker build
怎么去构建。
Step 1:新建一个ubuntu项目,里面包含一个Dockerfile文件
$ mkdir ubuntu && cd ubuntu
$ vi Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y vim
RUN mkdir /home/test && cd /home/test
RUN touch README.md
Step 2:构建镜像
docker build -t jerrymei/ubuntu:v1 .
-t
参数是给镜像命名并打标签,通常我们需要命名为我们的仓库名,比如:jerrymei/ubuntu
是我在 docker hub 上创建的一个仓库。
如果构建后的镜像没有对应我们的仓库名,可以使用另一个命令docker tag
来完成,比如:
docker build -t ubuntu:v1 .
docker tag ubuntu:v1 jerrymei/ubuntu:v1
推送镜像
推送镜像就比较简单了,我们以 Docker Hub 为例。首先我们创建好一个仓库,比如:jerrymei/ubuntu
,创建完毕后会提示我们push
的操作。
我们在操作的机器上先使用docker login
登陆到远程仓库,再执行docker push
即可。
管理镜像
Dockerfile 文件管理
使用Dockerfile
制作镜像,我们需要对Dockerfile
文件进行版本管理。对于开源的项目来说,我通常会在 Github 中建立一个库,然后关联到 Dockerhub 的仓库。其他的像Source to Image
工具也可以。这样的话,我们就可以跟踪Dockerfile
的变更情况。
在 Dockerhub 项目仓库的 Builds
选项中配置好对应的源代码位置,我们项目主页就会出现一个Dockerfile
的分区。
镜像版本管理
我们可以利用Tag
来对镜像做版本管理。需要注意的是,不要只使用latest
标签。我们对镜像的任何修改都需要发布新的 Tag,避免对之前的使用者造成影响。同样,作为镜像的使用者,我们也最好不要使用latest
标签,而是找到具体的版本。
参考: