初识DOCKERFILE
2017-11-15 13:38
381 查看
初识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执行创建的镜像)。这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。
修改后的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的编写过程中一定要牢记一点:镜像的每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。
相关文章推荐
- Dockerfile中ENTRYPOINT的用法
- dockerfile
- Dockerfile 示例一:创建一个MongoDB的镜像
- Dockerfile指令总结
- docker 应用-2(Dockerfile 编写以及镜像保存提交)
- Docker学习笔记——Dockerfile介绍
- dockerfile实现服务的快速部署
- Dockerfile注意事项
- 初识容器与Docker
- Dockerfile格式
- Dockerfile的CMD指令
- Docker教程:镜像构建和自动镜像构建dockerfile
- Dockerfile指令详解下
- Dockerfile常用命令
- Dockerfile编写制作含有node环境的项目镜像
- Docker系列(四)Dockerfile
- Docker-Dockerfile语法以及一些命令/关键字的区别浅析
- docker常用命令以及dockerfile使用
- Docker学习笔记 — Dockerfile最佳实践
- Dockerfile文件的书写规则