Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
1 FROM指定基础镜像
FROM 指令用于指定其后构建新镜像所使用的基础镜像。该指令必须是Dockerfile文件中的首条命令(非注释行)。启动构建流程后,Docker将会基于该镜像构建新的镜像,FROM后的命令也会基于这个基础镜像.
FROM语法格式为:
FROM <image>
FROM <image>:<tag>
FROM <image>:<digest>
注意事项:
- FROM 必须 是 Dockerfile 中第一条非注释命令
- 在一个 Dockerfile 文件中创建多个镜像时,FROM 可以多次出现。只需在每个新命令 FROM 之前,记录提交上次的镜像 ID。
- tag 或 digest 是可选的,如果不使用这两个值时,会使用 latest 版本的基础镜像
2 WORKDIR 指定工作目录
WORKDIR 用于在容器内设置一个工作目录:
WORKDIR /path/to/workdir
通过WORKDIR设置工作目录后,Dockerfile 中其后的命令 RUN、CMD、ENTRYPOINT、ADD、COPY 等命令都会在该目录下执行。 如,使用WORKDIR设置工作目录:
WORKDIR /test
WORKDIR test1
WORKDIR test2
RUN pwd
在以上示例中,pwd 最终将会在 /test/test1/test2 目录中执行。在使用 docker run 运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。
3 RUN 命令执行
在构建镜像的过程中需要执行的特定命令,生成一个中间的镜像
#shell格式
RUN <command> #RUN apk updat
#exec格式
RUN ["executable", "param1", "param2"] #RUN ["/bin/bash","-c","yum install -y gcc"] #json序列
注意事项
- RUN命令将在当前image中执行任意合法命令并提交结果,命令执行提交后,就会自动执行Dockerfile中的下一个命令
- 层级RUN指令和生成提交是符合Dockerh核心理念,它允许像版本控制那样在任意一个点对镜像进行定制化构建
- RUN指令创建的中间镜像会被缓存,并在下次构建中使用,如不想使用缓存镜像,可以在构建过程中指定
--no-cache参数
4 COPY&ADD 复制文件
命令使用方式
COPY <源路径>... <目标路径>
COPY ["<源路径1>",... "<目标路径>"]
ADD <源路径>... <目标路径>
ADD ["<源路径>",... "<目标路径>"]
对于COPY 和ADD命令来说如果要把本地文件copy到镜像中,本地文件必须包含在上下文目录中(该命令不能copy上下文之外的本地文件到镜像中)。
COPY 和ADD命令与WORKDIR协同工作,在设置了 WORKDIR 命令后,接下来的 COPY 和 ADD 命令中的相对路径就是相对于 WORKDIR 指定的路径
WORKDIR /app
COPY test.sh .
构建后生产的镜像中文件路径/app/test.sh,test.sh 文件就是被复制到了 WORKDIR /app 目录下。
4.1 COPY 复制文件
如果仅仅是把本地的文件拷贝到容器镜像中,COPY 命令是最合适不过的。其命令的格式为:
COPY
除了指定完整的文件名外,COPY 命令还支持 Go 风格的通配符,比如:
COPY test* /testdir/ # 拷贝所有 test 开头的文件
COPY test?.log /testdir/ # ? 是单个字符的占位符,比如匹配文件 test1.log
对于目录而言,COPY 和 ADD 命令具有相同的特点:只复制目录中的内容而不包含目录自身。 比如我们在 Dockerfile 中添加下面的命令:
WORKDIR /app
COPY test .
构建后生产的镜像中文件路径
/app
test1.log, test2.log
test1.log, test2.log文件就是被复制到了 WORKDIR /app 目录下,但是并没有包含test目录本身。如果想让 test1.log 和 test2.log 还保存在 test目录中,需要在目标路径中指定这个目录的名称,如
WORKDIR /app/test #方式1
======================================
WORKDIR /app #方式2
COPY test ./test
COPY 命令区别于 ADD 命令的一个用法是在 multistage (多阶段构建)场景下,在 multistage 的用法中,可以使用 COPY 命令把前一阶段构建的产物拷贝到另一个镜像中,比如:
4.2 ADD 复制文件
ADD 命令的格式和 COPY 命令相同,也是:
ADD <src> <dest>
但是ADD命令不能用在 multistage 的场景下,不过除了这一点外,ADD 命令可以完成 COPY 命令的所有功能,并且还可以完成两类超酷的功能:
- 解压压缩文件并把它们添加到镜像中,当是可识别的压缩包如gzip、bzip2等tar包时,首先会将包添加到镜像中,然后自动解压。这可以说是与COPY命令在使用中的最大的区别,最佳使用场景:
WORKDIR /app
ADD .tar.gz .
- 从 url 拷贝文件到镜像中,但是docker官方文档最佳实践并不建议这么用,docker 官方建议我们当需要从远程复制文件时,最好使用 curl 或 wget 命令来代替 ADD 命令。原因是,当使用 ADD 命令时,会创建更多的镜像层,当然镜像的 size 也会更大
5 MAINTAINER
格式为 MAINTAINER <name>,指定维护者信息。
注意:MAINTAINER 指令已经被抛弃,建议使用 LABEL 指令。
LABEL
格式为:LABEL <key>=<value> <key>=<value> <key>=<value>
6 ENV设置环境变量
格式有两种:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
这个指令很简单,就是设置环境变量而已,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。
7 EXPOSE 容器监听端口
为构建的镜像设置监听端口,使容器在运行时监听。格式:
EXPOSE <port> [<port>...]
EXPOSE 指令并不会让容器监听宿主机的端口,监听主机端口需要在 docker run 时使用 -p、-P 参数来发布容器端口到宿主机的某个端口上。
8 VOLUME 定义卷
VOLUME用于创建挂载点,即向基于所构建镜像创始的容器添加卷,格式为:
VOLUME ["/data"]
也可以使用 VOLUME 指令添加多个数据卷:
VOLUME ["/data1", "/data2"]
一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
- 卷可以容器间共享和重用
- 容器并不一定要和其它容器共享卷
- 修改卷后会立即生效
- 对卷的修改不会对镜像产生影响
- 卷会一直存在,直到没有任何容器在使用它
VOLUME 让我们可以将源代码、数据或其它内容添加到镜像中,而又不并提交到镜像中,并使我们可以多个容器间共享这些内容。
9 CMD
CMD用于指定在容器启动时所要执行的命令。CMD 有以下三种格式:
CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
省略可执行文件的 exec 格式,这种写法使 CMD 中的参数当做 ENTRYPOINT 的默认参数,此时 ENTRYPOINT 也应该是 exec 格式,具体与 ENTRYPOINT 的组合使用,参考 ENTRYPOINT。
注意事项: 与 RUN 指令的区别:RUN 在构建的时候执行,并生成一个新的镜像,CMD 在容器运行的时候执行,在构建时不进行任何操作。
10 ENTRYPOINT
ENTRYPOINT 用于给容器配置一个可执行程序。也就是说,每次使用镜像创建容器时,通过 ENTRYPOINT 指定的程序都会被设置为默认程序。ENTRYPOINT 有以下两种形式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数(经典操作:ENTRYPOINT + CMD = 默认容器命令参数),不同的是通过docker run执行的命令不会覆盖 ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给 ENTRYPOINT。Dockerfile 中只允许有一个 ENTRYPOINT 命令,多指定时会覆盖前面的设置,而只执行最后的 ENTRYPOINT 指令。
docker run运行容器时指定的参数都会被传递给 ENTRYPOINT ,且会覆盖 CMD 命令指定的参数。如,执行docker run <image> -d时,-d 参数将被传递给入口点。
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:
<ENTRYPOINT> "<CMD>"
也可以通过docker run --entrypoint重写 ENTRYPOINT 入口点。