Dockerfile 高效准则


Dockerfile 用来自动化 构建镜像
Dockerfile 统一 配置语法  不同的平台上 分发 通过 Dockerfile 构建 就能得到所需的镜像
Dockerfile 通过与镜像配合 使得 Docker镜像 构建时 利用镜像的缓存功能 提效
docker build 命令  以Dockerfile 描述的步骤 构建自定义 Docker镜像 比命令行手动 执行指令 高效 


提高 Dockerfile 可读性 使用效率
基础镜像的选择

尽量选择官方镜像库里的基础镜像
选择轻量级的镜像做底包

典型 Linux基础镜像 大小关系如下
Ubuntu > CentOS > alpine
因此相比 Ubuntu 其实更推荐使用最轻量级的 alpine 镜像


多使用标签Tag好处

构建镜像时 给其打上 易读的 镜像标签 有助于 了解镜像的功能
docker build -t=“centos:wordpress" .
这个 centos 镜像是用来做 wordpress 的 所以已经集成了wordpress功能 清晰明了

在 Dockerfile 的 FROM 指令 明确指明标签 Tag 不让 Docker daemon 去猜
FROM alpine:latest


充分利用镜像缓存

由 Dockerfile 最终构建出来的镜像是在 基础镜像 之上一层层叠加而得 因此在过程中会产生一个个新的 镜像层 Docker daemon 在构建镜像的过程中会缓存一系列中间镜像
docker build 镜像时 会顺序执行 Dockerfile 中的指令 并同时比较当前指令和其基础镜像的所有子镜像
若发现有一个子镜像也是由相同的指令生成 则 命中缓存 同时可以直接使用该 子镜像 而避免 去重新生成
为了有效地使用缓存 需要保证 Dockerfile 中指令的 连续一致 尽量将相同指令的部分放在前面 而将有差异性的指令放在后面
例如
用 Dockerfile 基于最基本的 CentOS 镜像来构建两个不同的镜像时 两个 Dockerfile 开头可以相同
FROM centos:latest
# 下面安装两个常用的工具
RUN yum install -y net-tools.x86_64
RUN yum install lrzsz
######## 上面为两个Dockerfile文件中相同的部分######
######## 下面为两个Dockerfile文件中不同的部分######


正确使用ADD 与 COPY 指令

以COPY指令为首选 原因在于 ADD指令并没有COPY指令来的纯粹 ADD会添加一些额外功能 典型的如下 ADD 一个压缩包时 其不仅会复制 还会自动解压 有时并不需要
ADD codesheep.tar.gz /path
在需要添加多个文件到镜像中的时候 不要一次性集中添加 而是选择 按需 在必要时 逐个添加即可 因为这样有利于利用镜像缓存
尽量使用 docker volume
若文件 大而多 应该优先用 docker -v 命令 挂载文件 而不是依赖于 ADD 或者 COPY


CMD 和 ENTRYPOINT指令

Dockerfile 制作镜像时 会组合 CMD 和 ENTRYPOINT 指令来作为容器运行时的默认命令
即 CMD + ENTRYPOINT 此时的默认命令组成中:
ENTRYPOINT 指令 固定不变 容器运行时不修改
而 CMD  指令 可以改变 表现在运行容器时 docker run 命令中提供的参数会覆盖CMD的指令内容

例子
FROM alpine:latest
MAINTAINER codesheep@163.com
ENTRYPOINT [ "ls", "-l"]
CMD ["-a"]
若以默认命令运行容器 可以发现 执行的是 ls -a -l 命令 ls -l -a
若 docker run 中增加参数 -t
docker run -it --rm --name test alpine:codesheep -t
也可以发现执行的是 ls -l -t 即 Dockerfile 中的 CMD 原参数被覆盖了ls -l -t
因此推荐的使用方式是
使用exec格式的 ENTRYPOINT指令 设置固定的默认命令和参数
CMD指令 设置可变的参数


不在 Dockerfile 做端口映射

Dockerfile 可以通过 EXPOSE指令 将容器端口映射到主机端口上 会导致镜像在一台主机上仅能启动一个容器
在 docker run 命令中来用 -p 参数来指定端口映射 而不要将该工作置于 Dockerfile 之中

#尽量避免这种方式
EXPOSE 8080:8899

#仅仅暴露端口
EXPOSE 8080
使用 Dockerfile 来共享镜像
推荐通过共享 Dockerfile 的方式来共享镜像 优点
通过 Dockerfile 构建的镜像用户可以清楚地看到构建的过程
Dockerfile 作为一个编排文件同样可以入库做版本控制  可以回溯