Dockerfile基础指令

## 一、Dockerfile简介

Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令,Docker程序将这些Dockerfile指令翻译真正的Linux命令;Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile,Docker程序将读取Dockerfile,根据指令生成定制的image。

Dockerfile的指令是忽略大小写的,建议使用大写,使用#作为注释,每一行只支持一条指令,每条指令可以携带多个参数。

Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层, 因此每一条指令的内容,就是描述该层应当如何构建。

## 二、dockerfile指令详解

**1. FROM**

功能为指定基础镜像,并且必须是第一条指令。

除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为scratch。这个镜像 是虚拟的概念,并不实际存在,它表示一个空白的镜像。

如果你以scratch为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始构建。

不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,比如swarm、coreos/etcd 。对于Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 FROM scratch 会让镜像体积更加小 巧。使用Go语言开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go 是特别适合容器微服务架构的语言的原因之一。

**2. MAINTAINER**

格式为 MAINTAINER <name>,指定维护者信息。/<name>

**3. RUN**

用来执行命令行命令

- shell格式:RUN ,就像直接在命令行中输入的命令一样

- exec格式:RUN ["可执行文件", "参数1", "参数2"],这更像是函数调用中的格式

使用 && 符连接多个命令; \\ 符进行换行。

为防止镜像臃肿,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉(编译构建所需要的软件,所有下载、展开的文件,apt缓存文件等)。

**4. CMD**

- shell格式:CMD

- exec 格式:CMD ["可执行文件", "参数1", "参数2"...]

- 参数列表格式:CMD ["参数1", "参数2"...],提供给 ENTRYPOINT 的默认参数

指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。

如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。

Docker不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用upstart/systemd去启动后台服务,容器内没有后台服务的概念。

CMD service nginx start ,如果这样写会出现容器执行后立即退出了,这主要是因为没搞明白前台和后台的概念,没有区分容器和虚拟机的差异,对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,进而退出,其他辅助进程不是他关心的内容。 上述命令可以理解为 CMD[ "sh", "-c", "service nginx start"] ,因此主进程是sh ,sh结束,主进程退出,自然容器也会退出。正确的做法是 CMD [ "nginx", "-g", "daemon off;" ]

**5. ENTRYPOINT**

两种格式:

- ENTRYPOINT ["executable", "param1", "param2"]

- ENTRYPOINT command param1 param2(shell中执行)

配置容器启动后执行的命令,ENTRYPOINT 在运行时也可以替代,不过比CMD要略显繁琐,需要通过docker run的参数 -entrypoint来指定。

**当指定了ENTRYPOINT后,CMD的含义就发生了改变:**

如果CMD中不是完整的命令,则将CMD的内容作为参数传给ENTRYPOINT指令,换句话说实际执行时,将变为 ENTRYPOINT CMD。

如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效。

每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。

**6. EXPOSE**

- EXPOSE [...]

功能为暴漏容器运行时的监听端口给外部,但是EXPOSE并不会使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P参数。

-P:大写P为自动映射,会将EXPOSE暴露出来的端口随机映射到宿主机的端口上,如果没有暴露端口,就不会有映射。

-p:小写p为手动映射,需要自己指定宿主机的端口和容器的端口,形式为:

-p宿主机端口:容器端口

(1)无论有没有暴露端口、自动映射或者手动映射,宿主机都可以通过容器ip+port(port随容器内部服务监听端口改变而改变)端口访问服务;

(2)要通过宿主机ip+端口的方式访问服务,宿主机的端口必须与容器端口有映射关系;

(3)如果没有暴露端口,-P自动映射不会映射任何端口,-p可以指定宿主机端口和容器端口形成映射。

**7. ENV**

1. ENV

2. ENV = ...

两者的区别就是第一种是一次设置一个,第二种是一次设置多个

下列指令可以支持环境变量展开:

**ADD、COPY 、ENV、EXPOSE 、LABEL 、USER 、WORKDIR 、VOLUME 、STOPSIGNAL、ONBU ILD**

**使用环境变量方式: $环境变量**

**8. COPY**

将从构建上下文目录中的文件或者目录复制到新的一层的镜像内的位置。

可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用WORKDIR指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。

此外,还需要注意一点,使用COPY指令,源文件的各种元数据都会保留。比如读、写、执 行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关文件都在使用Git 进行管理的时候。

- COPY:...

- COPY: ["",... ""]

```sh

COPY src1 \\

src2 \\

WORKDIR/

```

执行上述操作会发现将src1 src2 下的文件全部复制到WORKDIR下,并没有复制目录src1 src2,官方对于COPY解释是:

>Note: The directory itself is not copied, just its contents.

即:COPY指令拷贝一个文件夹只会拷贝文件夹的内容。

上述指令可以这样写:

```sh

COPY src1 \\

src2 \\

WORKDIR/src

```

这样将COPY的文件,放在了新创建的src目录下。

**9. ADD**

ADD指令和COPY的格式和性质基本一致,不过可以是一个URL,同时如果源文件是一个压缩文件,ADD会自动执行解压缩。

因此在COPY 和ADD指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用COPY指令,仅在需要自动解压缩的场合使用ADD 。

**10. VOLUME**

- VOLUME ["", ""...]

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存 动态数据的应用,其数据库文件应该保存于卷(volume)中。

为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

**如何使用:**

在Dockerfile中定义匿名卷,运行容器时,使用参数 **-v 宿主机目录:匿名卷** 进行挂载,实现了数据持久化。

**11. WORKDIR**

- WORKDIR

使用WORKDIR指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。

```sh

WORKDIR /a

WORKDIR b

WORKDIR c

RUN pwd

则最终路径为 /a/b/c。

```

**12. USER**

- USER

USER是改变之后层的执行RUN ,CMD以及ENTRYPOINT这类命令的身份。USER只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

**13. ONBUILD**

- ONBUILD

ONBUILD是一个特殊的指令,它后面跟的是其它指令,比如RUN ,COPY等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。

Dockerfile中的其它指令都是为了定制当前镜像而准备的,唯有ONBUILD是为了帮助别人定制自己而准备的。


分享到:


相關文章: