Dockerfile 简述


Dockerfile 由指令(docker的DSL)组成 使得创建镜像 可复用 及 自动化


Dockerfile指令格式


INSTRUCTION arguments
指令 不区分大小写 约定为全部大写
Dockerfile 指令的书写顺序就是执行顺序


Dockerfile指令介绍

FROM指令


Dockerfile 必须以FROM指令开始 FROM 指定 基础镜像 就是基于哪个镜像来制作自己的镜像
FROM <image name>
image name 格式一般为 image:tag


MAINTAINER指令


指定镜像的作者信息
MAINTAINER <author name>


RUN指令


在shell 或 exec 环境下执行的命令 RUN 在新创建的镜像上添加新的层面 提交的结果用在 Dockerfile 下一条指令中
RUN <command>


ADD和COPY指令


ADD <source> <destination>
source可以是URL 或 启动配置上下文中的一个文件
将 文件 拷贝到 container的文件系统对应的路径
所有拷贝到container中的文件和文件夹权限为 0755 uid和gid为 0
如果文件是可识别的压缩格式 则docker会帮忙解压缩

如果要ADD本地文件 则本地文件必须在 docker build  指定的目录下
如果要ADD远程文件 则远程文件必须在 docker build  指定的目录下
比如
docker build github.com/creack/docker-firefox
docker-firefox目录下必须有Dockerfile和要ADD的文件

COPY指令
COPY不允许source是 URL 也不会进行解压


CMD 和 ENTRYPOINT 指令


提供了容器默认的执行命令  Dockerfile 只允许使用一次 CMD/ENTRYPOINT 指令 使用多个CMD/ENTRYPOINT会抵消之前所有的指令 只有最后一个指令生效
CMD有三种形式
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD command param1 param2 (shell form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)

区别
第二种方式 以 /bin/sh -c 形式调用
第三种方式 为 ENTRYPOINT 指定参数 也就是使用第三种形式时 要有一个 ENTRYPOINT 指令
如果在执行 docker run 时提供了 command 且 command 和 CMD 中相同(参数可以不同) 则会执行command 不执行CMD中的命令(实际含义就是把CMD中传递param覆盖了)

ENTRYPOINT(An ENTRYPOINT allows you to configure a container that will run as an executable)有两种格式
ENTRYPOINT ["executable", "param1","param2"] (exec form)
ENTRYPOINT command param1 param2 (shell form)
区别
第二种(shell form) 屏蔽掉 docker run 时后面加的命令 和 CMD里的参数
第一种 把docker run后面的参数 或 CMD里的参数 追加给 ENTRYPOINT docker run后面的参数会覆盖掉CMD里的参数

例如 ENTRYPOINT ["echo", "param1"]

执行docker run -it test param2 显示 param1 param2
如果是 shell form 形式 docker run 提供的参数就无效
 
两者区别
ENTRYPOINT和CMD的不同点 执行docker run 时参数传递方式
CMD 指定的命令可以被 docker run 传递的命令覆盖
例如 用CMD指定 CMD ["echo"]
然后运行 docker run CONTAINER_NAME echo foo
CMD 指定的 echo 会被新指定的echo 覆盖 最终相当于运行 echo foo   打印出的结果就是 foo

ENTRYPOINT 把容器名后面的所有内容都当成参数传递给其指定的命令 不会对命令覆盖
ENTRYPOINT ["echo"]
然后运行 docker run CONTAINER_NAME echo foo
则CONTAINER_NAME后面 echo foo 都作为参数传递给ENTRYPOING里指定的echo命令了 所以相当于执行了 echo "echo foo"
打印出的结果 echo foo
在 Dockerfile 中 ENTRYPOINT 指定的参数比运行 docker run 时指定的参数更靠前
ENTRYPOINT ["echo", "foo"]
执行 docker run CONTAINER_NAME bar
相当于执行了 echo foo bar
打印出的结果就是 foo bar


EXPOSE指令


指定容器在运行时监听的端口
EXPOSE <port> [<port>...]
该指令会将 容器中的端口 映射成 宿主机器中的某个端口
当需要访问容器的时候 可以不使用容器的IP地址 而是使用 宿主机器的 IP地址 和 映射后的端口

要完成整个操作需要两个步骤
首先在 Dockerfile 使用EXPOSE设置需要映射的容器端口
然后在 运行容器的时候指定-p选项加上EXPOSE设置的端口
这样 EXPOSE 设置的端口号会被 随机映射成宿主机器中的一个端口号 也可以指定需要映射到宿主机器的那个端口
这时要确保宿主机器上的端口号没有被使用
EXPOSE指令 可以一次设置多个端口号 相应的运行容器的时候 可以配套的多次使用-p选项


WORKDIR指令


切换目录 可以多次切换(相当于cd命令) 对RUN,CMD,ENTRYPOINT生效
WORKDIR /path/to/workdir


ENV指令


设置环境变量 ENV <key> <value>
如果不指定value 表示清除key环境变量

USER指令
使用哪个用户跑container
USER <uid>

VOLUME指令
授权访问从容器内到主机上的目录
VOLUME ["/data"]