DockerFile指令

Dockerfile指令包括:

Dockerfile 指令说明
FROM指定基础镜像,用于后续的指令构建。
MAINTAINER指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令)
LABEL添加镜像的元数据,使用键值对的形式。
RUN在构建过程中在镜像中执行命令。
CMD指定容器创建时的默认命令。(可以被覆盖)
ENTRYPOINT设置容器创建时的主要命令。(不可被覆盖)
EXPOSE声明容器运行时监听的特定网络端口。
ENV在容器内部设置环境变量。
ADD将文件、目录或远程URL复制到镜像中。
COPY将文件或目录复制到镜像中。
VOLUME为容器创建挂载点或声明卷。
WORKDIR设置后续指令的工作目录。
USER指定后续指令的用户上下文。
ARG定义在构建过程中传递给构建器的变量,可使用 “docker build” 命令设置。
ONBUILD当该镜像被用作另一个构建过程的基础时,添加触发器。
STOPSIGNAL设置发送给容器以退出的系统调用信号。
HEALTHCHECK定义周期性检查容器健康状态的命令。
SHELL覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。

通过 Dockerfile 中的这些指令,可以构建出一个完整的Docker 镜像。

1 基础指令

1)FROM
格式:
FROM <image>
FROM <image>:<tag>

解释:FROM是Dockerfile的第一条而且只能是除了首行注释之外的第一条指令。

2)MAINTAINER
格式:
MAINTAINER <name>

解释:指定该Dockerfile文件的维护者信息,类似我们在docker commit时候使用-a参数指定的信息。

3)RUN:(构建镜像) 运行命令(安装环境)

解释:执行命令并创建新的镜像层,通常用于安装软件包

格式:
RUN <command>                         (shell 模式)
RUN["executable", "param1", "param2"] (exec 模式:注意需要"双引号")
shell模式:RUN echo 1 ——/bin/sh -c ‘1 '

使用 shell 模式时,docker 会以 /bin/sh -c "task command" 的方式执行任务命令。也就是说容器中的 1号进程 不是任务进程而是 bash进程

exec模式:RUN ["echo", "1"] ——

exec 模式是建议使用的模式 [注意需要"双引号"]

——因为当运行任务的进程作为容器中的 1 号进程时,我们可以通过 docker 的 stop 命令优雅的结束容器(详情请参考《在 docker 容器中捕获信号》)。

4)ENTRYPOINT:只能一个or加上CMD传参

不会被替换,可以让镜像如同一个 可执行程序

ENTRYPOINT 的 Exec 格式用于设置容器启动时要执行的命令及其参数,同时可通过CMD命令或者命令行参数提供额外的参数。ENTRYPOINT 中的参数始终会被使用,这是与CMD命令不同的一点。

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参

格式:
   ENTRYPOINT ["executable", "param1","param2"]     (exec 模式)
   ENTRYPOINT command param1 param2                 (shell模式)

解释:每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个起效。

  • 下面是一个例子:
ENTRYPOINT ["/bin/echo", "Hello"]  

当容器通过 docker run -it [image] 启动时,输出为:

Hello

而如果通过 docker run -it [image] CloudMan 启动(run时指定额外参数),则输出为:

Hello CloudMan

将Dockerfile修改为:

ENTRYPOINT ["/bin/echo", "Hello"]  
CMD ["world"]

当容器通过 docker run -it [image] 启动时,输出为:

Hello world

而如果通过 docker run -it [image] CloudMan 启动,输出依旧为:

Hello CloudMan

ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器run启动时增加命令——动态替换掉。

5)CMD:单独or配合ENTRYPOINT

CMD 指令允许用户指定容器的默认执行的命令。此命令会在容器启动且 docker run 没有指定其他命令时运行。

格式:
    CMD <command>

能够被 run 后替换:设置容器启动后默认执行的命令及其参数,但CMD设置的命令能够被docker run命令后面的命令行参数替换

正确姿势

对于 CMD 和 ENTRYPOINT 的设计而言,多数情况下它们应该是单独使用的。 ——当然,有一个例外是 CMD 为 ENTRYPOINT 提供默认的可选参数

我们大概可以总结出下面几条规律:
    • 如果 ENTRYPOINT 使用了shell 模式,CMD 指令会被忽略。
    • 如果 ENTRYPOINT 使用了 [exec] 模式,CMD 指定的内容被追加为 ENTRYPOINT 指定命令的参数。
    • 如果 ENTRYPOINT 使用了 [exec] 模式,CMD 也应该使用 [exec] 模式。

  • 例子

