简介
Dockerfile 是由一系列命令和参数构成的脚本,这些命令应用于操作系统基础镜像并最终创建的一个新镜像;
生产实践中一定优先使用 Dockerfile 的方式构建镜像。
基础镜像体积应该尽量小
尽量减少 Dockerfile 的行数,因为 Dockerfile 的每一条指令都会生成一个镜像层。
Dockerfile 书写原则
单一职责:由于容器的本质是进程,一个容器代表一个进程,因此不同功能的应用应该尽量拆分为不同的容器,每个容器只负责单一业务进程。
提供注释信息:
Dockerfile也是一种代码,我们应该保持良好的代码编写习惯,晦涩难懂的代码尽量添加注释,让协作者可以一目了然地知道每一行代码的作用,并且方便扩展和使用。保持容器最小化:应该避免安装无用的软件包,可以加快容器构建速度,而且可以避免镜像体积过大。
合理选择基础镜 :容器的核心是应用,因此只要基础镜像能够满足应用的运行环境即可
使用
.dockerignore文件 : 使用.dockerignore在构建时,忽略一些不需要参与构建的文件,从而提升构建效率。尽量使用构建缓存 :
Docker构建过程中,每一条Dockerfile指令都会提交为一个镜像层,下一条指令都是基于上一条指令构建的。如果构建时发现要构建的镜像层的父镜像层已经存在,并且下一条命令使用了相同的指令,即可命中构建缓存。
- 正确设置时区: 从
Docker Hub拉取的官方操作系统镜像大多数都是UTC时间 , 也可以运行时指定-e TZ=Asia/Shanghai
1 | # Debian |
- 使用国内软件源加快镜像构建速度: 最好的方式是换源
- 最小化镜像层数
常用命令
FROM image:tag : 使用的基础镜像构建MAINTAINER user_info : 声明镜像维护者信息LABEL value : 镜像描述元信息 (可以多条)ENV key value : 设置环境变量 (可以多条)RUN command : 构建镜像时需要运行的命令 (可以多条)WORKDIR path_dir : 设置终端默认登录进来的工作目录EXPOSE port : 当前容器对外暴露出的端口ADD source_dir/file dest_dir/file : 宿主机内文件复制到容器,压缩文件会解压,也可以获取远程文件COPY source_dir/file dest_dir/file : 宿主机内文件复制到容器,不过压缩文件不解压VOLUME : 创建一个 可以从本机或其他容器挂载的挂载点,一般用来存放数据库和需要保存的数据CMD : 指定容器启动时要运行的命令,多个CMD,最后一个生效 CMD ENTRYPOINT : 指定容器启动时要运行的命令,最后一个才有用ONBUILD : 为子镜像服务
示例
简单实例:父镜像 Dockerfile:1
2
3
4
5
6FROM centos
ONBUILD RUN yum -y install vim
CMD /bin/bash
子镜像简单点:
FROM parent
Dockerfile
1 | FROM centos |
多阶构建
多阶段构建可以通过一个 Dockerfile 很方便地构建出体积更小的镜像,只需要编写 Dockerfile 文件即可,无须借助外部脚本文件
1 | # 编译代码 |
与上面的效果一样1
2
3
4
5
6
7
8
9
10
11
12
13
14FROM golang:1.13 AS builder # 使用 AS 指令将这个阶段命名为 builder
WORKDIR /go/src/github.com/wilhelmguo/multi-stage-demo/
COPY main.go .
RUN CGO_ENABLED=0 GOOS=linux go build -o http-server .
FROM alpine:latest
WORKDIR /root/
# 可以使用 --from=builder,使得 Dockerfile 更加清晰可读
COPY --from=builder /go/src/github.com/wilhelmguo/multi-stage-demo/http-server .
# COPY --from=nginx:latest /etc/nginx/nginx.conf /etc/local/nginx.conf # 拷贝 nginx 官方镜像的配置文件到我们自己的镜像中时
CMD ["./http-server"]
在执行 docker build 命令时添加 target 参数,可以将构建阶段停止在指定阶段1
docker build --target builder -t http-server:latest .
补充说明
cmd 与 ENTRYPOINT
CMD 和 ENTRYPOINT 的基本使用格式分为两种:
第一种为 CMD/ENTRYPOINT["command" , "param"] 。这种格式是使用 Linux 的 exec 实现的, 一般称为 exec 模式,这种书写格式为CMD/ENTRYPOINT 后面跟 json 数组,也是 Docker 推荐的使用格式。
另外一种格式为 CMD/ENTRYPOINT command param ,这种格式是基于 shell 实现的, 通常称为 shell 模式。当使用 shell 模式时,Docker 会以 /bin/sh -c command 的方式执行命令.
Dockerfile 中如果使用了 ENTRYPOINT 指令,启动 Docker 容器时需要使用 --entrypoint 参数才能覆盖 Dockerfile 中的 ENTRYPOINT 指令 ,而使用 CMD 设置的命令则可以被 docker run 后面的参数直接覆盖。
ENTRYPOINT 指令可以结合 CMD 指令使用,也可以单独使用,而 CMD 指令只能单独使用