Docker Dockerfile详解使用

一、Dockerfile的基本知识

1、什么是 Dockerfile?

Dockerfile 是一个用来构建自定义镜像的文本文件,它的文本内容由一行行指令语句组成,并且支持已 # 开头的注释行。

当命令较长时可以使用 \(反斜杠)符号来换行,使用 &&符号连接命令。

2、指令语句

指令语句可以大致分为两种:配置指令和操作指令

指令不区分大小写。但是,使用中我们约定大写,以便更轻松地将它们与参数区分开。

这些指令基本上都可以在 docker run命令中使用用相关参数来覆盖掉 Dockerfile相关的值,docker run 的参数优先级高。

指令语句的基础知识:

  • 每条保留字指令都必须是大写字母并且后面要跟随至少一个参数
  • 指令按照从上到下,顺序执行
  • # 表示注释
  • 每条指令的执行都会创建一个新的镜像层,注意:过多无意义的层,会造成镜像膨胀过大。

 

3、什么是上下文路径?

上下文路径:指 docker 在构建镜像时,如果需要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将该路径下的所有内容打包。

解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

 

4、使用 Dockerfile 创建镜像的步骤

使用起来很简单,关键指令 + 参数。灵活使用就得熟悉各种指令的含义和多练理解。大致流程如下:

1. 新建一个空目录作为上下文目录,(如:/root/Dockerfiletest)。

2. 在上下文目录中,新建一个名为 Dockerfile文件,并编写指令内容,一般我们默认把 Dockerfile文件放到上下文目录中。

[root@centos7 ~]# mkdir /root/Dockerfiletest
[root@centos7 ~]# cd /root/Dockerfiletest
[root@centos7 Dockerfiletest]# vim Dockerfile
[root@centos7 Dockerfiletest]# cat Dockerfile 
# 基础镜像
FROM centos:7
# 创建数据卷
VOLUME ["vdata"]
# 镜像被docker run命令创建并启动容器后执行的命令

     使用默认的Dockerfile文件文件名为Dockerfile,以及会将其置于镜像构建上下文目录中。

3. 使用 docker build命令构建/创建新镜像放到本地镜像仓库

[root@centos7 Dockerfiletest]# docker build -t build_image:1.0 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM centos:7
 ---> 7e6257c9f8d8
Step 2/3 : VOLUME ["vdata"]
 ---> Running in a3e2e87151f9
Removing intermediate container a3e2e87151f9
 ---> abc8515e4b91
Step 3/3 : CMD ["/bin/bash"]
 ---> Running in b4a931b41f0b
Removing intermediate container b4a931b41f0b
 ---> 1f2cfb33aaed
Successfully built 1f2cfb33aaed
Successfully tagged build_image:1.0
[root@centos7 Dockerfiletest]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
build_image         1.0                 1f2cfb33aaed        About a minute ago   203MB

-t 选项:表示给最终生成的镜像起个名称,“ name:tag”格式的标签

后面那个 . 点儿,表示将当前目录的上下文路径中使用Dockerfile构建,也可使用 -f /root/Dockerfiletest/Dockerfile 来指定

4. 使用 Dockerfile文件新建的镜像来创建并启动容器,run正常ok。

[root@centos7 Dockerfiletest]# docker run -it build_image:1.0 
[root@962e7ea2ad26 /]# ls
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv  tmp  var
bin                etc  lib   media  opt  root  sbin  sys  usr  vdata

 

二、Dockerfile - 配置指令

具体指令查看官方文档:https://docs.docker.com/engine/reference/builder/#usage

1、FROM指令

FROM指令:指定所创建镜像的基础镜像。

基本语法:

FROM  <image> [AS <name>]

FROM  <image>[:<tag>] [AS <name>]

FROM  <image>[@<digest>] [AS <name>]

其中:

  • <tag>和<digest> 是可选项,如果没有选择,那么默认值为 latest。
  • AS <name> 可选的名称。该名称可以在多阶段构建FROM时,COPY --from=<name>说明中使用,以引用此阶段中构建的映像。

一般情况下,Dockerfile文件中的第一条指令就是FROM指令。同时意味着接下来所写的指令将作为镜像的第一层开始。

在 Docker Store 上有非常多的高质量的官方镜像,都可以直接拿来作为我们创建的镜像的基础镜像,服务镜像,如 nginx、redis、mongo、mysql、httpd、php、tomcat 等;方便开发、构建、运行各种编程语言的镜像,如 node、openjdk、python、ruby、golang 等。基础的操作系统镜像,如 ubuntu、debian、centos、fedora、alpine 等等。

 