ENTRYPOINT [ "sh" ]
CMD [ "/entrypoint.sh" ]
docker信号处理:stop=SIGTERM、kill=SIGKILL

参考: 在 docker 容器中捕获信号

6)EXPOSE:暴露端口
格式:
    EXPOSE <port> [<port>...]

解释:设置Docker容器对外暴露的端口号,Docker为了安全,不会自动对外打开端口,如果需要外部提供访问,还需要启动容器时增加-p或者-P参数对容器的端口进行分配。

2 文件编辑指令

1)ADD:复制(如果是压缩包则 [解压])
格式:
    ADD <src>... <dest>
    ADD ["<src>",... "<dest>"]

解释:将宿主机指定的文件复制到容器文件系统的中。
注意:如果源文件是个压缩文件,则docker会自动帮解压到指定的容器中。

2)COPY:复制(单纯)
格式:
    COPY <src>... <dest>
    COPY ["<src>",... "<dest>"]

解释:单纯复制文件场景,Docker推荐使用COPY。

3)VOLUME:匿名卷

默认Docker容器中数据都是 只读 的,要让它可写 + 并且可以共享给其他容器,就必须创建 VOLUME

VOLUME <路径>

VOLUME ["<路径1>", "<路径2>"...]

解释:VOLUME指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点。
注意:通过VOLUME指令创建的挂载点,无法指定主机上对应的目录,Docker会自动为这些挂载点分配一个主机上的匿名数据卷

关于卷(Volume):Dockerfile与Docker run

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。

为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在run运行时如果用户(忘了)没有指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

例如

VOLUME /data
  • 这里的 /data 目录就会在容器运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。

当然,运行容器时可以覆盖这个挂载设置。比如:

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

在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置——变成命名卷了。

3 环境指令

1)ENV:设置容器环境变量
格式:
    ENV <key> <value>
    ENV <key>=<value> ...
    ENV <key1>=<value1> \
    <key2>=<value2>...

解释:设置环境变量,可以在RUN之前使用,然后RUN命令时调用,容器启动时这些环境变量都会被指定。

ENV VERSION=1.0 DEBUG=on \
    NAME="Happy Feet"
2)ARG:Dockerfile内局部变量

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 –build-arg <参数名>=<值> 来覆盖。

3)WORKDIR:切换目录(cd)
格式:
WORKDIR /path/to/workdir                    (shell 模式)

解释:切换目录,为后续的RUN、ENTRYPOINT 指令配置工作目录,相当于cd。
可以使用多个WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。
进入容器后进入 最后一个 WORKDIR目录

举例:  
WORKDIR /a  
WORKDIR b  
WORKDIR c  
RUN pwd  
则最终路径为 /a/b/c(进入容器后默认进入此目录)

DockerFile 构建镜像

docker build 命令用于使用 Dockerfile 创建镜像。


# 创建镜像:使用当前目录的Dockerfile(点.)
docker build -t 标签/名 .

# 使用网络url的Dockerfile创建镜像
docker build github.com/creack/docker-firefox

Dockerfile实践

1)编辑Dockerfile文件

# 基础镜像
FROM ubuntu
# 镜像作者
MAINTAINER '[email protected]'

# 执行操作
ADD ./example.tar /
COPY ./example.tar /
VOLUME ["/data"]

# 启动指令
ENTRYPOINT /bin/bash

2)创建镜像

docker build -t test:v1.0 .

3)查看镜像

docker images

4)创建容器并查看

docker run -it test:v1.0 /bin/bash
  • ADD解压复制与COPY直接复制

镜像效果查看.png

更新:使用alpine作为基础镜像,运行python项目

FROM alpine:3.11


#系统环境
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g'  /etc/apk/repositories && \
    apk update && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone 

#python环境
WORKDIR /app
COPY requirements.txt /app
ARG PYPI_MIRROR=https://mirrors.aliyun.com/pypi/simple
RUN apk add python3 py3-pip tzdata libffi-dev python3-dev openssl-dev freetds-dev libc-dev gcc && \
    pip3 install -i $PYPI_MIRROR -r /app/requirements.txt && \
    rm -rf /app  ~/.cache/pip /var/cache/apk/*