初识DOCKERFILE
示例
[root@dockerdevops ~]# mkdir newdir
[root@dockerdevops ~]# cd newdir
[root@dockerdevops newdir]# touch Dockerfile
[root@dockerdevops newdir]# echo "FROM ubuntu:latest"> Dockerfile
[root@dockerdevops newdir]# echo "RUN mkdir /dir1">>Dockerfile
[root@dockerdevops newdir]# docker build -t testimage .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM ubuntu:latest
---> 747cb2d60bbe
Step 2/2 : RUN mkdir /dir1
---> Running in 1a2f1bb5a3e7
---> 6344d592f811
Removing intermediate container 1a2f1bb5a3e7
Successfully built 6344d592f811
Successfully tagged testimage:latest
[root@dockerdevops newdir]#
解释
Docker指令是从上到下一层一层执行的,所以在使用这个Dockerfile构建镜像时,首先执行FROM ubuntu:latest这条指令。
FROM ubuntu:latest指定ubuntu:latest作为基础镜像,也就是将ubuntu:latest镜像的所有镜像层放置在testimage镜像的最下面。
然后执行RUN mkdir dir1指令,前面我们说过,执行RUN指令时,会在之前指令创建出的镜像的基础上创建一个临时容器,在这里的容器Id为c5117d908931,并在容器中运行命令。在命令结束运行后提交新容器为新镜像,并删除临时创建的容器c5117d908931。
在Dockerfile的所有指令执行完后,新镜像就构建完成了!
注意事项,谨慎使用RUN
修改前的Dokcerfile文件
既然RUN就像 Shell 脚本一样可以执行命令,那么是否就可以像Shell 脚本一样把每个命令对应一个RUN呢?比如这样
- FROM debian:jessie
- RUN apt-get update
- RUN apt-get install -y gcc libc6-dev make
- RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz"
- RUN mkdir -p /usr/src/redis
- RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
- RUN make -C /usr/src/redis
- RUN make -C /usr/src/redis install
上面这个Dockerfile是为了编译、安装 redis可执行文件。虽然它能够完成了所需的功能,但是正如之前说过,Dockerfile中每一个指令都会建立一层,RUN 也不例外。每一个RUN的行为,都会创建一个新的镜像层。
而上面的这种写法,创建了 8 层镜像(1层基础镜像+7层由RUN执行创建的镜像)。这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。
因为之前所有的命令只有一个目的,就是编译、安装 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的编写过程中一定要牢记一点:镜像的每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。
685

被折叠的 条评论
为什么被折叠?