Docker 还存在一个特殊的镜像,名为 scratch 空白的镜像。这个镜像是虚拟的概念,并不实际存在。

如果你以 scratch 为基础镜像的话,表示你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。不以任何系统为基础,直接将可执行文件(所需的一切库都已经在可执行文件里)复制进镜像的做法并不罕见,比如centos,ubuntu等等。可以让镜像体积更加小巧。

 

2、ARG指令

ARG指令:定义创建镜像过程中使用的环境变量。

基本语法:ARG <name> [=<default value>] 。

在执行docker build命令时, 可以通过 --build-arg <参数名>=<值>来覆盖Dockerfile中定义的变量值,Dockerfile 文件中 ${变量名}来取值。

ARG 设置的环境变量仅对 Dockerfile 内有效,docker build构建成功后,构建好的镜像内不存在此环境变量。

[root@centos7 Dockerfiletest]# cat Dockerfile
ARG version=7
# 基础镜像
FROM centos:${version}
# 创建数据卷
VOLUME ["vdata1","vdata2"]
# 镜像被docker run命令创建并启动容器后执行的命令
CMD ["/bin/bash"]
[root@centos7 Dockerfiletest]# docker build --build-arg version=6 -t build_arg:1.0 .
[root@877dc4bf58ae /]# docker run -it build_arg:1.0
[root@06dfd4359482 /]# cat /etc/issue
CentOS release 6.10 (Final)
Kernel \r on an \m

 

3、LABEL指令

LABEL指令:可以添加元数据标签信息到为生成的镜像。

基本语法:LABEL <key>=<value> <key>=<value> <key>=<value> ...

LABEL是键值对。如果LABEL值中包含空格,请使用引号或反斜杠包裹。

一个镜像可以有多个标签。可以指定多行标签,也可以在一行上指定多个标签。

示例:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \

注意:

  • 1、键值对中等号两边不能有空格
  • 2、每条指令的执行都会创建一个新的镜像层,所以,最好把多个标签合并成一个LABEL指令。

 

4、EXPOSE指令

EXPOSE指令:指定当前容器对外暴露出的端口。

通知 Docker容器在运行时监听指定的网络端口。可以指定端口是侦听TCP还是UDP,如果未指定协议,则默认值为TCP。例如:EXPOSE 80/tcp 8008/udp 8888

基本语法:EXPOSE <port> [<port>/<protocol>...]

注意:

  • EXPOSE指令仅仅只是声明端口,并不会自动完成端口映射。
  • 如果要映射端口出来,在启动容器时可以使用 -P或 -p参数来映射一个或多个端口。

查看 tomcat,redis等官方容器的Dockerfile文件:

5、ENV 指令

ENV 指令:用来在构建镜像过程中设置环境变量。在镜像生成过程中会被后续RUN指令使用,并且通过镜像启动的容器中也会存在。

基本语法:

ENV <key> <value>

ENV <key>=<value> ...

ENV指令有两种形式:

  1. ENV <key> <value>会将一个变量设置为一个值。第一个空格之后的整个字符串将被视为<value>,包括空格字符。该值将为其他环境变量解释,因此如果不对引号字符进行转义,则将其删除。
  2. ENV <key>=<value> ...允许一次设置多个变量。引号和反斜杠可用于在值中包含空格。

在执行docker run 命令时, 可以通过 --env <key>=<value> 来覆盖Dockerfile中定义的变量值。

例如:

ENV myName="John Doe" myDog=Rex\ The\ Dog \   myCat=fluffy

ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy

注意:当一条ENV指令中同时为多个环境变量赋值并且值也是从环境变量读取时,会为变量都赋值后再更新。

例如:下面的指令:

ENV key1=value2
ENV key1=value1  key2=${key1}
最终结果为key1=value1  key2=value2

实例;

[root@centos7 Dockerfiletest]# cat Dockerfile 
ARG version=7
# 基础镜像
FROM centos:${version}
# 添加多个标签信息
LABEL version="1.0" author="赵云"  date="2020-09-20" description="Message ..."
# 环境变量
ENV APP_VERSION=1.0.0 APP_HOME=/usr/local/app author="赵云"
# 创建数据卷
VOLUME ["vdata1","vdata2"]
# 镜像被docker run命令创建并启动容器后执行的命令
CMD ["/bin/bash"]

