2018-03-19 11:34

Docker:Dockerfile常用指令

Brief

:创建镜像时,Dockerfile中常用指令

CMD

CMD指令用于指定一个容器启动时要运行的命令.类似于RUN指令,RUN指令是指定镜像被构建时要运行的命令,而CMD是指定容器被启动时要运行的命令。

CMD ls -a 也可以写作 cmd ["ls", "-a"] 数组才参数是推荐使用的方式

CMD ["ls", "-a"] 会被解析成 /bin/bash -c ls -a shell 解析器根据实际情况变化

CMD指令会被docker run指定的命令覆盖,Dockerfile中只有最后一个CMD命令会生

ENTRYPOINT

ENTRYPOINT指令与CMD指令非常类似,但ENTRYPOINT指令提供的命令不容易在启动容器时被覆盖。实际上,docker run命令行中指定的任何参数都会被当做参数再次传递给ENTRYPOINT指令中指定的命令。

ENTRYPOINT同CMD推荐使用数组参数 ENTRYPOINT ["/usr/sbin/nginx"]

...
ENTRYPOINT ["/usr/sbin/nginx"]

运行容器命令

docker run -d -p 80 xxx -g "daemon off;"

等效于Dockerfile没有加ENTRYPOINT ["/usr/sbin/nginx"]

docker run -d -p 80 xxx /usr/sbin/nginx -g "daemon off;"

docker run -d -p 80 xxx -g "daemon off;"  -g "daemon off;" 传递给 ENTRYPOINT 命令形成 /usr/sbin/nginx -g "daemon off;"

ENTRYPOINT可以与CMD结合使用

Dockerfile

...
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]

如果docker run启动时不指定参数,则默认容器会执行 /usr/sbin/nginx -h显示nginx帮助命令,同时也可以通过指定参数来覆盖-h默认命令 docker run -d -p xxx -g "daemon off;"则会执行/usr/sbin/nginx -g "daemon off;"

docker run可以通过--entrypoint强行指定覆盖ENTRYPOINT指令

WORKDIR

WORKDIR指令用来在从镜像创建一个新容器时,在容器内部设置一个工作目录,ENTRYPOINT或CMD等指令时会在这个目录下执行。

Dockerfile

...
WORKDIR /opt/
RUN ls -a
WORKDIR /var/
RUN ls -a

docker run可以通过-w在运行时覆盖Dockerfile指定的工作目录

[root@tvl-cnss-uat-3127 pro]# docker run -it -w /var/ ubuntu
root@f5e43c5a13a3:/var# pwd
/var

ENV

ENV指令用来在镜像构建过程中设置环境变量,环境变量可以在后续的任何RUN指令中使用,类似在命令前使用环境变量前缀。

Dockerfile

...

ENV JAVA_HOME /opt/java/jdk_1.8
RUN apt-get nginx

等效于

Dockerfile

...
JAVA_HOME=/opt/java/jdk_1.8 apt-get nginx

ENV可同时制定多个环境变量 Dockerfile

...

ENV JAVA_HOME=/opt/java/jdk_1.8 JVM_HOME=/opt/java

DEV 定义的环境变量可以被其他Docker指令继续使用

Dockerfile

...

ENV JAVA_HOME=/opt/java/jdk_1.8 JVM_HOME=/opt/java
WORKDIR $JAVA_HOME

* ENV 设置的环境变量会被持久保存到以该镜像创建的任何容器中

docker run可以通过-e来设置环境变量,仅运行时有效

[root@tvl-cnss-uat-3127 pro]# docker run -it -e "JAVA_HOME=/opt/java" -e "VERSION=1.0.0" ubuntu env 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=bcca083725ba
TERM=xterm
JAVA_HOME=/opt/java
VERSION=1.0.0
HOME=/root

USER

USER指令用来指定该镜像会以什么样的用户去运行。

Dockerfile

# 指定用户USER root 

# 指定用户&用户组USER user:group

VOLUME

向基于镜像创建的容器添加卷。一个卷是可以存在于一个或者多个容器内的特定的目录,这个目录可以绕过联合文件系统 ,并提供共享数据或者对数据进行持久化的功能,具有以下特性:

  • 卷可以在容器间共享和重用

  • 一个容器不是必须和其他容器共享卷

  • 对卷的修改是立时生效的

  • 对卷的修改不会对更新镜像产生影响

  • 卷会一直存在直到没有任何容器再使用它

Dockerfile

...
# 指令将会为基于此镜像创建的任何容器创建一个名为/opt/java-sources的挂载点
VOLUME ["/opt/java-sources"]

ADD

ADD指令用来将构建环境下的文件和目录复制到镜像中,不能对构建目录或者上下文之外的文件进行ADD操作。如果将一个归档文件(合法的归档文件包括gzip、bzip2、xz)指定为源文件,Docker会自动将归档文件解开。如果目的地址以/结尾,那么Docker就认为源位置指向的是目录。如果目的地址不以/结尾,那么Docker就认为源位置指向的是文件。* 文件源也可以使用URL的格式

Dockerfile

...
ADD application.yml /opt/application.yml
# 指定URL源文件
# ADD http://xxxxx/application.yml /opt/application.yml

