使用Dockerfile构建一个镜像
下面介绍使用Dockerfile
构建一个镜像,步骤如下:
- 首先创建一个空文件夹:
mkdir newdir
; - 然后进入该文件夹:
cd newdir
; - 在该文件夹下创建一个名为
Dockerfile
的文件,根据实际需求补全Dockerfile
的内容; - 使用
Dockerfile
构建一个镜像:docker build -t testimage .
(注意这个小数点)其中-t
指定新镜像的镜像名。
下面举一个实例,使用Dockerfile
构建一个名为testimage
的镜像,该镜像具备ubuntu:latest
的运行环境,而且在镜像的/目录下创建了一个dir1
文件夹。
#先创建一个新的空文件夹
mkdir newdir
#进入这个新文件夹中
cd newdir
#创建一个Dockerfile文件
touch Dockerfile
#补全Dockerfile的内容(为了方便展示,这里用的是echo向Dockerfile中输入内容)
echo "FROM ubuntu:latest" > Dockerfile
echo "RUN mkdir /dir1" >> Dockerfile
#使用该Dockerfile构建一个名为testimage的镜像
docker build -t testimage .
Dockerfile构建镜像的过程详解:
上面的实例创建了一个Dockerfile
文件,Dockerfile
的内容如下:
FROM ubuntu:latest
RUN mkdir /dir1
执行docker build
命令,指定使用Dockerfile
构建一个镜像。执行结果如下所示:
[root@localhost newdir]# docker build -t testimage .
Sending build context to Docker daemon 2.048 kB
Step 1/2 : FROM ubuntu
---> 14f60031763d
Step 2/2 : RUN mkdir dir1
---> Running in c5117d908931
---> cb0193727724
Removing intermediate container c5117d908931
Successfully built cb0193727724
Docker
指令是从上到下一层一层执行的,所以在使用这个Dockerfile
构建镜像时,首先执行FROM ubuntu:latest
这条指令。
FROM ubuntu:latest
指定ubuntu:latest
作为基础镜像,也就是将ubuntu:latest
镜像的所有镜像层放置在testimage
镜像的最下面。
然后执行RUN mkdir dir1
指令,前面我们说过,执行RUN
指令时,会在之前指令创建出的镜像的基础上创建一个临时容器,在这里的容器Id
为c5117d908931
,并在容器中运行命令。在命令结束运行后提交新容器为新镜像,并删除临时创建的容器c5117d908931
。
在Dockerfile
的所有指令执行完后,新镜像就构建完成了!
修改后的Dockerfile文件
因为之前所有的命令只有一个目的,就是编译、安装 redis
可执行文件。因此没有必要建立很多层,这只是一层的事情。因此,修改之后的Dockerfile
文件并没有使用很多个RUN
指令,而仅仅使用一个RUN
指令,并使用 &&
将各个命令串联起来。除此以外,把redis的编译环境、更新的软件包也通通清除掉了,减少镜像占用的存储空间。如下所示,修改之后的Dockerfile
构建完成后是就只会有2
层镜像了(1
层基础镜像+1
层由RUN
执行创建的镜像)。
FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-component
s=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
在Dockerfile
的编写过程中一定要牢记一点:镜像的每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。