// 省略构建和启动
[root@2b4be9773226 /]# echo $APP_HOME
/usr/local/app

 

6、VOLUME指令

VOLUME指令:创建具有指定名称的匿名数据卷挂载点。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

基本语法:VOLUME ["<mountpoint>",...]

该值可以是JSON数组,也可以是VOLUME ["/var/log/"]具有多个参数的纯字符串,例如:VOLUME /var/log或VOLUME /var/log /var/db。

例如:

RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
# 创建数据卷
VOLUME ["vdata1","/myvol"]

该Dockerfile生成一个镜像,该镜像会在docker run启动时创建一个新的挂载点/myvol并将该greeting文件复制到新创建的卷中。

7、WORKDIR指令

WORKDIR指令:指定工作目录。指定在创建容器后,终端默认登陆进来的工作目录,一个落脚点。

基本语法:WORKDIR <工作目录路径>。

可以在 docker run命令中用 -w参数覆盖掉WORKDIR指令的设置。

作用:

  • 使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),后面的指令工作的当前目录就是这个指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。
  • 使用docker run 启动容器后,默认进入的目录,也会是这个指定的目录。

示例:

[root@centos7 Dockerfiletest]# cat Dockerfile 
ARG version=7
# 基础镜像
FROM centos:${version}
# 添加多个标签信息
LABEL version="1.0" author="赵云"  date="2020-09-20" description="Message ..."
# 环境变量
ENV APP_VERSION=1.0.0 APP_HOME=/usr/local/app author="赵云"

RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
# 创建数据卷
VOLUME ["vdata1","/myvol"]

