# Dockerfile命令详解

Dockerfile介绍

Dockerfile类似于shell的脚本,由一条条指令组成,Docker进程可以通过读取Dockerfile中的指令,依据指令内容自动构建生成镜像。

dockerfile 官方文档

Dockerfile常用指令

FROM
LABEL
RUN
EXPOSE
COPY
ADD
ENV
ARG
USER
CMD
ENTRYPOINT
VOLUME
WORKDIR

FROM: 指定基础镜像

FROM指令:指定dockerfile的底层镜像,后续都每条指令都可以看做是在这个底层镜像上的叠加,Dockerfile一般都是以FROM指令开头,其镜像文件,一般选用官方提供的镜像较为安全,当然也可以是已经制作好的镜像其他镜像。

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]

--platform 指定镜像的平台,比如: linux/amd64, linux/arm64, or windows/amd64 tag 和 digest是可选项,如果不指定,默认为latest

# 示例
FROM scratch  #所有镜像的起源镜像
FROM ubuntu
FROM ubuntu:bionic
FROM centos:7.9.2009

LABEL: 指定镜像元数据

LABEL指令:向镜像中添加元数据信息,例如 镜像的作者,镜像的信息,镜像的版本号,它是以键值对的方式来存储数据的,一个镜像可以有多个LABEL,可以写在一行中,也可以写在多行中,行尾使用 号分隔,推荐写在一行中,可以减少镜像的大小。

LABEL <key>=<value> <key>=<value> <key>=<value> ...

# 示例
#一行格式
LABEL label1="value1" label2="value2" label3="value3"

#多行格式
LABEL label1="value1" 	  label2="value2" 	  label3="value3"

RUN: 执行 shell 命令

RUN指令:在当前映像的顶部执行shell命令,并提交生成一层镜像,每一个RUN指令都会建立一个镜像层,所以尽可能将多个RUN合并成一条指令,以减少镜像层数,比如将多个shell命令通过 && 连接一起成为在一条指令。

# RUN指令后面直接跟shell命令,默认为sh -c
RUN <命令>

# exec格式
RUN ["executable", "param1", "param2"] (exec form)

# exec格式只支持双引号,不支持单引号,也无法使用环境变量,但它可以指定其它shell。例如:
RUN ["/bin/bash","-c","echo hello,world!"]

