文章目录
[隐藏]

1 概述

Dockerfile基于DSL(Domain  Specific Language)语法的指令来构建镜像,利用Dockerfile构建镜像具备可重复性和幂等性,比利用docker commit的方式更具优势。

2 指令介绍

每个Dockerfile指令必须大写

(1)FROM:指定基础镜像,FROM是必备的指令,并且必须是第一条指令。

(2)RUN:用来执行命令,有shell格式和exec格式两种方式来执行命令。

每执行一个命令就会构建一层镜像,为避免不必要的commit,建议使用&&将命令连接起来。为了增加可读性,利用#进行注释,利用\进行换行,并增加相应缩进。

注意这里的清理操作,执行rm清理不必要的临时文件,–auto-remove清理临时变量,避免镜像臃肿。

(3)COPY:文件的复制,可用于将一些本地文件复制进镜像。

格式:

COPY <源路径>… <目标路径>
COPY [“<源路径1>”,… “<目标路径>”]

<目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。

注意:COPY 指令会保留源文件的rwx等权限、变更时间等信息。

(4)ADD:同COPY,但源文件路径可以是URL,Docker 引擎会先下载,然后再拷贝到目标路径中。通常情况下如果需要对文件进行解压并变更权限,建议直接使用docker run命令,再拷贝进去,实际中推荐COPY指令,仅在需要自动解压缩的场合使用 ADD。

(5)CMD:用于指定默认的容器主进程的启动命令。

格式同RUN相似:

shell 格式:CMD <命令>
exec 格式:CMD [“可执行文件”, “参数1”, “参数2″…]
参数列表格式:CMD [“参数1”, “参数2″…]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。

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

以下方式是错误的,

正确做法是直接执行可执行文件来启动服务。

(6)ENTRYPOINT:同CMD一样,可以指定容器启动程序及参数,使用ENTRYPOINT 替代,可以直接在docker  run  镜像名称后跟参数

使用 docker build -t myip . 来构建镜像后,为了查询公网IP,可以执行:

Dockerfile中使用ENTRYPOINT 还可以直接在后面跟curl的参数

(7)ENV:设置环境变量

格式:ENV <key1>=<value1> <key2>=<value2>..

利用ENV设置环境变量后,其他指令可以利用“$变量”的方式进行调用,这一点同shell。

(8)ARG:构建参数

ARG同ENV一样也是设置环境变量,但ARG是在Bulid的时候,通过–build-arg传入参数的,例如:

构建时动态传入参数:

格式:

  • ${variable:-word} :如果variable动态传值,则以variable设定的文字为主,如未设定,则变量为word字符串。
  • ${variable:+word} 代表,如果variable动态传值,则以variable设定的文字为主,如未设定,则变量为空(好BT的约定)。

(9)VOLUME:定义匿名卷

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中,VOLUME会定义某些目录为匿名卷,如果用户在运行时未指定挂载,镜像中应用想该目录写入的数据也不会向存储层写入大量数据。从而保证了容器存储层的无状态化。

当然也可以在运行时可以覆盖这个挂载设置,如:

在示例中,使用了 mydata 这个命名卷挂载到了 /var/lib/mysql/这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。

(10)EXPOSE:声明端口

EXPOSE声明运行时容器提供服务端口,仅仅是帮助镜像使用者查看该镜像守护服务所使用的端口。

区分:不同运行时使用 -p <宿主端口>:<容器端口>,EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射

(11)WORKDIR:指定工作目录

WORKDIR指定工作目录,以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

(12)USER:指定当前用户

同WORKDIR,执行RUN、CMD等命令的指定用户。

注意:对于需要Root权限,建议采用gosu替代执行su或sudo,例如:

(13)HEALTHCHECK:健康检查

HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常,格式如下:

  • HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
  • HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

详细请参考:https://yeasy.gitbooks.io/docker_practice/content/image/dockerfile/healthcheck.html

(14)ONBUILD:为其他镜像引用做准备

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

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

其他项目构建引用上个镜像:

(15)构建镜像

在 Dockerfile 文件所在目录执行:

3 构建示例

neutron镜像构建的Dockerfile为例:

下载源码:

Dockerfile内容如下:

第1行:FROM ubuntu:vivid,基于ubuntu:vivid镜像构建

第2行:MAINTAINER Angus Lees <gus@inodes.org>,维护者标签信息

第4~9行:ENV设置环境变量,可供后续操作使用

第13~18行:RUN,创建user&install用户,执行更新,并安装软件包

第28~35行:RUN,依赖包的安装,创建neutron相关目录并修改目录权限,创建软连接,并向文件中追加内容

第38行:COPY,拷贝脚本_wrap.sh到镜像的 /usr/local/bin/路径下

第39行:ENTRYPOINT,设置镜像入口点,运行时执行脚本/usr/local/bin/_wrap.sh

第40行:CMD,设置容器的启动时执行/bin/bash

第43行:USER,切换命令执行用户为install

第44~56行:RUN,下载neutron源码,利用pip执行安装,并测试neutron命令

第58行:COPY,复制neutron所需的配置文件到/etc/neutron/目录中

第60行:USER,切换用户为user

第61行:WORKDIR,指定工作目录为镜像根目录

第62行:EXPOSE,声明neutron所需的三个端口

构建镜像:

4 参考文档

《第一本Docker书》

http://dockone.io/article/131

https://yeasy.gitbooks.io/docker_practice/content/image/build.html

https://peihsinsu.gitbooks.io/docker-note-book/content/dockerfile-env-vs-arg.html