WORKDIR /mydir
RUN echo "hello dsfajflll" > hello.txt
# 镜像被docker run命令创建并启动容器后执行的命令
CMD ["/bin/bash"]
[root@centos7 Dockerfiletest]# docker run -it build_iamge:1.0   
[root@437b38a71a47 mydir]# ls
hello.txt
[root@437b38a71a47 mydir]# cat hello.txt 
hello dsfajflll
[root@437b38a71a47 mydir]# ls /  
anaconda-post.log  dev  home  lib64  mnt    myvol  proc  run   srv  tmp  var
bin                etc  lib   media  mydir  opt    root  sbin  sys  usr  vdata1
[root@437b3

执行命令 "hello dsfajflll" > hello.txt 时的当前目录就是 /mydir。

8、USER指令

USER指令:用于指定执行后续命令的用户和用户组。

基本语法:

USER <user>[:<group>]

USER <UID>[:<GID>]

USER指令设置运行映像时以及用于任何映像时使用的用户名(或UID)以及可选的用户组(或GID)这类命令的身份。

USER指令只是切换到后续命令执行的用户而已,这个用户必须是事先建存在,否则无法切换。

示例:推荐使用第三方的 gosu命令(需要下载 gosu)来切换用户。官方Redis镜像。

 

9、ENTRYPOINT指令

ENTRYPOINT指令:指定一个容器启动时要运行的命令。与 CMD 指令类似,目的都是在指定容器启动程序及参数。

基本语法:ENTRYPOINT有两种形式:

exec形式,这是优选的形式:ENTRYPOINT ["executable", "param1", "param2"]

shell形式:ENTRYPOINT command param1 param2

如果运行 docker run 时使用了 --entrypoint 选项,会覆盖Dockerfile中有ENTRYPOINT。

一般情况下ENTRYPOINT和CMD是结合起来用使用。当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:和CMD一样,每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个起效。

例如:让镜像变成像命令一样使用

下面的Dockerfile可以写成这个命令:# docker run --entrypoint=/bin/ls centos:7 -l /tmp 

相当于在启动容器后执行了:/bin/ls -l /tmp

FROM  centos:7
ENTRYPOINT ["/bin/ls"]
CMD ["-l", "/tmp"]

例如:应用运行前的准备工作

启动容器就是启动主进程,但是,有时候启动主进程之前,需要做一些准备工作。

这些准备工作是和容器 CMD 无关的,无论 CMD 是什么,都需要事先进行预处理的工作。

这种情况下,可以写一个脚本,然后放入 ENTRYPOINT 中去执行,而这个脚本会将接到的参数(也就是 <CMD>)放在最后执行,CMD的参数是主进程。

查看 官方Reids镜像

可以看到其中为了 redis 服务创建了 redis 用户,并在最后指定了 ENTRYPOINT 为 docker-entrypoint.sh 脚本。

假设启动容器的命令是:自己可以分析下那些准备工作

docker run --name myredis -idt  -v /root/redis/:/usr/local/etc/redis/ redis:6 redis-server /usr/local/etc/redis/redis.conf

 

10、ONBUILD指令

ONBUILD指令:用于延迟构建命令的执行。

基本语法:ONBUILD <其它指令>

ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在本次构建镜像的过程中不会被执行。只有当使用本次构建的镜像作为基础镜像,去构建下一个新的镜像的时才会被执行。

简单来说,Dockerfile 文件中,所有指令都是为了定制当前镜像而准备的(除了ONBUILD指令),只有 ONBUILD指令是为了帮助别人定制镜像而准备的。

示例:

ONBUILD RUN mkdir /dir222

[root@centos7 Dockerfiletest]# docker build -t build_iamge:1.0 .
[root@centos7 Dockerfiletest]# docker run -it build_iamge:1.0  
[root@904eb0379bfa mydir]# ls /
anaconda-post.log  dev  home  lib64  mnt    myvol  proc  run   srv  tmp  var
bin                etc  lib   media  mydir  opt    root  sbin  sys  usr  vdata1

dir222 目录是没有被创建的,然后使用  build_iamge:1.0作为基础镜像在构建镜像,在FROM指令执行之后,就会执行ONBUILD指令指定的命令。

[root@centos7 Dockerfiletest]# cat Dockerfile 
FROM build_iamge:1.0  
[root@centos7 Dockerfiletest]# docker build -t build_iamge:2.0 . 
[root@centos7 Dockerfiletest]# docker run -it build_iamge:2.0   
[root@de18dd0f9073 mydir]# ls /
anaconda-post.log  dev     etc   lib    media  mydir  opt   root  sbin  sys  usr  vdata1
bin                dir222  home  lib64  mnt    myvol  proc  run   srv   tmp  var

11、STOPSIGNAL指令 - 不常用

STOPSIGNAL指令:设置将被发送到容器退出的系统调用信号(默认信号值是SIGTERM)。该信号可以是与内核syscall表中的位置匹配的有效无符号数字(例如9),也可以是格式为SIGNAME的信号名称(例如:STOPSIGNAL SIGKILL)。

基本语法:STOPSIGNAL 信号

这个指令和执行 docker stop命令有点类似,执行docker stop命令时,docker首先会向容器内的当前主程序发送一个SIGTERM信号,用于容器内程序的退出。容器在收到SIGTERM后不会马上退出, 而 stop命令会在等待一段时间(默认是10s)后,再向容器发送SIGKILL信号,将容器杀死,变为退出状态。

 

12、HEALTHCHECK指令

HEALTHCHECK指令:健康检查,用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

基本语法:有两种形式:

HEALTHCHECK  [OPTIONS]  CMD <命令>:设置检查容器健康状况的命令

HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以禁用从基本映像继承的任何运行状况检查

支持下列选项:

  • --interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
  • --timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
  • --retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。

HEALTHCHECK指令用于告诉Docker如何测试容器以检查其是否仍在正常工作。

这样可以检测到诸如Web服务器陷入无限循环并且无法处理新连接的情况,即使服务器进程仍在运行。

指定容器的运行状况检查后,除了其正常状态外,它还具有运行状况。此状态最初为starting。只要运行状况检查通过,它将变为healthy。如果在一定数量的连续失败之后,它变为unhealthy。

注意:

HEALTHCHECK指令只可以出现一次,如果写了多个,只有最后一个生效。

CMD后面的命令,格式分为两种: shell 格式 和 exec 格式。

命令退出的返回值(状态),决定了该次容器健康检查的状态。可能的值为:

  • 0:成功-容器健康且可以使用
  • 1:失败/不健康-容器无法正常工作
  • 2:保留-请勿使用此退出代码

示例:

[root@centos7 Dockerfiletest]# cat Dockerfile 
FROM nginx:1.19.0
RUN apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://localhost/ || exit 1
[root@centos7 Dockerfiletest]# docker build -t build_iamge:1.0 . 

设置每5秒检查一次,健康检查命令超过3秒没响应就视为失败,并使用 curl -fs http://localhost/ || exit 1 作为健康检查命令。

curl 命令的:-f参数将不输出错误信息。-s不输出内容。

&&:用来执行条件成立后执行的命令 

||:用来执行条件不成立后的执行命令

[root@centos7 Dockerfiletest]# docker run -d --name "nginxweb" -p 80:80 build_iamge:1.0   
2848e4bc93d57c3a8128ee9602f9bcfc3e36df27ba8748708f0eb6070f4f6d4e
[root@centos7 Dockerfiletest]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS                NAMES
2848e4bc93d5        build_iamge:1.0     "/docker-entrypoint.…"   4 seconds ago      Up 54 seconds (starting)   0.0.0.0:80->80/tcp   nginxweb
[root@centos7 Dockerfiletest]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS                NAMES
2848e4bc93d5        build_iamge:1.0     "/docker-entrypoint.…"   15 seconds ago      Up 54 seconds (healthy)   0.0.0.0:80->80/tcp   nginxweb

13、SHELL指令 - 不常用

SHELL指令:指定其他命令使用 shell形式时的默认 shell类型。

基本语法:SHELL ["executable", "parameters"]

注意:在Linux上,默认值是["/bin/sh", "-c"]。在Windows 上,默认值["cmd", "/S", "/C"]。

 

三、Dockerfile - 操作指令

1、RUN 运行指定命令。

RUN指令:容器构建时需要运行的命令,实际上运行命令并提交结果。

基本语法:有2种形式:

RUN <command>(shell形式,命令在shell中运行,默认情况,Linux在/bin/sh -c或Windows在cmd /S /C上运行)

RUN ["executable", "param1", "param2"]( exec 格式,必须使用双引号(“),不要使用单引号('))

指定使用其他shell终端类型时可以使用 shell形式实现。

每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像层。

当命令较长时可以使用 \(反斜杠)符号来换行,使用 &&符号连接命令

例如:RUN ["/bin/bash","-c","echo hello"] 

例如:

RUN  apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \
    && rm -rf /var/cache/apt \
    && rm -rf /var/lib/apt/lists/*

 

2、CMD 容器启动命令

CMD指令:用于指定默认的容器主进程的启动的命令。

简单来理解CMD 相当于启动docker时候后面添加的参数。如:docker run -it centos:7 /bin/bash

基本语法:有三种形式:

CMD ["可执行文件", "参数1", "参数2"...](exec形式,这是首选形式)

CMD ["param1","param2" ...](作为ENTRYPOINT的默认参数)

CMD <命令>(shell形式)

CMD指令只可以出现一次,如果写了多个,只有最后一个生效。

shell格式和Exec格式区别:

  • Exec格式使用exec执行,不会启动shell环境。Exec格式指令会被解析一个JSON数组,因此必须使用双引号(“)不能使用单引号(')。
  • shell格式,默认将在shell 终端中运行命令,实际的命令会被包装为 sh -c 的参数的形式进行执行。

比如:CMD echo $HOME    在实际执行中,会将其变更为:CMD [ "sh", "-c", "echo $HOME" ]

RUN实际上运行命令并提交结果;CMD在生成时不执行任何操作,但是指定映像的预期命令。

 

3、COPY 复制指令

COPY指令:从上下文目录中复制文件或者目录到容器里的指定路径中。

基本语法:

COPY [--chown=<user>:<group>] <src>... <dest>

COPY [--chown=<user>:<group>] ["<src1>",... "<dest>"]

 

  • [--chown=<user>:<group>]:可选参数,用户改变复制到容器内文件的拥有者和属组。
  • <src>:源文件或者源目录,可以指定多个资源,但是必须在构建上下文路径内。

可以包含通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

COPY hom* /mydir/

COPY hom?.txt /mydir/

  • <dest>:容器内的指定路径,必须以斜杠结尾/。

可以是容器中内的绝对路径(推荐),也可以是相对于工作目录的相对路径(工作目录是用 WORKDIR 指令来指定)。路径不存在时会自动创建。

注意:

  • 源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。
  • 目录本身不被复制,仅其内容被复制。
[root@centos7 Dockerfiletest]# tree
.
├── abc.txt
├── dir1
│   └── dd.txt
└── Dockerfile

实例:复制文件

[root@centos7 Dockerfiletest]# docker build -t copyimage:1 .
[root@centos7 Dockerfiletest]# docker run -it copyimage:1
[root@657c464192cd /]# ls
anaconda-post.log  dev  home  lib64  mnt    opt   root  sbin  sys  usr
bin                etc  lib   media  mydir  proc  run   srv   tmp  var
[root@657c464192cd /]# cat /mydir/abc.txt 
hello

实例:复制目录 

[root@centos7 Dockerfiletest]# cat Dockerfile 
FROM centos:7
RUN mkdir /mydir
COPY dir1 /mydir
CMD ["/bin/bash"]
[root@centos7 Dockerfiletest]# docker build -t copyimage:1 .
[root@centos7 Dockerfiletest]# docker run -it copyimage:1   
[root@20dab72ef433 /]# ls
anaconda-post.log  dev  home  lib64  mnt    opt   root  sbin  sys  usr
bin                etc  lib   media  mydir  proc  run   srv   tmp  var
[root@20dab72ef433 /]# cat /mydir/dd.txt 
adfaf

可以直接一次复制:

[root@centos7 Dockerfiletest]# cat Dockerfile 
FROM centos:7
RUN mkdir /mydir
COPY ["abc.txt","dir1","/mydir/"]
CMD ["/bin/bash"]

[root@fd3273cd7528 /]# cd /mydir/
[root@fd3273cd7528 mydir]# ll
total 8
-rw-r--r-- 1 root root 6 Sep 20 06:36 abc.txt
-rw-r--r-- 1 root root 6 Sep 20 06:36 dd.txt

4、ADD 更高级的复制文件

ADD指令:ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。

基本语法:有两种形式:

ADD [--chown=<user>:<group>] <src>... <dest>

ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

 

  • [--chown=<user>:<group>]:可选参数,用户改变复制到容器内文件的拥有者和属组。
  • <src>:源文件或者源目录,可以指定多个资源,但是必须在构建上下文路径内。

支持远程文件URL,Docker 引擎会试图去下载这个链接的文件放到 <dest> 中。

可以包含通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

COPY hom* /mydir/

COPY hom?.txt /mydir/

  • <dest>:容器内的指定路径,必须以斜杠结尾/。

可以是容器中内的绝对路径(推荐),也可以是相对于工作目录的相对路径(工作目录是用 WORKDIR 指令来指定)。路径不存在时会自动创建。

注意:

  • 源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。
  • 目录本身不被复制,仅其内容被复制。

如果 <src>为远程文件 URL时,

下载后的文件权限自动设置为 600,可以增加一层 RUN 指令进行权限调整。

ADD指令不支持身份验证。如果你的URL文件受身份验证保护,可以使用 RUN wget, RUN curl或从容器中使用其他工具。

如果下载的是个压缩包,需要解压缩时,同样需要添加一层 RUN 指令进行解压缩。我们还不如直接使用 RUN 指令方便,然后使用 wget 或者 curl 工具下载,处理权限、解压缩、然后清理无用文件更合理。

因此,这个功能其实并不实用,而且不推荐使用。其他复制文件的情况时,推荐使用 COPY指令,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。

 

如果 <源路径> 为一个宿主机上的 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。在某些情况下,这个自动解压缩的功能非常有用,比如官方镜像 ubuntu centos等:

  

 

四、docker  build 命令

具体查看官方文档:https://docs.docker.com/engine/reference/commandline/build/

docker build 命令用于使用 Dockerfile 文件来创建镜像。如果创建镜像成功,会返回最终镜像的ID。

基本语法:docker build [OPTIONS] PATH | URL | -

选项:

名称,简写默认描述
--add-host 添加自定义主机到IP的映射(host:ip)
--build-arg 设置构建时变量
--cache-from 视为缓存源的图像
--cgroup-parent 容器的可选父cgroup
--compress 使用gzip压缩构建上下文
--cpu-period 限制CPU CFS(完全公平的调度程序)期限
--cpu-quota 限制CPU CFS(完全公平的调度程序)配额
--cpu-shares , -c CPU份额(相对重量)
--cpuset-cpus 允许执行的CPU(0-3,0,1)
--cpuset-mems 允许执行的MEM(0-3,0,1)
--disable-content-trusttrue跳过图像验证
--file , -f Dockerfile的名称(默认为“ PATH / Dockerfile”)
--force-rm 始终取出中间容器
--iidfile 将图像ID写入文件
--isolation 集装箱隔离技术
--label 设置图像的元数据
--memory , -m 内存限制
--memory-swap 交换限制等于内存加交换:“-1”以启用无限交换
--network 在构建过程中为RUN指令设置网络模式
--no-cache 构建映像时不要使用缓存
--output , -o 输出目的地(格式:type = local,dest = path)
--platform 如果服务器支持多平台,则设置平台
--progressauto设置进度输出的类型(自动,普通,tty)。使用普通显示容器输出
--pull 始终尝试提取图像的较新版本
--quiet , -q 禁止生成输出并成功打印图像ID
--rmtrue成功构建后删除中间容器
--secret 公开给构建的秘密文件(仅在启用BuildKit的情况下):id = mysecret,src = / local / secret
--security-opt 安全选项
--shm-size / dev / shm的大小
--squash 将新构建的层压缩为一个新层
--ssh SSH代理套接字或要公开给构建的密钥(仅在启用BuildKit的情况下)(格式:default |[=|[,]])
--stream 流附加到服务器以协商构建上下文
--tag , -t 名称以及“ name:tag”格式的标签(可选)
--target 设置要构建的目标构建阶段。
--ulimit Ulimit选项

docker build命令从Dockerfile和“上下文”中构建Docker映像。

构建的上下文是位于指定PATH或 URL。

URL参数可以引用三种资源:Git存储库,预打包的tarball上下文和纯文本文件。

1、使用 PATH 构建镜像。

  • -tag , -t        名称以及“ name:tag”格式的标签(可选)
  • --file , -f        Dockerfile的名称(默认为“ PATH 为上下文路径”)

1. 使用 上下文路径 构建镜像。

默认情况下, Dockerfile放在上下文目录里。指定PATH为 . 符号代表上下文路径。上面示例使用过了。

2. 使用 非上下文路径下的Dockerfile 构建镜像(不推荐)

[root@centos7 Dockerfiletest]# cp ./Dockerfile /root/abc/
[root@centos7 Dockerfiletest]# docker build -t copyimage:1 -f /root/abc/Dockerfile .

2、支持从 URL 构建

比如:可以直接从 Git repo 中构建,注意这个需要依赖git工具,确保Linux安装好git工具。

[root@centos7 git-2.9.5]# docker build https://github.com/twang2218/gitlab-ce-zh.git#:11.0

这行命令指定了构建所需的 Git repo,#后面不写,默认指定的 master 分支,构建目录为 /11.0/,

然后 Docker 就会自己去 git clone 这个项目、切换到指定分支、并进入到指定目录后开始构建。
 

3、用给定的 tar 压缩包构建

如果所给出的 URL 不是一个 Git仓库,而是个 tar 压缩包归档文件,那么 Docker 引擎会下载这个包,并将其用作构建上下文,自动解压缩构建。

# docker build http://server/context.tar.gz

4、从标准输入中读取 Dockerfile 进行构建:

docker build - < Dockerfile
或
cat Dockerfile | docker build -

如果标准输入传入的是文本文件,则将其视为 Dockerfile,并开始构建。

这种形式由于直接从标准输入中读取 Dockerfile 的内容,任何-f,--file 选项被忽略。在这种情况下,没有上下文。

因此不可以像其他方法那样可以将本地文件 COPY 进镜像之类的事情。

如果标准输入是读取上下文压缩包进行构建:

$ docker build - < context.tar.gz

如果发现标准输入的文件格式是 gzip、bzip2 以及 xz 的话,将会使其为上下文压缩包,直接将其展开并视为上下文,然后开始构建。

重点在1和2 两种形式,后面几个构建方式了解即可。

 

5、使用 .dockerignore文件

.dockerignore文件:排除从上下文中不需要上传到容器的文件或者目录。

使用 Dockerfile 构建镜像时最好是将 Dockerfile 放置在一个新建的空目录(上下文路径)下,然后将构建镜像所需要的文件添加到该目录中。

在上下文路径下新建一个 .dockerignore 文件来排除与其中的模式匹配的文件和目录。为了匹配,上下文的根被认为是工作目录和根目录。

示例:

[root@centos7 Dockerfiletest]# tree
.
├── aa.file
├── abc.txt
├── dir1
│   ├── a.file
│   └── dd.txt
└── Dockerfile

1 directory, 5 files
[root@centos7 Dockerfiletest]# cat .dockerignore 
/dir1*
!*.txt
[root@centos7 Dockerfiletest]# cat Dockerfile 
FROM centos:7
COPY [".","/mydir/"]
CMD ["/bin/bash"]
[root@centos7 Dockerfiletest]# docker build -t bulidimage1:1 .
[root@centos7 Dockerfiletest]# docker run -it bulidimage1:1
[root@ef823e49026f /]# ls /mydir/
Dockerfile  aa.file  abc.txt

五、Docker多阶段构建入门(multi-stage builds)

具体查看官方文档:https://docs.docker.com/develop/develop-images/multistage-build/

从17.05版本以后,新增了Dockerfile多阶段构建。通过多阶段构建,可以在一个Dockerfile 中使用多个 FROM 指令。

每个FROM指令可以使用不同的基础镜像,并且每个指令都开始构建的新阶段,多条 FROM 指令就是多阶段构建。

多个 FROM 指令并不是为了生成多根的层关系,而最后生成的镜像,仍然是以最后一条 FROM 指令生成的镜像为准。

 

如果把全部构建指令放入在一个 Dockerfile 中,包括项目及其依赖库的编译、测试、打包等流程,可能会带来的一些问题:

  • Dockerfile 特别长,可维护性降低
  • 镜像层次多,镜像体积较大,部署时间变长
  • 源代码存在泄露的风险

多阶段构建可以很方便地将多个彼此依赖的项目通过一个Dockerfile就可轻松构建出期望的容器镜像,而不用担心镜像太大、源码泄露等风险。还可以的构建环境和运行环境进行分离,从而减少镜像层次多,镜像体积较大,部署时间变长,可维护性降低等问题。

示例:以安装nginx做演示

1、使用一个FROM,未优化

[root@centos7 Dockerfiletest]# mkdir /usr/local/nginx
[root@centos7 Dockerfiletest]# ls
Dockerfile  nginx-1.18.0.tar.gz
[root@centos7 Dockerfiletest]# cat Dockerfile 
FROM centos:7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
ADD nginx-1.18.0.tar.gz /mnt
RUN yum install -y gcc pcre-devel zlib-devel make
WORKDIR /mnt/nginx-1.18.0
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@centos7 Dockerfiletest]# docker build -t buildnginx:v1 .
[root@centos7 Dockerfiletest]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
buildnginx          v1                  4225534fe92d        7 seconds ago       365MB

2、优化:清理中间缓存并尽量减少镜像层数

[root@centos7 Dockerfiletest]# cat Dockerfile 
FROM centos:7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN yum install -y gcc pcre-devel zlib-devel make \ 
        && yum clean all \
        &&  ./configure --prefix=/usr/local/nginx \
        && make \
        && make install
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@centos7 Dockerfiletest]# docker build -t buildnginx:v2 .
[root@centos7 Dockerfiletest]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
buildnginx          v2                  486ef7b26ac2        7 seconds ago      297MB

2、多条 FROM 指令:多阶段构建

[root@centos7 Dockerfiletest]# cat Dockerfile 
# nginx安装编译
FROM centos:7 as build_nginx
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN yum install -y gcc pcre-devel zlib-devel make \ 
        && yum clean all \
        &&  ./configure --prefix=/usr/local/nginx \
        && make \
        && make install \
        && rm -rf /mnt/nginx-1.18.0

# 创建镜像,将编译好的文件直接拿过来用
FROM centos:7   
# 把上面阶段的安装文件复制到本阶段目录中
COPY --from=build_nginx  /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@centos7 Dockerfiletest]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
buildnginx          v3                  049fa454801c        6 seconds ago       207MB
<none>              <none>              8451d367293d        7 seconds ago       285MB

可以发现,文件大小有了变化。

 

—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。

  • 8
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Docker部署Dockerfile是通过使用Docker来构建和运行镜像的一种方式。可以使用手动部署的方式来熟悉部署流程,也可以使用插件方式来编写Dockerfile文件。 对于手动部署,首先需要修改docker配置,开放远程部署(上传)端口。可以通过编辑docker.service文件,在ExecStart=后添加配置"-H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock"来实现。 对于使用插件的方式,则是通过配置Dockerfile的命令参数来生成Dockerfile文件,并最终根据jar包和Dockerfile构建镜像。 在进行Docker部署之前,首先需要进行Docker的安装和部署。具体的流程包括配置Docker、测试Docker、镜像的分层以及镜像的构建。 Docker部署Dockerfile的具体步骤包括: 1. 配置Docker,确保远程部署(上传)端口已经开放。 2. 使用插件方式或手动方式编写Dockerfile文件。 3. 将需要的jar包和Dockerfile放置在同一个目录下。 4. 使用命令行工具进入到该目录,并执行docker build命令来构建镜像。 5. 根据构建后的镜像,运行相应的容器。 通过以上步骤,就可以成功部署Dockerfile并运行相应的容器。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [docker实战之Dockerfile构建部署项目(三)](https://blog.csdn.net/weixin_42322925/article/details/121697564)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Docker 1 (安装部署、Dockerfile详解)](https://blog.csdn.net/qq_38664479/article/details/119488160)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值