Dockerfile 指令详解
在上一节的 Dockerfile 例子中,我们用到了几个指令,比如:FROM, MAINTAINER,RUN,EXPOSE等等,Dockerfile 构建镜像需要用到的指令当然不止这些,下面是我们将介绍常用的构建指令 。
1. FROM:指明当前的镜像基于哪个镜像构建
用法:
FROM <基础镜像:版本>
示例:
FROM alpine:latest
写上这一行指令后,我们的 Dockerfile 就可以构建镜像了,构建出的镜像就是未做任何修改、没有执行任何命令的 alpine:latest
。
在 Docker 官方仓库里有很多高质量的服务镜像如 redis、mongo、MysqL、httpd、PHP、tomcat 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 node、openjdk、python、ruby、golang 等。我们可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。如果没有找到对应服务的镜像,官方镜像中还提供了一些更为基础的操作系统镜像,如 ubuntu、debian、centos、fedora、alpine 等,这些操作系统的软件库为我们提供了更广阔的扩展空间。尽可能使用当前官方仓库作为构建镜像的基础。
2. LABEL: 标记镜像信息
用法:
LABEL <标签>=<描述>
示例:
LABEL MYLABEL="First Test"
3. MAINTAINER:指定镜像的作者信息,包含镜像的所有者和联系人信息
用法:
MAINTAINER <NAME>
示例:
MAINTAINER nickname@domain.com
这是一种语义化的表达方式,也可以用LABEL来标记
LABEL maintainer="nickname@domain.com"
4. RUN : 运行命令
用法:
RUN <命令>
示例:
RUN echo 'text' > test.txt
为了保持 Dockerfile 文件的可读性,以及可维护性,建议将长的或复杂的RUN
指令用反斜杠\
分割成多行。
例如:
RUN apt update && apt install -y \
vim \
emacs
这里需要注意一个关于软件源更新安装软件的问题。
如果我们需要更新软件源并安装软件源中的软件vim,在Linux环境中我们一般会执行这个的命令:
apt update
apt install -y vim
如果需要在镜像中安装软件,我们会想当然地在 Dockerfile 写成这样
RUN apt update
RUN apt install -y vim
Dockerfile 构建一次之后,apt update
构建的镜像层就会缓存到本地,无论后面这个 Dockerfile 如何更新 apt install
的内容,apt update
镜像缓存也不会更新,这会导致安装的始终是第一次 Dockerfile构建时获取的软件源版本,除非你手动删除这些缓存镜像层。
5. CMD:指定容器的默认执行的命令。
建议用法:
CMD ["可执行命令", "参数1", "参数2"...]
示例:
CMD ["echo" "hello"]
Tips:ENTRYPOINT 与 CMD 类似,但不会被
docker run
指定的命令覆盖。
6. EXPOSE:指定容器将要监听的端口
用法:
EXPOSE 端口号
示例:
EXPOSE 8080
如果没有指定 EXPOSE
,使用 -p
手动指定端口映射参数也可以访问到容器内提供服务的端口。
EXPOSE
显式地标明镜像开放端口,一定程度上提供了操作的便利,也提高了 Dockerfile 的可读性和可维护性。
7. ENV:定义环境变量
用法:
ENV 环境变量名 环境变量值
示例:
ENV PATH /usr/local/Nginx/bin:$PATH
Tips:
- 通过 ENV 定义的环境变量,可以被后面的所有指令中使用,但是不能被 CMD 指令使用。
- 通过 ENV 定义的环境变量,会永久的保存到该镜像创建的任何容器中,我们可以在 docker run 命令中通过 -e 标记来传递环境变量,启动的容器将会使用我们指定的变量值。
- ARG 指令与 ENV 作用基本一致,区别在于它仅在构建过程中使用,不会保留到容器中。
用法:
示例:
copY app.py /web/
# * 是任意字符的占位符,匹配文件 test11 test22
copY test* /tmp
# ? 是单个字符的占位符,匹配文件 test1.txt test2.txt
copY test?.txt /tmp
testdir/
├── file1
└── file2
copY testdir /tmp
镜像的 /tmp 目录下,将得到这样的文件结构:
tmp/
├── file1
└── file2
如果要带目录拷贝到镜像中,需要使用:
copY testdir /tmp/testdir
# 宿主机压缩包test.tar 解压到 镜像/tmp中
ADD test.tar /tmp
9. VOLUME:指定目录为数据卷存储方式
用法:
VOLUME ["<路径1>", "<路径2>"...]
示例:
VOLUME ["/data"]
这里的 /data
目录就会在运行时自动挂载为匿名卷,容器运行时使用 -v mydata:/data
可以覆盖这个挂载设置。
10. USER:指定运行容器时的用户名或 UID
用法:
USER <user>[:<group>]
或
USER <UID>[:<GID>]
示例:
USER www
Tips:
docker run -i -t -u 1001 busyBox sh
11. workdir: 切换到镜像中的指定路径
我们使用 workdir 来替代 RUN cd <path> && <do something>
的这类切换目录进行操作的指令。
12. ONBUILD:引用后构建指令
用法:
ONBUILD <其他指令>
示例:
ONBUILD copY . /tmp/
FROM alpine:latest
ONBUILD RUN mkdir /app
ONBUILD copY . /app/
CMD [ "echo", "hello" ]
使用上面 Dockerfile 在构建基础镜像的时候,这两行 ONBUILD 并不会被执行。它的效果等价于:
FROM alpine:latest
CMD [ "echo", "hello" ]
构建出来的镜像作为基础镜像,在其他 Dockerfile 的 FROM
指令中被引用,去构建新镜像的时候,ONBUILD 后的指令会执行。