3. Dockerfile 详解
Docker 的架构很有魅力,他拥有类似于虚拟机性质的隔离机制,但并不是严格意义上的虚拟机。我还是喜欢拿货轮举例,以前我们是一条小船运一个集装箱的货物,现在可以把 N 个集装箱扔到一条大货轮上。每个容器(集装箱)共用宿主机(货轮)的内核(运载力),Dockerfile 就像是每个集装箱中的货物清单和说明书,一般由以下五部分构成:
3.1 基础指令
FROM: 指定基础镜像,且必须位于第一行,使用格式如下:
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
Docker 的原理基于 Linux 内核的隔离技术,且 Linux From Scratch,因此 FROM scratch 是 docker 中最基础的镜像,debian、ubuntu 和 centos 等都基于 scratch 之上。在实际的运用中,如果必须从零开始搭建镜像的一般都选择 FROM debian 作为基础镜像,不过大多数情况下一般都会以如下:FROM python、FROM nginx、FROM java 等为基础镜像。
**MAINTAINER:**指定维护者信息,例:MAINTAINER user user@mail.com。
3.2 控制指令
RUN: 在构建的过程中指定需要被执行的命令,使用格式如下:
RUN command param1 param2 # 更推荐
RUN ["executable","param1","param2"]
WORKDIR: 用于切换构建过程中的工作目录,例:WORKDIR project。可配合环境变量使用,例:
ENV BASEDIR /project
WORKDIR $BASEDIR/test
ONBUILD: 在当前镜像被当做基础镜像时,执行其携带指令,例:
ONBUILD RUN echo "hello world"
“hello world”会在子镜像被构建的过程中输出。
3.3 引入指令
COPY: 拷贝文件或目录,格式:
COPY <src> <dest>
COPY ["<src>","<dest>"]
ADD: 在COPY的基础之上,ADD可识别压缩文件,例:ADD rootfs.tar.xz /。理论上也可添加网络地址,但还是建议在 RUN 指令中执行 wget 或 curl 命令,感觉这样更加可控。实际应用中我喜欢将 COPY 用于文件,ADD 用于目录(仅我个人的使用习惯)。
3.4 执行指令
CMD: 容器启动时需要执行的命令,格式:
在这里插入代码片CMD ["executable","param1","param2"] # 更推荐
CMD ["param1","param2"]
CMD command param1 param2
若在 docker run 中指定启动命令,则 CMD 将被覆盖。
ENTRYPOINT: 主程序启动前的准备指令,用于启动主程序所依赖的服务,格式同CMD(基本上没用过就不介绍了,而且容易出错,不推荐使用)。
3.5 配置指令
- EXPOSE: 暴露容器端口,格式:EXPOSE […],注意此处的暴露端口和docker run 中-p指定的映射端口是两个概念。
- ENV: 声明环境变量,格式:ENV = …。
- LABEL: 标记,格式:LABEL =…。
- USER: 设置启动容器的用户,格式:USER daemo。
- ARG: 设置变量,格式同ENV。
- STOPSIGNAL: 容器停止时给应用程序发出的信号,例:STOPSIGNAL SIGKELL。
- SHELL: 指定shell,例:SHELL [“bash”,“-c”]。