ADD指令会使得构建缓存变得无效,这一点也非常重要。如果通过ADD指令向镜像添加一个文件或者目录,那么这将使Dockerfile中的后续指令都不能继续使用之前的构建缓存。

COPY

COPY指令类似于ADD,COPY只关心在构建上下文中复制本地文件,不会做文件提取extraction)和解压(decompression)。 文件源路径必须与当前构建环境相对的文件或者目录,本地文件都放到和Dockerfile同一个目录下,不能复制该目录之外的任何文件,COPY指令的目的位置必须是容器内部的一个绝对路径。

LABEL

为Docker镜像添加元数据,元数据以键值对的形式展现。推荐将所有的元数据都放到一条LABEL指令中,以防止不同的元数据指令创建过多镜像层。

Dockerfile

...

LABEL location="China" type="BigData" role="Web Server"

STOPSIGNAL

STOPSIGNAL指令用来设置停止容器时发送什么系统调用信号给容器,这个信号必须是内核系统调用表中合法的数,如:9,或者SIGNAME格式中的信号名称,如:SIGKILL。

ARG

ARG指令用来定义可以在docker build命令运行时传递给构建运行时的变量,通过docker build --build-arg进行对ARG指定都参数赋值。

Dockerfile

...
# 设置一个需要传入都参数user
ARG user
# 设置一个需要传入都参数group 默认值为root
ARG group=root

docker build --build-arg user=root xxx 将root赋值给user,group由于没有指定则使用默认值root

多个参数需要重复使用--build-arg参数进行指定 docker build --build-arg user=root --build-arg group=root xx

Docker预定义了一组ARG变量,这些变量无需在Dockerfile指定直接可以使用
HTTP_PROXY http_proxy HTTPS_PROXY https_proxy FTP_PROXY ftp_proxy NO_PROXY no_proxy

ONBUILD

ONBUILD指令能为镜像添加触发器(trigger)。当一个镜像被用做其他镜像的基础镜像时(比如用户的镜像需要从某未准备好的位置添加源代码,或者用户需要执行特定于构建镜像的环境的构建脚本),该镜像中的触发器将会被执行,触发器可以指定所有都构建指令。

Dockerfile

# 指定基础镜像
FROM ubuntu

# 指定作者和联系邮箱
MAINTAINER Acexy "acexy@acexy.cn"

# 安装nginx
RUN apt-get update && apt-get install -y nginx

# 修改nginx默认index页面内容
RUN echo 'This page comes from docker ubuntu nginx.' > /var/www/html/index.nginx-debian.html

ONBUILD COPY . /var/source/

# 向宿主机暴露容器80端口使其可以访问
EXPOSE 80

以ubuntu为基础镜像,创建一个带有nginx都新镜像,其中指定了ONBUILD 指令 COPY . /var/source/ 将当前构建目录都所有内容复制到指定的目录中

构建完毕后得到新镜像

REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
onbuild              0.0.1     4b4ecde8f445   24 seconds ago   159MB

创建一个新都工作空间,以onbuild:0.0.1作为基础镜像来创建一个新的镜像,测试onbuild:0.0.1中都ONBUILD指令

[root@tvl-cnss-uat-3127 images]# ll
total 0drwxr-xr-x. 2 root root 24 Feb 17 22:00 my_ubuntu_images
drwxr-xr-x. 2 root root 24 Feb 19 10:34 onbuild
drwxr-xr-x. 2 root root 24 Feb 17 22:02 volume

[root@tvl-cnss-uat-3127 images]# mkdir test-onbuild

[root@tvl-cnss-uat-3127 images]# cd test-onbuild/

[root@tvl-cnss-uat-3127 test-onbuild]# touch Dockerfile

# 在工作空间创建一个空的名字为file的文件[root@tvl-cnss-uat-3127 test-onbuild]# touch file

修改Dockerfile

Dockerfile

FROM onbuild:0.0.1
MAINTAINER Acexy "acexy@acexy.cn"
RUN apt-get install lrzsz

执行docker build -t="onbuild:0.0.2" .

[root@tvl-cnss-uat-3127 test-onbuild]# docker build -t="onbuild:0.0.2" .
Sending build context to Docker daemon   2.56kB
Step 1/3 : FROM onbuild:0.0.1# Executing 1 build trigger
 ---> 3903099e4f9e
Step 2/3 : MAINTAINER Acexy "acexy@acexy.cn"...

启动这个镜像查看/var/source/下是否有触发器添加都工作目录都文件

[root@tvl-cnss-uat-3127 test-onbuild]# docker run -it onbuild:0.0.2 /bin/bash
root@93c809962054:/# cd /var/source/
root@93c809962054:/var/source# ll
total 4
drwxr-xr-x. 2 root root 36 Feb 19 02:50 ./
drwxr-xr-x. 1 root root 41 Feb 19 02:50 ../
-rw-r--r--. 1 root root 80 Feb 19 02:46 Dockerfile
-rw-r--r--. 1 root root  0 Feb 19 02:42 file

在构建onbuild:0.0.2时,由于指定的基础镜像为onbuild:0.0.1,且0.0.1中ONBUILD指定在构建时复制当前工作空间的文件到/var/source,所以构建完毕之后0.0.2自动执行了这些步骤。