一、Docker镜像的缓存特性
1、构建镜像
Docker 会缓存已有镜像的镜像层,构建新镜像时,如果某镜像层已经存在,就直接使用,无需重新创建。
例如:
在前面的 Dockerfile 中添加一点新内容,往镜像中复制一个文件imageFuGai:
vi Dockerfile
# This my first CentOS Dockerfile
# Version 1.0
# Base images
FROM centos
#MAINTAINER
MAINTAINER zola
#ENV
#ADD
#RUN
RUN yum install -y wget
COPY imageFuGai
#WORKDIR
#EXPOSE
#CMD
[root@docker-centos ~]# pwd
/root
[root@docker-centos ~]# ll
total 8
-rw-------. 1 root root 1616 Apr 29 17:42 anaconda-ks.cfg
-rw-r--r--. 1 root root 189 May 10 20:09 Dockerfile
-rw-r--r--. 1 root root 0 May 10 20:02 imageFuGai
[root@docker-centos ~]# docker build -t centos-with-wget-02 .
Sending build context to Docker daemon 17.41kB
Step 1/4 : FROM centos
---> 470671670cac
Step 2/4 : MAINTAINER zola
---> Using cache
---> fe6ec852b0c9
Step 3/4 : RUN yum install -y wget
---> Using cache
---> 1cca79f8389d
Step 4/4 : COPY imageFuGai /
---> e0ebf5dc3b3c
Successfully built e0ebf5dc3b3c
Successfully tagged centos-with-wget-02:latest
[root@docker-centos ~]#
解释:
Step 2和Step 3:之前已经运行过相同的 RUN 指令,这次直接使用缓存中的镜像层 fe6ec852b0c9和1cca79f8389d。
Step 4:执行 COPY 指令。
其过程是启动临时容器,复制 imageFuGai,提交新的镜像层 e0ebf5dc3b3c,删除临时容器。
在构建镜像时不使用缓存,可以在 docker build 命令中加上 --no-cache 参数
docker build -t --no-cache centos-with-wget-02 .
Dockerfile 中每一个指令都会创建一个镜像层,上层是依赖于下层的。无论什么时候,只要某一层发生变化,其上面所有层的缓存都会失效。
若改变 Dockerfile 指令的执行顺序,或者修改或添加指令,都会使缓存失效。
2、下载镜像
Docker 在下载镜像时也会使用缓存。例如我们下载 httpd 镜像
docker history debian
二、调试 Dockerfile
1、通过 Dockerfile 构建镜像的过程
从 base 镜像运行一个容器
执行一条指令,对容器做修改
执行类似 docker commit 的操作,生成一个新的镜像层
Docker 再基于刚刚提交的镜像运行一个新容器
重复 2-4 步,直到 Dockerfile 中的所有指令执行完毕
2、Dockerfile 由于某种原因执行到某个指令失败了,我们也将能够得到前一个指令成功执行构建出的镜像,这对调试 Dockerfile 非常有帮助
如果Dockerfile 在执行第三步 RUN 指令1时失败。我们可以利用第二步创建的镜像 111133223 进行调试,方式是通过 docker run -it 启动镜像的一个容器
docker run -it 111133223
手工执行 RUN 指令1很容易定位失败的原因
三、Dockerfile 常用指令
参考链接:
https://www.runoob.com/docker/docker-dockerfile.html
FROM
指定 base 镜像。
MAINTAINER
设置镜像的作者,可以是任意字符串。
COPY
将文件从 build context 复制到镜像。
COPY 支持两种形式:
COPY src dest
COPY ["src", "dest"]
注意:src 只能指定 build context 中的文件或目录。
ADD
与 COPY 类似,从 build context 复制文件到镜像。不同的是,如果 src 是归档文件(tar, zip, tgz, xz 等),文件会被自动解压到 dest。
ENV
设置环境变量,环境变量可被后面的指令使用。例如:
...
ENV MY_VERSION 1.3
RUN yum -y install -y mypackage=$MY_VERSION
...
EXPOSE
指定容器中的进程会监听某个端口,Docker 可以将该端口暴露出来。我们会在容器网络部分详细讨论。
VOLUME
将文件或目录声明为 volume。我们会在容器存储部分详细讨论。
WORKDIR
为后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY 指令设置镜像中的当前工作目录。
RUN
在容器中运行指定的命令。
CMD
容器启动时运行指定的命令。
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。CMD 可以被 docker run 之后的参数替换。
ENTRYPOINT
设置容器启动时运行的命令。
Dockerfile 中可以有多个 ENTRYPOINT 指令,但只有最后一个生效。CMD 或 docker run 之后的参数会被当做参数传递给 ENTRYPOINT。
注:Dockerfile 支持以“#”开头的注释
注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:
FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz
以 && 符号连接命令,这样执行后,只会创建 1 层镜像
RUN、CMD、ENTRYPOINT 很重要且容易混淆
四、RUN、CMD 和 ENTRYPOINT
RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包
CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换
ENTRYPOINT 配置容器启动时运行的命令
1、Shell 和 Exec 格式
两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式,二者在使用上有细微的区别。
Shell 格式
<instruction> <command>
Exec 格式
<instruction> ["executable", "param1", "param2", ...]
CMD 和 ENTRYPOINT 推荐使用 Exec 格式,因为指令可读性更强,更容易理解。RUN 两种格式shell格式和Exec格式都可以
2、RUN 有两种格式
Shell 格式:RUN
Exec 格式:RUN ["executable", "param1", "param2"]
使用 RUN 安装多个包:
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
注意:apt-get update 和 apt-get install 被放在一个 RUN 指令中执行,这样能够保证每次安装的是最新的包。如果 apt-get install 在单独的 RUN 中执行,则会使用 apt-get update 创建的镜像层,而这一层可能是很久以前缓存的。
3、最佳实践
使用 RUN 指令安装应用和软件包,构建镜像。
如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。
如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。
微信链接 :https://mp.weixin.qq.com/s/ZA7NtaCfgOhYCcj-k5tQDA
详情请见,公众号