1. FROM:指明当前的镜像基于哪个镜像构建
用法:
- 1
示例:
- 1
写上这一行指令后,我们的 Dockerfile 就可以构建镜像了,构建出的镜像就是未做任何修改、没有执行任何命令的 alpine:latest
。
在 Docker 官方仓库里有很多高质量的服务镜像如 redis、mongo、mysql、httpd、php、tomcat 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 node、openjdk、python、ruby、golang 等。我们可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。如果没有找到对应服务的镜像,官方镜像中还提供了一些更为基础的操作系统镜像,如 ubuntu、debian、centos、fedora、alpine 等,这些操作系统的软件库为我们提供了更广阔的扩展空间。尽可能使用当前官方仓库作为构建镜像的基础。
2. LABEL: 标记镜像信息
给镜像添加标签来标记镜像信息,每个标签一行。
用法:
- 1
示例:
- 1
3. MAINTAINER:指定镜像的作者信息,包含镜像的所有者和联系人信息
用法:
- 1
示例:
- 1
这是一种语义化的表达方式,也可以用LABEL来标记
- 1
4. RUN : 运行命令
用法:
- 1
示例:
- 1
为了保持 Dockerfile 文件的可读性,以及可维护性,建议将长的或复杂的RUN
指令用反斜杠\
分割成多行。
例如:
- 1
- 2
- 3
这里需要注意一个关于软件源更新安装软件的问题。
如果我们需要更新软件源并安装软件源中的软件vim,在Linux环境中我们一般会执行这个的命令:
- 1
- 2
如果需要在镜像中安装软件,我们会想当然地在 Dockerfile 写成这样
- 1
- 2
Dockerfile 构建一次之后,apt update
构建的镜像层就会缓存到本地,无论后面这个 Dockerfile 如何更新 apt install
的内容,apt update
镜像缓存也不会更新,这会导致安装的始终是第一次 Dockerfile构建时获取的软件源版本,除非你手动删除这些缓存镜像层。
解决的方法很简单,用 RUN apt-get update && apt-get install -y
可以确保 Dockerfiles
每次安装的都是包的最新的版本。
5. CMD:指定容器的默认执行的命令。
建议用法:
- 1
示例:
- 1
docker run 没有指定其他命令时,CMD 指令会在容器执行。Dockerfile 中 CMD 只能有一个,如果写了多个 CMD,则以最后一个为准。
6. EXPOSE:指定容器将要监听的端口
用法:
- 1
示例:
- 1
启动容器时,如果我们使用自动映射 -P
或 --net=host
宿主机网络模式,容器中 EXPOSE
标记暴露的端口与宿主机网络会自动建立关联。
如果没有指定 EXPOSE
,使用 -p
手动指定端口映射参数也可以访问到容器内提供服务的端口。
EXPOSE
显式地标明镜像开放端口,一定程度上提供了操作的便利,也提高了 Dockerfile 的可读性和可维护性。
7. ENV:定义环境变量
用法:
- 1
示例:
- 1
8. COPY: 将宿主机文件拷贝到镜像中
用法:
- 1
示例:
- 1
除了指定完整的文件名外,COPY 命令还支持 Go 风格的通配符,比如:
- 1
- 2
- 3
- 4
对于目录而言,COPY 只复制目录中的内容而不包含目录自身。 如下目录结构:
- 1
- 2
- 3
- 1
镜像的 /tmp 目录下,将得到这样的文件结构:
- 1
- 2
- 3
如果要带目录拷贝到镜像中,需要使用:
- 1
ADD
和COPY
用法类似,一般优先使用 COPY。COPY 只支持简单将本地文件拷贝到容器中,而 ADD 还有从压缩包中提取文件的功能,如:
- 1
- 2
9. VOLUME:指定目录为数据卷存储方式
为了防止运行时用户忘记将需要保存数据的目录挂载为卷,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也不会向容器存储层写入大量数据。
用法:
- 1
示例:
- 1
这里的 /data
目录就会在运行时自动挂载为匿名卷,容器运行时使用 -v mydata:/data
可以覆盖这个挂载设置。
10. USER:指定运行容器时的用户名或 UID
用法:
- 1
- 2
- 3
示例:
- 1
当容器中运行的服务不需要管理员权限时,可以先建立一个特定的用户和用户组,为它分配必要的权限,然后通过该命令,使用 USER 切换到这个用户。
Tips:
- 使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。
- 使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。
我们可以在docker run
中使用-u
参数指定用户执行命令,来替代默认设定,如果为了精确控制用户的id,也可以传入uid。
- 1
11. WORKDIR: 切换到镜像中的指定路径
在WORKDIR
中需要使用绝对路径,如果镜像中对应的路径不存在,会自动创建此目录。
我们使用 WORKDIR 来替代 RUN cd <path> && <do something>
的这类切换目录进行操作的指令。
WORKDIR指令对ADD COPY等指令也生效,如下操作会将宿主机的test.txt 文件复制到 镜像的/tmp/test.txt。
- 1
- 2
12. ONBUILD:引用后构建指令
用法:
- 1
示例:
- 1
ONBUILD
是一个特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等。
- 1
- 2
- 3
- 4
使用上面 Dockerfile 在构建基础镜像的时候,这两行 ONBUILD 并不会被执行。它的效果等价于:
- 1
- 2
构建出来的镜像作为基础镜像,在其他 Dockerfile 的 FROM
指令中被引用,去构建新镜像的时候,ONBUILD 后的指令会执行。
13. 小结
本节介绍了我们使用 Dockerfile 构建镜像的过程中经常会用到的指令,这些指令大多简单易懂的。但本节中也提到,其中有些指令的用法比较特殊,在某些看似“理所当然”的使用方法下,可能会出现"bug",请大家一定要留意。后面也有实战章节,帮助大家加深理解。