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自动执行了这些步骤。