Docker - Dockerfile之ENV、ENTRYPOINT、VOLUME、ONBUILD、STOPSIGNAL指令详解
ENV
ENV指令用以定义镜像的环境变量。
格式
-
。ENV <key>=<value> ...
-
。ENV <key> <value>
该ENV指令将环境变量
<key>
设置为值
<value>
。此值可以在构建阶段的所有后续指令中使用。
例如:
FROM ubuntu
ENV INDEX=index
RUN apt-get update && apt-get install -y curl && curl http://127.0.0.1:8080/$MODE && rm -rf /var/lib/apt/lists/*
如果你要设置多个环境变量,为了美观,你可以使用
\
来进行换行。多个环境变量也可以使用空格进行隔开,如果某个环境变量的值是由一组英文单词构成,那么你可以使用
""
将其圈起来。
例如:
ENV INDEX=index USER=root \
TITLE="this is kaven's blog"
ARG指令和ENV指令的作用很相似,但是每个指令存在就肯定有它的原因。这两个指令都是设置环境变量。与ENV指令不同的是,ARG指令设置的环境变量只是在镜像构建时使用,在将来容器运行时是不会存在这些环境变量的。由最终镜像创建并且运行容器时,使用ENV指令设置的环境变量将被保留,可以使用
docker inspect
命令查看它们的值,或者使用
docker run --env <key> = <value>
命令更改它们的值。
如果仅在镜像构建过程中需要使用该环境变量,而在最终镜像中或者说由该镜像(最终镜像)创建的容器中已经不再需要该环境变量,就可以使用ARG指令,否则使用ENV指令,这样可以使得最终镜像足够干净。
作用的时机
- ARG指令设置的环境变量是在构建镜像的时候使用(它不会保留在最终镜像中)。
- ENV指令设置的环境变量一般是容器运行的时候使用(它会保留在最终镜像中)。
ENTRYPOINT
格式
-
。ENTRYPOINT ["executable", "param1", "param2"]
-
。ENTRYPOINT command param1 param2
ENTRYPOINT指令与CMD指令非常类似,
Dockerfile
中也只允许有一个ENTRYPOINT指令,有多个ENTRYPOINT指令时,只会执行最后的ENTRYPOINT指令。在
docker run
命令中使用了
--entrypoint
选项时,会覆盖
Dockerfile
中的ENTRYPOINT指令设置的内容。
当使用了ENTRYPOINT指令时,CMD指令的性质将会发生改变:CMD指令中的内容将会以参数形式传递给ENTRYPOINT指令,如下:
FROM ubuntu
ENTRYPOINT ["rm", "docker"]
CMD ["-rf"]
其实,它真正执行的命令将会是:
rm docker -rf
VOLUME
VOLUME指令用于构建镜像时指定挂载点。
格式
-
。VOLUME ["/data"]
容器是基于镜像创建的,容器的文件系统包括镜像的只读层+镜像上面的可写层,容器中新产生的数据都是保存在镜像上面的可写层。一旦容器删除后,这些数据就没了,除非我们人工备份下来(或者基于当前容器创建新的镜像)。能否让容器新产生的数据保存在主机上呢?这样即使容器删除了,数据在主机上还有备份,这就需要在容器中指定挂载点了 :Docker - Docker数据持久化。
通过
Dockerfile
的VOLUME指令可以在镜像中定义挂载点,这样只要通过该镜像创建的容器都有了挂载点。
通过VOLUME指令定义的挂载点,无法指定主机上对应的目录,当有新容器基于该镜像被创建时,新容器中的挂载点对应的主机目录,其实就是由Docker自动生成的数据卷的
_data
目录,由Docker自动生成的数据卷的名称一般如下图红框中的数据卷名称类似。
定义一个挂载点:
FROM java:8
VOLUME /java
定义多个挂载点:
FROM java:8
VOLUME ["/java", "/classpath"]
这里的
/java
和
/classpath
目录在容器运行时会自动生成并且挂载到主机上的某个目录(Docker维护的数据卷)。给容器挂载数据卷可以在
docker run
命令中使用
-v
选项来实现。
[root@izoq008ryseuupz ~]# docker run -v /data --name java_8 java:8
[root@izoq008ryseuupz ~]# docker inspect java_8
"Mounts": [
{
"Type": "volume",
"Name": "cb954c7b65c7b249ef81154622bb7ebc41c07d508b139d0ab231be4500a4dcbb",
"Source": "/var/lib/docker/volumes/cb954c7b65c7b249ef81154622bb7ebc41c07d508b139d0ab231be4500a4dcbb/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
ONBUILD
格式
-
。ONBUILD <INSTRUCTION>
指定当该镜像作为其它新镜像的基础镜像时,所需要执行的命令。
例如,生成
image1
镜像的
Dockerfile
如下。
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
当基于
image1
镜像创建新镜像时(通过
FROM image1
指令指定基础镜像),新镜像的
Dockerfile
会自动执行
image1
镜像的
Dockerfile
中ONBUILD指令指定的内容,等价于在新镜像的
Dockerfile
后面添加了两条指令:
FROM image1
#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
在生成
java:8
镜像的
Dockerfile
中,ONBUILD指令可以用来指定设置Java环境变量的命令,之后以
java:8
镜像为基础镜像的新镜像,就会自动设置Java环境变量,这样在由新镜像创建的容器中就可以直接使用
java -jar
这种命令。
STOPSIGNAL
格式
-
。STOPSIGNAL signal
STOPSIGNAL指令用于设置停止信号,来指定容器的停止方式。容器默认的停止信号是SIGTERM,在容器停止的时候会给容器发送这个
signal
,通过
--stop-signal
选项可以设置自己需要的
signal
,停止信号主要的目的是为了让容器内的应用程序在接收到
signal
之后可以先做一些事情,实现容器的平滑退出,如果不做任何处理,容器将在一段时间之后强制退出,会造成业务的强制中断,这个时间默认是
10s
。