Dockerfile指令解析

语言: CN / TW / HK

Dockerfile是由一系列命令和参数构成的脚本,以FROM命令为开始,然后是各种方法和参数的使用,最终生成一个新的镜像。在使用Docker构建镜像的时,每一个命令都会在前一个命令的基础上形成一个新层。

Dockerfile示例

这里以制作一个centos+jdk8的镜像为例:

FROM       centos
MAINTAINER MAINTAINER authors_name <xxxx@gmail.com>

ADD jdk-8u211-linux-x64.tar.gz /usr/local

ENV JAVA_VERSION 1.8.0

ENV JAVA_HOME /usr/local/jdk1.8.0_211
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin

Docker执行步骤分析

每条指令都会创建一个新的镜像层并对镜像进行提交,Docker执行Dockerfile大致流程:

  • Docker从基础镜像(如:centos)运行一个容器;

  • 执行一条指令(如:ADD),对容器做出修改;

  • 执行类似docker commit的操作,提交一个新镜像层;

  • Docker再基于刚提交的镜像运行一个新容器;

  • 执行Dockerfile中的下一条指令,直到所有指令都执行完毕;

示例解析

  • FROM:Dockerfile的第一条命令,指定一个已经存在的镜像,后续的指令都是基于该镜像(centos)进行操作。
  • MAINTAINER:该指令告诉Docker,作者和邮箱地址。
  • ADD:复制宿主机下的jdk8安装文件到容器的目录下,并解压。
  • ENV:设置jdk8的环境变量。

Dockerfile指令解析

FROM

DockerFile的首个命令,指定使用的基础镜像,如果没有发行该镜像,则试图从Docker image index来查找该镜像。

FROM       centos

这里查询centos最新镜像作为基础镜像。

MAINTAINER

声明作者和邮箱,一般放置于FROM命令之后。

MAINTAINER MAINTAINER authors_name <xxxx@gmail.com>

COPY

COPY用于将构建上下文中的<源路径>的文件/目录复制到镜像内的<目标路径>,源路径可以有多个,<目标路径>可以是容器内的绝对路径,也可以是相对于工作目录(用WORKDIR指令指定的)的相对路径。目标路径无需事先创建,如果目标路径不存在会自动创建。

需要注意的是,使用COPY指令复制文件,源文件的各种属性如读写执行权限、文件创建时间等都会保留,等于是原封不动地将文件复制过去。

COPY jdk-8u211-linux-x64.tar.gz /usr/local

此处仅执行复制操作,并没有进行解压。

ADD

ADD命令会将宿主机上的文件复制到容器中的目标目录。如果源是一个URL,URL的内容将被下载并复制到容器中。如果源文件是一个压缩文件时,复制到镜像后会自动解压。

ADD jdk-8u211-linux-x64.tar.gz /usr/local

这里将Dockerfile文件当前目录下的jdk安装文件复制到容器内的/usr/local目录下。

RUN

RUN命令是Dockerfile执行命令的核心部分,执行后面的命令并创建镜像。

# Install jdk
RUN yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel && \
 yum clean all

这里通过yum命令安装jdk。

CMD

CMD指令用于指定默认的容器主进程的启动命令。这些命令是在用镜像构建容器后被调用,可以使用三种格式。

CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/bash 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;

ENTRYPOINT

ENTRYPOINT帮助你配置一个容器使之可执行化,如果你结合CMD命令和ENTRYPOINT命令,你可以从CMD命令中移除“application”而仅仅保留参数,参数将传递给ENTRYPOINT命令。

# Usage: ENTRYPOINT application "argument", "argument", ..
# Remember: arguments are optional. They can be provided by CMD
# or during the creation of a container.
ENTRYPOINT echo

# Usage example with CMD:
# Arguments set with CMD can be overridden during *run*
CMD "Hello docker!"
ENTRYPOINT echo

ENV

ENV命令用于设置环境变量,以”key=value”的形式存在,可以在容器内被脚本或者程序调用。

# ENV key value

ENV SERVER_WORKS 4

USER

USER指定运行容器时的用户名或UID,可以改变以后的层执行命令时使用的用户,当然这个用户必须是事先建立好的,否则无法进行用户指定。

# USER [UID]

USER 751

VOLUME

要保持容器的无状态,因此不应该向容器的存储层写入任何需要持久化的数据。为此可以事先指定某些目录挂载为匿名卷,然后再启动容器时通过-v参数将宿主机的命名卷挂载到容器的匿名卷上。之后容器将数据写入这个匿名卷实际就是将数据写入宿主机的这个命名卷上。

# VOLUME ["/dir_1", "/dir_2" ..]

VOLUME ["/my_files"]

WORKDIR

WORKDIR命令用于设置CMD指明的命令的运行目录。

# WORKDIR /path

WORKDIR ~/

EXPOSE

EXPOSE指令用来告诉Docker容器在运行时监听的端口,Docker在连接不同的容器(使用–link参数)时使用这些信息。在 Dockerfile中可以映射私有和公有端口,但如果通过Dockerfile映射公有端口,则该端口便不可被其他应用程序使用。

# EXPOSE [port]

# private and public mapping
EXPOSE 80:8080

# private only
EXPOSE 80

构建镜像

使用以下命令构建镜像:

# docker build -t centos/jdk8 .

注意最后面有一个“.”。

分享到: