Zacard's Notes

Docker学习系列二:Dockerfile

前言

构建或者修改Docker image建议都使用Dockerfile。因为通过Dockerfile构建image或者修改image是透明的、可记录的,且无需重复的镜像和容器的创建过程。甚至可以使用版本控制(如:git)来保存Dockerfile的修改记录,以保留docker image完整的生命周期。

参考:官方Dockerfile说明

Dockerfile基本语法

Dockerfile支持的语法命令如下:

INSTRUCTION argument

指令不区分大小写。但是,命名约定全部为大写。

所有Dockerfile都必须以FROM命令开始。FROM命令会指定基于哪个基础镜像创建,接下来的命令也会基于这个基础镜像。FROM命令可以多次使用,表示会创建多个镜像。集体突发如下:

FROM <IMAGE NAME>

例如:

FROM ubuntu

上面的指定告诉我们,新的镜像将基于Ubuntu的镜像来构建。

FROM命令,Dockerfile还提供了一些其他的命令以实现自动化。这些命令的顺序就是他们的执行顺序。

MAINTAINER

MAINTAINER命令用来设置改镜像的作者。语法如下:

MAINTAINER <author name>

例如:

MAINTAINER zacard

RUN

RUN有2种形式,shell和exec。shell形式的语法如下:

RUN <command>

exec形式的语法如下:

RUN ["executable","param1","param2"]

ADD

ADD复制文件的命令。它有2个参数。source可以是url或者是启动配置上下文中的一个文件。destination是容器内的路径。语法如下:

ADD <source> <destination>

CMD

CMD提供了容器默认的执行命令。Dockerfile只允许使用一次CMD命令。使用多个CMD会抵消之前所有的命令,只有最后一个命令生效。CMD命令有3种形式:

// exec形式,推荐的使用形式
CMD ["executable","param1","param2"]

// 默认ENTRYPOINT的param形式
CMD ["param1","param2"]

// shell形式
CMD command param1 param2

ENTRYPOINT

ENTRYPOINT命令配置给容器一个可执行的命令,使镜像创建容器时默认运行一个可执行文件。且和CMD类似,Dockerfile也只允许一个ENTRYPOINT命令,多个ENTRYPOINT只会执行最后一个命令。语法如下:

// exec形式,推荐的使用形式
ENTRYPOINT ["executable","param1","param2"]

// shell形式
ENTRYPOINT command param1 param2

CMD和ENTRYPOINT如何相互影响

2个命令相互间的影响如下表格所示:

No ENTRYPOINT ENTRYPOINT exec_entry p1_entry ENTRYPOINT [“exec_entry”,”p1_entry”]
No CMD error,not allowrd /bin/sh -c exec_entry p1_entry exec_entry p1_entry
CMD [“exec_cmd”,”p1_cmd”] exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_cmd p1_cmd exec_entry p1_entry exec_cmd p1_cmd
CMD [“p1_cmd”,”p2_cmd”] p1_cmd p2_cmd /bin/sh -c exec_entry p1_entry p1_cmd p2_cmd exec_entry p1_entry p1_cmd p2_cmd
CMD exec_cmd p1_cmd /bin/sh -c exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

另外,docker run命令中的参数会传递给ENTRYPOINT命令,而不用担心被覆盖(CMD与之相反)。所以ENTRYPOINTCMD结合使用效果会更好。

EXPOSE

EXPOSE命令指定容器在运行时监听的端口。语法如下:

EXPOSE <port> [<port>...]

例如:

// 映射容器私有端口80到共有端口8080    
EXPOSE 80:8080

// 开放私有端口80
EXPOSE 80

注意,永远不要使用Dockerfile映射公有端口。不然你将可能只能运行一个容器化应用程序的实例。

WORKDIR

WORKDIR命令指定了RUNCDMENTRYPOINT命令的工作目录。语法如下:

WORKDIR /path/to/workdir

ENV

ENV命令设置环境变量。使用键值对的方式,增加了运行程序的灵活性。语法如下:

// 推荐
ENV <key>=<value>

ENV <key> <value>

USER

给镜像运行时设置一个UID。语法如下:

USER <uid>

VOLUME

授权访问从容器内到宿主主机上的目录。语法如下:

VOLUME ["/data"]

Dockerfile的一些建议

  • 不要开机初始化
  • 不要在构建中升级版本
  • 使用小型基础镜像,建议FROM alpine:3.3
  • 尽量使用格式一致的Dockerfile,这样能使用缓存
  • 不要在构建中升级版本,如在容器中apt-get upgrade
  • 使用特点的标签。如FROM debian:jeesie,而不是FROM debian
  • 常见的命令组合。如:apt-get updateatp-get install组合。此外使用\格式化成多行命令。这样能够最大程度的应该缓存。
  • 使用自己的基础镜像
坚持原创技术分享,您的支持将鼓励我继续创作!

热评文章