Skip to content

Dockerfile

镜像的定制实际上就是定制每一层所添加的配置、文件。

在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。

每个 RUN 都会创建一个层

COPY

优先使用 COPY 而不是 ADD

sh
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

目标路径 没有会自动创建

COPY 会保留数据的元属性,如 rwx

sh
COPY --chown=55:mygroup files* /mydir/

ADD

更高级的 COPY

会自动解压 tar 的 gzip, bzip2, xz

CMD

尽量使用双括号

用于指定默认的容器主进程的启动命令的

sh
CMD <>

CMD ["可执行文件", "参数1", "参数2"...]

Docker 是 进程,前台,不是后台,所以下面的命令将无效

sh
CMD service nginx start

ENTRYPOINT

todo

ENV

sh
ENV <key> <value>
ENV <key>=<value> ...
sh
ENV MYSQL_ROOT_PASSWORD=123456 \
    MYSQL_DATABASE="test" \
    MYSQL_USER=test \
    MYSQL_PASSWORD=123456

ARG

ARG 是 构建时的环境变量

不要将敏感数据放入 ARG

如:

sh
ARG DOCKER_USERNAME=library

FROM ${DOCKER_USERNAME}/alpine

RUN set -x ; echo ${DOCKER_USERNAME}

VOLUME

设置 匿名卷

sh
VOLUME /data
sh
$ docker run -d -v mydata:/data xxxx

EXPOSE

声明容器打算使用什么端口,并不会自动在宿主进行端口映射。

sh
EXPOSE <端口1> [<端口2>...]

-p <宿主端口>:<容器端口>

WORKDIR

指定工作目录

目录不存在会自动创建

sh
# 无效代码
RUN cd /app
RUN echo "hello" > world.txt
sh
# 正确代码
WORKDIR /app
RUN echo "hello" > world.txt

关于路径切换

sh
WORKDIR /a
WORKDIR b
WORKDIR c

RUN pwd

# RUN pwd 的工作目录为 /a/b/c

USER 指定用户

sh
USER <用户>[:<用户>]
sh
USER redis

HEALTHCHECK

通过指定一行命令,来判断容器主进程的服务状态是否还正常

sh
HEALTHCHECK [选项] CMD <命令>

命令的返回值决定了是否健康

  • 0:成功;
  • 1:失败
  • 2:保留。不要用 2

HEALTHCHECK 支持下列选项:

  • --interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
  • --timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
  • --retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。
sh
HEALTHCHECK --interval=5s --timeout=3s \
  CMD curl -fs http://localhost/ || exit 1

LABEL

以键值对的形式添加一些元数据(metadata)。

sh
LABEL org.opencontainers.image.authors="yeasy"

LABEL org.opencontainers.image.documentation="https://yeasy.gitbooks.io"

SHELL

指定 shell,默认是 ["/bin/sh", "-c"]

RUN ENTRYPOINT CMD 都会受其影响

ONBUILD

ONBUILD 跟其他指令,不会执行。只有当前 image 被作为其他镜像基础镜像时候,才会生效

build

sh
docker build [选项] <上下文路径/URL/->

Context

docker build 并非在 Docker 客户端运行,而是在 Docker 服务器,也就是 Docker 引擎

sh
docker build -t nginx:v3 .

上面命令中最后一个 . 是指定 context

未指定 dockerfile 时候,会在 context 中寻找 Dockerfile

Dockerfile 可以在 build 时候通过 -f 指定

比如

sh
COPY ./package.json /app/

COPY 复制是上下文指定的路径下的 package.json 文件

从 git repo 构建

sh
docker build -t hello-world https://github.com/docker-library/hello-world.git#master:amd64/hello-world

master 分支

amd64/hello-world 目录