# Dockerfile

Dockerfile 是用来描述文件的构成的文本文档,其中包含了用户可以在使用行调用以组合 Image 的所有命令,用户还可以使用Docker build 实现连续执行多个命令指今行的自动构建。

通过编写 Dockerfile 生成镜像,可以为开发、测试团队提供基本一致的环境,从而提升开发、测试团队的效率,不用再为环境不统一而发愁,同时运维也能更加方便地管理我们的镜像。

Dockerfile 的语法非常简单,常用的只有 11 个:

命令 说明
FROM 基于哪个镜像来实现
MAINTAINER 镜像的作者
ENV 声明环境变量
RUN 执行命令
ADD 添加宿主机文件到容器里,\n有需要解压的文件会自动解压
COPY 添加宿主机文件到容器里
WORKDIR 工作目录
EXPOSE 容器内应用可使用端口
CMD 容器启动后所执行的程序。\n如果执行 docker run 后面跟启动命令会被覆盖掉
ENTRYPOINT 与 CMD 功能相同,但是 docker run 不会覆盖。\n如果需要覆盖可增加参数 --entrypoint 来覆盖
VOLUME 将宿主机容器的目录挂载到容器里

# 1. docker build

Docker CLI 为我们提供了 docker build 命令,通过这个命令,我们能够以 Dockerfile 中约定的流程构建对应的镜像。

Docker 根据 Dockerfile 建立镜像的每一步操作都会生成一层镜像。在建立每一层镜像的时候, Docker 都会先查找本地的镜像库中是否含有需要构建的镜像,如果有,就会直接采用这个镜像,可以从构建过程的输出中看到 ---> Using cache 的字样,表示构建此镜像层时采用了本地己有的镜像。逐个对操作生成单独的镜像层,实现了拆分镜像和对镜像层高效利用的效果。

需要注意的是,在 docker build 命令接收的参数中,提供给 docker build 命令的 -f 选项应该 Dockerfile 路径名。如果 Dockerfile 文件就叫 Dockerfile 那么文件名可省略,如果 Dockerfile 文件就在当前目录下,那么 -f 选项可省略。

docker build -f ./Dockerfile -t xxx .
# 等同于
docker build -f . -t xxx .
# 等同于
docker build -t xxx .

如果你的 Dockerfile 在别处,而且还不叫 Dockerfile 那么你的 docker build 命令就应该形如如下形式:

docker build -f /xxx/yyy/zzz -t xxx .

在上面的例子中,你的 Dockerfile 在 /xxx/yyy 下,名为 zzz

docker build 命令后 . 号的意思

在 docker build 命令中,最后的 . 号不是用来指定 Dockerfile 文件所在的位置的!-f 参数才是用来指定 Dockerfile 的路径的!

那么 . 号究竟是用来做什么的呢?

Docker 是 CS 结构,分为客户端和服务端(和 MySQL 一样)。我们日常对 Docker 的使用和操作,实际上一直都是在和 docker client 打交道,而 docker client 将我们输入的命令 “交给” docker server,等待 docker server 的执行,接收 docker server 的返回,然后再展现给我们看。

镜像的创建工作是由 Docker Server 创建的,而不是 Docker CLI 。那么如果在 Dockerfile 中使用了一些 COPY 等指令来操作文件,如何让 Docker Server 获取到这些文件呢?毕竟 Docker CLI 中的 “当前目录” 下有 xxx 文件,你不能保证 Docker Server 的 “当前目录” 下也有 xxx 文件啊。

这里就有了一个 “镜像构建上下文” 的概念。简单来说,它就是一个由用户指定的用于构建镜像的文件夹,这个文件夹中理应包含所有和构建有关的所有的内容,Docker CLI 再执行 docker build 命令时,会将这个文件夹都打包上传给 Docker Server ,这样 Docker Server 在构建镜像的过程中自然就能找到 Dockerfile 中所说的 xxx 文件了。

docker build 命令中的 . 号所在的 “那个位置” 所要放的就是一个你需要 “传” 给 Docker Server 的一个文件夹。. 表示就是把当前文件夹传给 Docker Server 用于镜像的构建。

# 2. 指令说明

# 2.1 基础指令

基础指令是表述 Dockerfile 整体性质的指令,能够为我们选择基础镜像,也能提供镜像的基本信息。

# 2.2 控制指令

控制指令是 Dockerfile 的核心部分,我们通过控制指令来描述整个镜像的构建过程。

# 2.3 引入指令

在很多场合下,我们希望将文件加入到即将构建成的镜像中,引入指令就能够帮助我们实现这个目的。

# 2.4 执行指令

执行命令能够指定通过镜像创建的容器,在启动、运行时默认执行的命令。

简单来说就是, Docker 容器就是一个虚拟机,只不过这个虚拟机有且仅干一件事情,具体是什么事情,则由创建容器的镜像的 Dockerfile 中的 CMDENTRYPOINT 指定。

# 2.5 配置指令

# 3. Dockerfile 示例

Dockerfile 文件格式如下:

##Dockerfile 文件格式
# This dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] ..

# (1) 第⼀行必须指定基础镜像信息
FROM ubuntu

# (2) 维护者信息
MAINTAINER docker_user [email protected]

# (3) 镜像操作指令
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf

# (4) 容器启动执行指令
CMD /usr/sbin/nginx

Dockerfile 分为四部分:基础镜像信息维护者信息镜像操作指令容器启动执行指令

  • ⼀开始必须要指明所基于的镜像名称,

  • 接下来⼀般会说明维护者信息;

  • 后面则是镜像操作指令,如 RUN 指令。每执行⼀条 RUN 指令,镜像添加新的⼀层,并提交;

  • 最后是 CMD 指令,来指明运行容器时的操作命令。