Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。
文件格式
Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,’#’ 为 Dockerfile 中的注释。
- 注释: 以 # 开头的是注释语句
- 指令:
INSTRUCTION argument
常用指令
FROM
指定基础镜像。
FROM [image] # 使用 latest 版本
FROM [image:tag] # 使用指定版本
- 必须是已经存在的基础镜像
- 必须是第一条非注释指令
MAINTAINER
指定镜像的作者信息,包括镜像的所有者和联系信息。
MAINTAINER [name]
示例:
MAINTAINER quanzaiyu
MAINTAINER 731734107@qq.com
MAINTAINER quanzaiyu <731734107@qq.com>
RUN
指定当前镜像中运行的命令。
RUN [command] # shell 模式
RUN ["executable", "param1", "param2"] # exec 模式
在 shell 模式下,是以 /bin/sh -c command
开始执行命令。
比如:
RUN echo hello
在 exec 模式下,可以使用其他的 shell 执行命令。
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用 (因此, 不要过多书写 RUN 指令,尽量将多个命令合并)。如果不想使用这些缓存镜像,可以在构建时指定—no-cache参数,如:docker build —no-cache
EXPOSE
指定运行该镜像的容器使用的端口。
EXPOSE [port1] [port2] ...
但是运行时Docker并不会自动开启对应服务,还需要手动开启对应的服务并添加端口的映射指令,比如:
$ docker run --name nginx-server -p 80 -d ubuntu:latest nginx -g "daemon off;"
CMD
跟 RUN 命令使用方法类似,也是运行一个指令:
CMD [command] # shell 模式
CMD ["executable", "param1", "param2"] # exec 模式
CMD ["param1", "param2"] # 作为 ENTRYPOINT 指令的默认参数
与 RUN 命令的区别:
- RUN 命令时在镜像构建时运行
- CMD 命令是在容器启动时运行
比如:
CMD ['/usr/sbin/nginx', '-g', 'deamon off;']
指定 CMD 命令之后,运行容器的时候就不需要在后面加上运行参数了,不过还是得指定端口映射:
$ docker run --name nginx-server -p 80 -d ubuntu:latest
:::info 如果在启动一个容器时,指定了运行时命令,则 CMD 中的命令会被覆盖。 :::
ENTRYPOINT
也是运行一个命令,与 RUN 不同的是,ENTRYPOINT 中的指令不会被运行容器时覆盖。
ENTRYPOINT [command] # shell 模式
ENTRYPOINT ["executable", "param1", "param2"] # exec 模式
运行容器时如果必须覆盖 ENTRYPOINT 中的命令,需要使用以下命令进行覆盖:
$ docker run --entrypoint [command]
ADD 和 COPY
ADD 和 COPY 都是复制文件。
ADD [src]... [dest]
ADD ["src"... "dest"] # 适用于文件路径中有空格的情况
COPY [src]... [dest]
COPY ["src"... "dest"] # 适用于文件路径中有空格的情况
区别为:ADD 包含了类似 tar 的解压功能。
- ADD: 将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget
- COPY: 功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
如果只是简单的复制文件,推荐使用 COPY。
VOLUME
用于指定持久化目录。
格式:
VOLUME ["/path/to/dir"]
示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"
注:一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
- 卷可以容器间共享和重用
- 容器并不一定要和其它容器共享卷
- 修改卷后会立即生效
- 对卷的修改不会对镜像产生影响
- 卷会一直存在,直到没有任何容器在使用它
WORKDIR
设置工作目录,即创建容器后进入的目录,类似于cd命令。
格式:
WORKDIR /path/to/dir
示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
注:通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用 docker run
运行容器时,可以通过-w
参数覆盖构建时所设置的工作目录。
ENV
设置环境变量。
格式:
ENV <key> <value> # <key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key>=<value> ... # 可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy myDog=Rex
USER
指定容器为哪个用户运行,可以使用uid(用户)和gid(用户组),以及其组合。默认使用 root 用户。
USER daemon
有以下几种组合:
USER user
USER user:group
USER user:gid
USER uid
USER uid:group
USER uid:gid
ONBUILD
ONBUILD 用于设置镜像触发器。当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被触发。
格式:
ONBUILD [INSTRUCTION]
示例:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
LABEL
用于为镜像添加元数据。
格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
注:使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。
ARG
用于指定传递给构建运行时的变量。
格式:
ARG <name>[=<default value>]
示例:
ARG site
ARG build_user=www
Dockerfile 示例
使用Ubuntu构建一个nginx容器
FROM ubuntu:14.04
MAINTAINER quanzaiyu "quanzaiyu@163.com"
ENV REFERSH_DATE 2015-04-01
RUN apt-get update && apt-get install -y nginx
COPY index.html /usr/share/nginx/html # 将宿主机的文件覆盖到容器中
EXPOSE 80
ENTRYPOINT ['/usr/sbin/nginx', '-g', 'deamon off;']
CMD echo 'created'
为 CentOS 安装常用工具
FROM centos:latest
RUN yum update -y && yum install net-tools.x86_64 -y
EXPOSE 80
CMD /bin/bash
Dockerfile 构建过程
- 从基础镜像运行一个容器
- 执行一条指令,对容器做出修改
- 执行类似 docker commit 的操作,提交一个新的镜像层
- 再基于刚提交的镜像运行一个新容器
- 执行 Dockerfile 中的下一条指令,直至所有指令执行完毕
构建过程中,会生成一些中间层镜像,可以使用中间层镜像进行调试,便于定位错误的位置。
正常情况下,构建镜像会用到缓存,这样可以提升构建速度,但有的时候不想用缓存,可以在构建命令中加入 --no-cache
选项。
另外,修改环境变量也可以刷新缓存,比如上面的 Dockerfile 示例中,改变 REFERSH_DATE 的值即可。
可以使用 docker history
命令查看镜像的构建过程。
使用 Dockerfile 构建镜像
docker build 命令用于从 Dockerfile 构建镜像
可以在 docker build 命令中使用 -f 标志指向文件系统中任何位置的 Dockerfile, 加上 -t 为构建的镜像打标签
docker build -t '731734107/test' -f /path/to/a/Dockerfile # 以指定路径的Dockerfile进行构建
如果 Docker 文件就在当前目录,则不需要显式指定Dockerfile的路径:
docker build -t "731734107/test" .