# 示例
RUN echo ‘Welcome to Nginx in Docker !‘ > /usr/share/nginx/html/index.html
RUN yum -y install epel-release     && yum -y install nginx     && rm -rf /usr/share/nginx/html/*
    && echo ‘Welcome to Nginx in Docker !‘ > /usr/share/nginx/html/index.html

注意事项:

  • 每条RUN命令的初始目录都是基于WOKRDIR目录,并不会因为上一条RUN命令进入了某个目录而影响后续的RUN命令的初始目录。

EXPOSE:暴露端口

EXPOSE指令:指定服务端容器打算监听的端口号,但实际上并不会主动发布端口,仅仅只是声明,只有在启动容器的时候通过-P或者-p参数,Docker才会真正将端口暴露出来使用。

EXPOSE <port> [<port>/<protocol>...]

# 示例
EXPOSE 80 443
EXPOSE 80/tcp
EXPOSE 80/udp

注意事项:

  • 默认情况下,EXPOSE使用TCP,当然也可以指定为UDP。
  • 即使Dockerfile文件中没有使用EXPOSE指令指定暴露端口,也可以在启动容器的时候通过-p参数来暴露指定的监听端口,所以,EXPOSE指令仅用于指定默认的暴露端口,通过-P参数才能进行真正的端口暴露。

COPY:复制文件

COPY指令:可以复制宿主机中的文件到容器中 ,并且连元数据等相关信息也一起复制,如读写执行权限,文件创建变更时间,但如果没有--chown指定属主,默认属主为容器root用户。

# COPY指令有两种使用方式,如果路径中包含空格,需要使用第二种格式
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

注意事项:

  • 可以指定多个,支持通配符,使用 Go’s filepath.Match rules。
  • 如果是目录,则将复制目录的整个内容,但目录本身不会被复制。
  • 基于当前Dockerfile的相对路径。
  • 是绝对路径或相对于WORKDIR的路径。
  • 如果不是以斜杠/结束,它将被认为是源文件拷贝后的重命名文件,如果以结尾斜杠/结束,它将被视为目录,即将源文件拷贝到目录下。
  • 当指定了多个,或者使用了通配符的情况下,必须以/结尾
  • --chown只支持linux系统。
  • 如果 < dest > 不存在,则递归创建所有不存在的目录。

ADD:复制和解压文件

ADD指令:该指令不仅支持复制文件,如果复制的文件是一个压缩文件,还支持自动解压缩。另外还支持URL下载,下载后的文件权限默认为600。

# 和COPY指令类似,有两种使用方式,如果路径中包含空格,需要使用第二种格式
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

注意事项:

  • 参考COPY指令的注意事项 ,ADD指令基本都适用。
  • 如果URL是一个tar.gz类的压缩文件,下载后并不会自动解压。

ENV: 设置环境变量

ENV指令:用来定义环境变量。可以被所有后续指令(如:ENV,ADD,COPY,RUN等)进行引用,
并在容器运行时保持此值。

# 只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成部分
ENV <key> <value>

# 支持多个key赋值,定义多个变量建议使用,减少镜像层
ENV <key1>=<value1> <key2>=<value2>  
    <key3>=<value3> ...

#如果<value>中包含空格,可以以反斜线进行转义,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行

# 如果只在构筑镜像的时候使用一次变量,可以考虑在RUN命令中直接设置
RUN <key>=<value> <command>

#引用变量
RUN $key .....

#变量支持高级赋值格式
${key:-word}
${kye:+word}

ARG: 构建参数

ARG指令:在镜像构建阶段指定变量,和ENV不同的是,容器运行后并不会保留变量。也可以在构建镜像时使用docker build命令的--build-arg = 将变量传递进Dockerfile覆盖原有的AGR变量值。

ARG <name>[=<default value>]

# 示例
FROM centos:7.9.2009   
RUN touch ${test:-aaa}.txt
ARG test=demo
RUN touch ${test:-bbb}.txt

# 上面示例最终会生成一个aaa.txt文件和demo.txt文件
[root@ubuntu2004:/docker/test]# docker run -it --name t4 fbf6635fb360 bash
[root@0c5878a01837 /]# ls
aaa.txt            bin       dev  home  lib64  mnt  proc  run   srv  tmp  var
anaconda-post.log  demo.txt  etc  lib   media  opt  root  sbin  sys  usr

注意事项:

  • 如果同时存在同名的ENV和ARG变量,ENV变量将覆盖ARG变量。
  • ARG变量定义从Dockerfile中定义的行往后才开始生效。
  • 不建议在构建镜像时使用-build-arg参数来传递如密钥,用户凭据等信息,因为使用docker history命令可以看得到。

USER:指定用户

USER指令:用于指定运行容器时的用户名或者UID。

USER <user>[:<group>]
USER <UID>[:<GID>]

# 示例
RUN groupadd -r test 	&& useradd -r -g test test
USER test

注意事项:

  • 用户必须提前创建好,否则会报错。
  • 如果没有指定用户,默认使用root身份运行容器。
  • Dockerfile后续的指令例如RUN,CMD,ENTRYPOINT也会使用该指定用户。

CMD:容器运行命令

CMD指令:用来指定在启动容器时默认执行的命令,该命令运行结束后,容器将停止运行,所以一般情况下CMD均为可持续运行的前台命令。使用docker run运行容器的时候可以后续指定具体命令来覆盖CMD中的命令。

# exec格式,不支持环境变量,第一个参数必须为绝对路径
CMD ["executable","param1","param2"]

# 用于给ENTRYPOINT传递参数
CMD ["param1","param2"]

# 之间跟shell命令和参数,支持环境变量,默认使用/bin/sh
CMD command param1 param2

# 示例
CMD ["nginx","-g","demon off;"]

注意事项:

  • Dockerfile中只能有一个CMD命令,如果有多个,只有最后一条会生效。
  • 当Dockerfile中同时还有ENTRYPOINT指令时,CMD只能当做其参数使用。

ENTRYPOINT:入口点

ENTRYPOINT指令:该指令功能类似于CMD指令,所不同的是ENTRYPOINT指令中的命令不能被docker run后续的命令所覆盖,而是将其追加作为参数使用。

如果想要覆盖Dockerfile中的ENTRYPOINT指令,可以在docker run后使用--entrypoint参数来指令新的命令作为入口点。

ENTRYPOINT指令可以结合exec命令,在启动容器的时候运行脚本。

# exec格式
ENTRYPOINT ["executable", "param1", "param2"]

# shell格式
ENTRYPOINT command param1 param2

VOLUME:匿名卷

VOLUME指令:用于为容器中的某个目录创建一个挂载点来存放需要保存的数据,即使容器被删除后,该目录对应的宿主机目录也会一直存在,宿主机目录的默认路径为 /var/lib/docker/volumes/<volume_id>/_data ,因为是匿名卷,不太好查找,可以使用docker inspect <image_id>l来查看具体的目录信息。

我们在使用docker run命令启动容器的时候可以使用 -v 参数来指定具体的目录挂载关系,因此该指令也不算太常用,当然,用户在使用docker run命令启动容器的时候可能会忘记使用 -v 参数指定挂载点,因此对于有重要数据的容器来说,VOLUME指令相当于多了一层保障。

VOLUME ["/data"]
VOLUME ["/data1","/data2"]

WORKDIR:工作目录

WORKDIR指令:该指令可以为后续的RUN,CMD,ENTRYPOINT,COPY和ADD指令配置默认的工作目录,当容器运行后,也会进入WORKDIR所指定的目录。

WORKDIR /path/to/workdir

使用docker build命令构建镜像

查看帮助:

[root@ubuntu2004:~]# docker build --help

Usage:	docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Options:
      --add-host list           Add a custom host-to-IP mapping (host:ip)
      --build-arg list          Set build-time variables
      --cache-from strings      Images to consider as cache sources
      --cgroup-parent string    Optional parent cgroup for the container
      --compress                Compress the build context using gzip
      --cpu-period int          Limit the CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int           Limit the CPU CFS (Completely Fair Scheduler) quota
  -c, --cpu-shares int          CPU shares (relative weight)
      --cpuset-cpus string      CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string      MEMs in which to allow execution (0-3, 0,1)
      --disable-content-trust   Skip image verification (default true)
  -f, --file string             Name of the Dockerfile (Default is ‘PATH/Dockerfile‘)
      --force-rm                Always remove intermediate containers
      --iidfile string          Write the image ID to the file
      --isolation string        Container isolation technology
      --label list              Set metadata for an image
  -m, --memory bytes            Memory limit
      --memory-swap bytes       Swap limit equal to memory plus swap: ‘-1‘ to
                                enable unlimited swap
      --network string          Set the networking mode for the RUN instructions
                                during build (default "default")
      --no-cache                Do not use cache when building the image
  -o, --output stringArray      Output destination (format: type=local,dest=path)
      --platform string         Set platform if server is multi-platform capable
      --progress string         Set type of progress output (auto, plain, tty).
                                Use plain to show container output (default "auto")
      --pull                    Always attempt to pull a newer version of the image
  -q, --quiet                   Suppress the build output and print image ID on success
      --rm                      Remove intermediate containers after a successful
                                build (default true)
      --secret stringArray      Secret file to expose to the build (only if
                                BuildKit enabled): id=mysecret,src=/local/secret
      --security-opt strings    Security options
      --shm-size bytes          Size of /dev/shm
      --squash                  Squash newly built layers into a single new layer
      --ssh stringArray         SSH agent socket or keys to expose to the build
                                (only if BuildKit enabled) (format:
                                default|<id>[=<socket>|<key>[,<key>]])
      --stream                  Stream attaches to server to negotiate build context
  -t, --tag list                Name and optionally a tag in the ‘name:tag‘ format
      --target string           Set the target build stage to build.
      --ulimit ulimit           Ulimit options (default [])

示例:

[root@ubuntu2004:~]# docker build -t cenos7.9:base-v1.0 .

范例:Tomcat业务镜像制作

1. 制作 CentOS 基础镜像

[root@ubuntu2004:/docker/centos]# ls
CentOS7.repo  Dockerfile


[root@ubuntu2004:/docker/centos]# cat CentOS7.repo
[Base-Package]
name=Base
baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos/7/os/x86_64/
        http://mirrors.aliyun.com/centos/7/os/x86_64/
        http://mirrors.huaweicloud.com/centos/7/os/x86_64/
gpgcheck=1
gpgkey=http://mirrors.tuna.tsinghua.edu.cn/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7

[Epel]
name=epel
baseurl=http://mirrors.tuna.tsinghua.edu.cn/epel/7/x86_64/
        http://mirrors.aliyun.com/epel/7/x86_64/
        http://mirrors.huaweicloud.com/epel/7/x86_64/
gpgcheck=1
gpgkey=http://mirrors.tuna.tsinghua.edu.cn/epel/RPM-GPG-KEY-EPEL-7

[Extras]
name=extras
baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos/7/extras/x86_64/
        http://mirrors.aliyun.com/centos/7/extras/x86_64/
        http://mirrors.huaweicloud.com/centos/7/extras/x86_64/
gpgcheck=1
gpgkey=http://mirrors.tuna.tsinghua.edu.cn/centos/RPM-GPG-KEY-CentOS-Official


[root@ubuntu2004:/docker/centos]# cat Dockerfile 
FROM centos:7.9.2009  
LABEL maintainer=wuvikr message=centos7.9_base_image
COPY CentOS7.repo /etc/yum.repos.d/
RUN find /etc/yum.repos.d ! -name CentOS7.repo -a -type f -exec rm -rf {} ;     && yum -y install vim curl wget telnet tree wget bash-completion net-tools iproute lrzsz lsof zip unzip nfs-utils gcc make glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel zlib-devel rsync tcpdump psmisc bzip2     && yum clean all     && rm -f /etc/localtime     && ln -s ../usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN groupadd www -g 2020 && useradd www -u 2020 -g www
    

[root@ubuntu2004:/docker/centos]# docker build -t centos7.9:base .

2. 制作构建 JDK 镜像

[root@ubuntu2004:/docker/jdk]# ls
Dockerfile  jdk-8u271-linux-x64.tar.gz  jdk.sh


[root@ubuntu2004:/docker/jdk]# cat jdk.sh 
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=$JAVA_HOME/lib/:$JRE_HOME/lib/


[root@ubuntu2004:/docker/jdk]# cat Dockerfile 
FROM centos7.9:base
LABEL maintainer=wuvikr message=JDK8u271-CentOS7.9
ADD jdk-8u271-linux-x64.tar.gz /usr/local/src/
RUN ln -s /usr/local/src/jdk1.8.0_271 /usr/local/jdk
COPY jdk.sh /etc/profile.d/
ENV JAVA_HOME="/usr/local/jdk" PATH="${JAVA_HOME}/bin:${PATH}"     JRE_HOME="${JAVA_HOME}/jre" CLASSPATH="${JAVA_HOME}/lib/:${JRE_HOME}/lib/"


[root@ubuntu2004:/docker/jdk]# docker build -t centos7.9-jdk:8u271 .

3. 制作Tomcat镜像

[root@ubuntu2004:/docker/tomcat]# ls
apache-tomcat-8.5.61.tar.gz  Dockerfile


[root@ubuntu2004:/docker/tomcat]# cat Dockerfile 
FROM centos7.9-jdk:8u271
LABEL maintainer=wuvikr message=Tomcat8.5.61-JDK8u271-Centos7.9
RUN mkdir /apps
ADD apache-tomcat-8.5.61.tar.gz /apps/
RUN ln -s /apps/apache-tomcat-8.5.61 /apps/tomcat
ENV TZ="Asia/Shanghai" LANG="en_US.UTF-8" TERM="xterm" TOMCAT_MAJOR_VERSION="8"     TOMCAT_MINOR_VERSION="8.5.61" CATALINA_HOME="/apps/tomcat"     APP_DIR="${CATALINA_HOME}/webapps" PATH="/apps/tomcat/bin:${PATH}"


[root@ubuntu2004:/docker/tomcat]# docker build -t centos7.9-tomcat:8.5.61 .

4. 制作web业务镜像

[root@ubuntu2004:/docker/web1]# ls
app.tar.gz  Dockerfile  run.sh  server.xml


[root@ubuntu2004:/docker/web1]# cat run.sh
#!/bin/bash
su - www -c "/apps/tomcat/bin/catalina.sh run"


[root@ubuntu2004:/docker/web1]# cat Dockerfile 
FROM centos7.9-tomcat:8.5.61
LABEL maintainer=wuvikr message=WEB1-Tomcat8.5.61-JDK8u271-Centos7.9
COPY server.xml /apps/tomcat/conf/server.xml
ADD app.tar.gz /data/tomcat/webapps/ROOT/
COPY run.sh /apps/tomcat/bin/
RUN echo "nameserver 114.114.114.114" >> /etc/resolv.conf     && chown -R www.www /apps/ /data/
EXPOSE 8080 8009
CMD ["/apps/tomcat/bin/run.sh"]


[root@ubuntu2004:/docker/web1]# docker build -t centos7.9-tomcat8.5.61-web1:app .

# Dockerfile命令详解

原文地址:https://www.cnblogs.com/wuvikr/p/14319215.html