一篇复现Dockerfile指令

docker镜像结构

在这里插入图片描述

  • 共享宿主机kernel
  • base镜像提供的是最小的Linux发行版
  • 同一docker主机支持运行多种Linux发行版
  • 采用分层结构的最大好处是:共享资源

镜像运行的基本原理

在这里插入图片描述

  • Copy-on-Write 可写容器层
  • 容器层以下所有镜像层都是只读
  • docker从上往下依次查找文件
  • 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
  • 一个镜像最多127层

镜像获得方式

  • 基本镜像通常有软件官方提供
  • 企业镜像可以有官方镜像+dockerfile来生成
  • 系统关于镜像的获取方式有两种:
    • docker pull 镜像名
    • docker load -i 本地.tar.gz镜像包

制作镜像

当我们docker镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改:

  • 从已经创建的容器中更新镜像,并comimt提交这个镜像
  • 使用docker指令来创建一个新的镜像

基于dockerfile制作镜像

dockerfile介绍

  • docker中有个非常重要的概念叫做镜像image)。docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序,库,资源,配置等文件外,还包含了一些为运行时准备的一些==配置参数(如匿名卷,环境变量,用户等==)。镜像不包含任何动态数据,其内容在构建之后不会被改变
  • 镜像的定制实际上就是定制每一层所添加的配置,文件如果我们可以把每一层修改,安装,构建,操作的命令都写入一个脚本用这个脚本来构建,定制镜像。那么之前提及的无法重复的问题,镜像构建透明性的问题,体积的问题就都会解决。这个脚本就是dockerfiledockerfile是一个文本文件其内包含了一条条的指令Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建

(1)dockerfile编写的基本结构

  • dockerfile一般分为四部分基础镜像信息维护者信息镜像操作指令容器启动时执行指令,"#"为dockerfile中的注释

(2)一台主机可以有多个dockerfile

  • 要使用多个dockerfile创建镜像,可以在不同目录编写dockerfile然后在dockerfile所在的目录下构建新的镜像

(3)docker build基于dockerfile制作镜像的命令

注意

dockerfile中所包含需要的内容;如copy的文件,目录等,都需要在dockerfile同级目录下存在

格式

基本语法如下:

docker build [OPTIONS] PATH | URL | -

其中:

  • OPTIONS可选参数,用于配置构建过程的行为。例如,--tag-t 用于指定镜像的名称和标签

  • PATHDockerfile 所在的目录路径Docker 会在该目录下查找名为 Dockerfile默认的文件名,除非使用 -f 参数指定了其他文件名)的文件,并按照其中的指令构建镜像

  • URL Git 仓库的 URL如果 Dockerfile 位于远程 Git 仓库中,可以通过这个 URL 直接构建。

  • - 表示从标准输入stdin)读取 Dockerfile 内容,这通常与管道操作符 | 结合使用,以便从其他命令的输出中直接构建镜像。

  • -t:指定镜像名称

  • -f:指定Dockerfile文件

  • -c:CPU份额(相对权重)

  • -m:内存限制

  • --build-arg:设置构建时变量,就是构建时修改ARG指令的参数

PATH

  • 一般用.(即当前工作目录)作为上下文路径
  • 说明:Docker 在运行时分为 Docker 引|擎(也就是服务端守护进程)和客户端工具。 Docker 的引擎提供了一组REST API,被称为Docker Remote API,而如 docker命令这样的客户端工具,则是通过这组 APIDocker引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker功能,但实际上,一切都是使用的远程调用形式在服务端(Docker引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker引擎变得轻而易举。
  • 经常会需要将一些本地文件复制进镜像,比如通过 COPY 指令,当我们进行镜像构建的时候,并非所有定制都会通过 RUN 指令完成,会ADD 指令等,而 docker build 命令构建镜像、其实并非在本地构建,而是在服务端,也就是 Docker引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?
  • 这就引入了上下文的概念。 当构建的时候,用户会指定构建镜像上下文的路径docker build 命令得知这个路径后, 会将路径下所有内容打包,然后上传给 Docker引擎。这样Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件

上下文路径

  • Docker构建过程中,上下文路径是一个关键概念。当用户执行docker build命令时,需要指定一个构建镜像上下文路径Docker会将这个路径下的所有内容打包,然后上传给Docker引擎。这个路径通常包含Dockerfile,以及其他构建镜像所需的文件和目录

  • 默认情况下,如果不额外指定DockerfileDocker会在上下文目录下查找名为Dockerfile文件作为构建依据。但实际上,Dockerfile文件名并不要求必须为Dockerfile,而且并不要求必须位于上下文目录中。用户可以通过-f--file参数来指定某个文件作为Dockerfile,例如docker build -f dockerfiles/Dockerfile .

  • 此外,最佳实践建议是使用.dockerignore文件来排除不需要加入到build context中的文件,类似于.gitignore文件。这样可以确保构建镜像时只包含必要的文件,从而提高构建效率和镜像质量

  • 在指定上下文路径时,可以使用.来表示当前路径作为上下文路径,或者提供具体的文件或目录路径。请注意,构建过程中的网络、缓存等策略也可以通过相应的选项进行配置。

URL

docker build还支持从URL构建,docker build http://server/context.tar.gz,如果所给出的URL是个tar压缩包,那么docker引擎会下载这个,并自动解压缩,以其作为上下文开始构建

-

docker build还支持从标准输入中读取dockerfile进行构建

  • docker build - < dockerfile或者cat dockerfile | docker build -

如果标准输入传入的是文本文件,则将其视为dockerfile,并开始构建这种形式由于直接从标准输入中读取dockerfile的内容,它没有上下文,因此不可以像其他方法那样可以将本地文件copy进镜像之类的事情。

  • docker build - < context.tar.gz

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

Dockerfile指令-from指令

  • dockerfile文件中要大写
  • FROM指令必须是 Dockerfile非注释行的第一个指令,即一个 DockerfileFROM语句开始
  • FROM 指令用于为镜像文件构建过程指定基础镜像,后续的指令运行于此基础镜像所提供的运行环境
  • 实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会自动从 Docker 的公共库 pull 镜像下来。如果找不到指定的镜像文件,docker build 会返回一个错误信息
  • 如果有需求在一个Dockerfile中创建多个镜像FROM可以在一个 Dockerfie 中出现多次
  • 如果FROM语句没有指定镜像标签,则默认使用latest标签

格式

FROM 镜像名[:tag]
或
FROM 镜像名@digest

Dockerfile指令-maintainer指令

  • 用于让docker制作者提供本人的详细信息
  • 这个指令已经在较新的Docker版本中被弃用,取而代之的是使用label指令
  • 使用LABEL指令来设置维护者信息的示例如下:
LABEL key="描述内容"
  • 其中,描述可以是任意字符串,通常包含维护者名字和联系方式,如邮箱地址
  • key的名称随便起

示例

[root@server docker]# vim dockerfile
#description: test image
FROM busybox:latest
LABEL maintainer="huazi <huazi@163.com>"   

Dockerfile指令-copy指令

  • 上下文目录复制文件或目录镜像里的指定路径
  • Dockerfile中,copy 指令用于从构建的上下文context)中复制文件目录镜像中。
  • 构建的上下文通常是你在执行 docker build 命令时指定的目录或文件路径
  • copy 指令在镜像构建过程中执行

COPY 指令的基本语法如下:

COPY    宿主机的文件路径   镜像中的文件路径
  • 宿主机的文件路径:源文件或目录的路径,可以是一个或多个,支持通配符。
  • 镜像中的文件路径:目标路径,即文件或目录在镜像中的位置。

下面是一些 COPY 指令的示例:

  1. 复制单个文件镜像的根目录
COPY myfile.txt /
  1. 复制多个文件到镜像的某个目录
COPY   file1.txt   file2.txt    /mydir/
  1. 使用通配符复制多个文件镜像中
COPY   *.txt   /mydir/
  • 需要注意的是,如果目标路径在镜像中不存在Docker 会尝试创建它。如果 <dest> 是一个已存在的文件,copy 指令会替换它。如果 <dest> 是一个已存在的目录,copy 指令会将源文件或目录复制到该目录中。

  • 此外,copy指令add指令在功能上有些相似,但 add指令具有一些额外的功能,比如支持从URL下载文件自动解压缩.tar文件

  • 复制的文件必须是docker build上下文中的路径

  • 如果是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制

  • 使用copy指令源文件的各种元数据都会保留,比如读,写,执行权限,文件变更时间等;

  • 目标路径,即正在创建的image的文件系统路径,建议使用绝对路径

  • 目标路径不需要事先创建,如果目录不存在会在复制文件前先行在镜像中创建目录

示例1

[root@server docker]# echo "hello world" > index.html
[root@server docker]# ls  #要确保dockerfile的同级路径下有index.html文件 
dockerfile  index.html


[root@server docker]# vim dockerfile
#description: test image
FROM busybox:latest
LABEL maintainer="huazi <huazi@163.com>"
COPY  index.html  /data/web/html/  


[root@server docker]# docker build -t busyboxhttpd:v1  ./   #制作镜像
[+] Building 0.2s (7/7) FINISHED                                                                         docker:default
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 158B                                                                               0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                                  0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 31B                                                                                   0.0s
 => [1/2] FROM docker.io/library/busybox:latest                                                                    0.0s
 => CACHED [2/2] COPY index.html /data/web/html/                                                                   0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:a5a8571e609a0206d515d12b13b8f2ecc017e6a3de61a9b7b4d2faba6610921a                       0.0s
 => => naming to docker.io/library/busyboxhttpd:v1                                                                 0.0s


[root@server docker]# docker images
REPOSITORY     TAG       IMAGE ID       CREATED         SIZE
busyboxhttpd   v1        a5a8571e609a   3 minutes ago   1.24MB


[root@server docker]# docker run --name web -itd busyboxhttpd:v1   #运行镜像生成容器
2da1daa0f76049acb0b3fb1d5b7ddd89fdcb2f905f19a2aba3e4c90eceebc84e
[root@server docker]# docker exec -it web sh #进入容器
/ # cd /data/web/html  
/data/web/html # ls
index.html
/data/web/html # cat index.html
hello world

示例2

[root@server docker]# cp -r /etc/yum.repos.d/ ./
[root@server docker]# ll
总用量 8
-rw-r--r-- 1 root root 121  329 16:47 dockerfile
-rw-r--r-- 1 root root  12  329 16:36 index.html
drwxr-xr-x 2 root root  70  329 17:11 yum.repos.d


[root@server docker]# vim dockerfile
#description: test image
FROM busybox:latest
LABEL maintainer="huazi <huazi@163.com>"
COPY index.html /data/web/html/
COPY ./yum.repos.d  /etc/yum.repos.d/

#如果是复制目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制
#在dockerfile的同级目录下准备好yum.repos.d目录


[root@server docker]# docker build -t busyboxhttpd:v2 ./     #制作镜像
[+] Building 0.2s (8/8) FINISHED                                                                         docker:default
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 198B                                                                               0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                                  0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [1/3] FROM docker.io/library/busybox:latest                                                                    0.0s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 2.86kB                                                                                0.0s
 => CACHED [2/3] COPY index.html /data/web/html/                                                                   0.0s
 => [3/3] COPY ./yum.repos.d  /etc/yum.repos.d/                                                                    0.0s
 => exporting to image                                                                                             0.1s
 => => exporting layers                                                                                            0.1s
 => => writing image sha256:2141dc00c0c0a3850e43c086f06cbca040aac603b65c3cd043c940faac974c41                       0.0s
 => => naming to docker.io/library/busyboxhttpd:v2                                                                 0.0s


[root@server docker]# docker run --name web1 -itd busyboxhttpd:v2  #运行容器
0fc2106fc16f66b59a105c185c595545a5ac9aafe4c7488c0af997ea58a300fe
[root@server docker]# docker exec -it web1 sh
/ # cd /etc/yum.repos.d/   #进入容器
/etc/yum.repos.d # ls
RHELserver.repo  docker-ce.repo   redhat.repo
/etc/yum.repos.d # cd
/ # cd /data/web/html
/data/web/html # ls
index.html

Dockerfile指令-add指令

  • add指令类似于copy指令add支持使用.tar文件URL文件
  • Dockerfile中的add指令是一个强大的工具,用于将文件目录URL标记的文件从构建上下文(通常是Dockerfile所在的目录)复制镜像中。以下是关于ADD指令的详细解释:
ADD <src>... <dest>
  • <src>指定了源文件或目录的路径,也可以是URL
  • <dest>指定了在镜像中的目标路径

功能特性

  1. 自动解压:如果源文件(本地系统上,不是URL上的)是tar类型的压缩文件,ADD指令会自动解压它到目标路径。
  2. 网络资源支持add指令可以从URL获取文件并添加到镜像中,类似于wget命令。然而,为了保持镜像尽可能小,官方推荐在获取网络资源后使用RUN命令结合curl或wget来删除不再需要的文件,以避免在镜像中额外添加不必要的层。
  3. 路径创建:如果目标路径不存在,add指令自动创建它

copy指令的区别

COPY指令ADD指令在功能和使用方式上类似,但COPY指令不支持自动解压和从网络获取文件。因此,在不需要这些额外功能的情况下,使用COPY指令更为简单和直接。

示例

  1. 本地文件添加到镜像
ADD   myfile.txt   /mydir/
  1. 目录及其内容添加到镜像
ADD    mydir/    /mydir/
  1. URL添加文件到镜像
ADD    https://example.com/myfile.txt    /mydir/
  • 如果是一个本地系统上的压缩格式的.tar文件,它将被展开为一个目录,其行为类似于"tar-x"命,然而,通过URL获取到的tar文件将不会自动展开

示例

[root@server docker]# vim dockerfile
#description: test image
FROM busybox:latest
LABEL maintainer="huazi <huazi@163.com>"
COPY index.html /data/web/html/
COPY ./yum.repos.d  /etc/yum.repos.d/
ADD http://nginx.org/download/nginx-1.15.8.tar.gz  /usr/local/src/  



[root@server docker]# docker build -t busyboxhttpd:v3 ./
[+] Building 3.4s (10/10) FINISHED                                                                       docker:default
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 265B                                                                               0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                                  0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [1/4] FROM docker.io/library/busybox:latest                                                                    0.0s
 => [4/4] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  /usr/local/src/                                       3.1s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 198B                                                                                  0.0s
 => CACHED [2/4] COPY index.html /data/web/html/                                                                   0.0s
 => CACHED [3/4] COPY ./yum.repos.d  /etc/yum.repos.d/                                                             0.0s
 => [4/4] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  /usr/local/src/                                       0.1s
 => exporting to image                                                                                             0.1s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:7251cc27a9053f755582ae72aff9d92d3d14f728a89c44c0a3b6d0ae106fd3f8                       0.0s
 => => naming to docker.io/library/busboxhttpd:v3                                                                  0.0s



[root@server docker]# docker run --name web -itd busyboxhttpd:v3
ff95162ff1f3b6591274d6f482ae933be85b19a2d88d88113e047b0f33d435ec
[root@server docker]# docker exec -it web sh
/ # ls /usr/local/src  #可以看到没有解压
nginx-1.15.8.tar.gz   

Dockerfile指令-workdir指令

  • 用于为dockerfile中所有的run,cmd,copy,add等指令设定工作目录
  • workdir指令Dockerfile中用于设置工作目录,或者称为当前目录
  • 指定了workdir后,容器启动时执行的命令会在该目录下执行

workdir指令的语法如下:

WORKDIR /path/to/workdir
  • 其中,/path/to/workdir是你想要设置的工作目录的路径
  • 如果目录不存在workdir会自动创建它

下面是一个使用workdir指令的示例:

# 基础镜像
FROM centos

# 设置工作目录为/app
WORKDIR /app

# 在/app目录下执行一些命令,比如安装软件或复制文件
RUN yum install some-package -y
COPY myfile.txt .

# 启动容器时执行的命令会在/app目录下执行
CMD ["some-command"]
  • 在这个例子中,我们首先设置工作目录/app,然后在这个目录下执行RUNCOPY指令。最后,CMD指令启动的命令也会在/app目录下执行。
  • dockerfile文件中,workdir指令可以出现多次
  • 如果该目录不存在workdir会帮你建立目录

示例

[root@server docker]# vim dockerfile
#description: test image
FROM busybox:latest
LABEL maintainer="huazi <huazi@163.com>"
COPY index.html /data/web/html/
COPY ./yum.repos.d  /etc/yum.repos.d/
WORKDIR /huazi/home/
ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/


[root@server docker]# docker build -t busyboxhttpd:v4 ./  #创建镜像
[+] Building 1.0s (11/11) FINISHED                                                                       docker:default
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 278B                                                                               0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                                  0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [1/5] FROM docker.io/library/busybox:latest                                                                    0.0s
 => CACHED [5/5] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                         0.8s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 198B                                                                                  0.0s
 => CACHED [2/5] COPY index.html /data/web/html/                                                                   0.0s
 => CACHED [3/5] COPY ./yum.repos.d  /etc/yum.repos.d/                                                             0.0s
 => [4/5] WORKDIR /huazi/home/                                                                                     0.0s
 => [5/5] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                                0.0s
 => exporting to image                                                                                             0.1s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:5413ad4f732008c16d639d267b9b341ff15b46da2b02ff66bc6eae520c2c7aff                       0.0s
 => => naming to docker.io/library/busyboxhttpd:v4                                                                 0.0s


[root@server docker]# docker run --name web -itd busyboxhttpd:v4  #运行镜像
0c3898fb881228fbc52e47e043a76739120f20206f90152d29d4111e45a9f03c
[root@server docker]# docker exec -it web sh  #进入镜像,可以发现,一进来就会进入/huazi/home目录下
/huazi/home # cd /
/ # cd /huazi/home
/huazi/home # ls
src
/huazi/home # cd src
/huazi/home/src # ls
nginx-1.15.8.tar.gz

Dockerfile指令-volume指令

  • Dockerfile中的volume指令用于在Docker镜像声明一个或多个目录作为挂载点
  • Docker容器基于这个镜像运行时,这些目录可以挂载宿主机上目录或者其他容器上
  • 使用volume指令声明,不会实现数据的持久化
  • 声明的目录在镜像中

volume指令的基本语法如下:

VOLUME   镜像中的文件位置
  • 你可以指定一个或多个目录作为挂载点这些目录在容器运行时会自动创建(如果不存在的话),并且会被标记为挂载点,以供后续挂载操作使用。

以下是一个使用VOLUME指令的Dockerfile示例:

# 基础镜像
FROM ubuntu:latest

# 声明一个挂载点
VOLUME   /data
  • 在这个例子中,/data目录被声明为一个挂载点。当基于这个Dockerfile构建的镜像运行容器时,/data目录将自动创建,并且可以被挂载宿主机或者其他容器上

  • 需要注意的是,volume指令只是声明了挂载点并不会自动执行挂载操作

  • 挂载操作是在容器运行时通过使用docker run命令的-v参数来指定挂载点,实现永久挂载

示例

[root@server docker]# vim dockerfile
#description: test image
FROM busybox:latest
LABEL maintainer="huazi <huazi@163.com>"
COPY index.html /data/web/html/
COPY ./yum.repos.d  /etc/yum.repos.d/
WORKDIR /huazi/home/
ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/
VOLUME /data/mysql   #这是容器中的挂载点


[root@server docker]# docker build -t busyboxhttpd:v5 ./  #创建镜像
[+] Building 1.0s (11/11) FINISHED                                                                       docker:default
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 297B                                                                               0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                                  0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [5/5] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                                0.9s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 198B                                                                                  0.0s
 => [1/5] FROM docker.io/library/busybox:latest                                                                    0.0s
 => CACHED [2/5] COPY index.html /data/web/html/                                                                   0.0s
 => CACHED [3/5] COPY ./yum.repos.d  /etc/yum.repos.d/                                                             0.0s
 => CACHED [4/5] WORKDIR /huazi/home/                                                                              0.0s
 => CACHED [5/5] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                         0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:deedcfdefb575ec612003e2c6809038bf3fa9dbe73092d21bdb6208ba4a8a622                       0.0s
 => => naming to docker.io/library/busyboxhttpd:v5                                                                 0.0s


#在主机上创建共享目录
[root@server ~]# mkdir /data


[root@server docker]# docker run --name web -itd -v /data:/data/mysql busyboxhttpd:v5
2287b5c7866b6b09327a6e2df9ad9c472c8e9c55b9b35883d66ab9a599e0ba05
[root@server docker]# docker exec -it web sh
/huazi/home # cd /
/ # cd /data/mysql
/data/mysql # ls
/data/mysql # touch file1.txt
/data/mysql # ls
file1.txt
/data/mysql # exit

[root@server ~]# cd /data
[root@server data]# ls   #看到了在容器中创建的file1.txt
file1.txt  

Dockerfile指令-expose指令

  • Dockerfile中的expose指令用于声明容器运行时所监听的网络端口
  • 它的作用是告诉Docker守护进程容器在运行时需要监听哪些网络端口,以便外部可以访问这些端口

expose指令的语法格式如下:

EXPOSE <port> [<port>/<protocol>...]
  • 其中<port>表示需要被监听的端口号,而[<port>/<protocol>...]可选的,用于指定协议类型,如TCP或UDP等。
  • 如果未指定协议,则默认为TCP
  • 需要注意的是,expose指令声明的端口必须与容器内应用程序监听端口一致否则无法正常通信。此外
  • expose指令并不会自动将这些端口映射到主机上任何端口。它只是向用户以及后续的Dockerfile指令传达这个信息,以便更好地配置和管理容器
  • 要在容器运行时expose指令声明的端口映射到宿主机端口,需要使用docker run命令的-p参数。例如:
docker run -p <宿主机端口号>:<容器端口号> <镜像名>
  • 在某些特殊情况下,如使用了--net=host宿主机网络模式,容器内expose指令暴露的端口会直接使用宿主机对应的端口不存在映射关系
  • expose指令可以一次指定多个端口,例如:
EXPOSE 11211/udp 11211/tcp
  • 仅对容器中的端口进行声明不做任何操作

示例

[root@server docker]# vim dockerfile
#description: test image
FROM nginx:latest
LABEL maintainer="huazi <huazi@163.com>"
COPY index.html /data/web/html/
COPY ./yum.repos.d  /etc/yum.repos.d/
WORKDIR /huazi/home/
ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/
VOLUME /data/mysql
EXPOSE 80/tcp



[root@server docker]# docker build -t busyboxhttpd:v6 ./
[+] Building 0.9s (11/11) FINISHED                                                                       docker:default
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 307B                                                                               0.0s
 => [internal] load metadata for docker.io/library/nginx:latest                                                    0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [1/5] FROM docker.io/library/nginx:latest                                                                      0.1s
 => CACHED [5/5] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                         0.6s
 => [internal] load build context                                                                                  0.1s
 => => transferring context: 198B                                                                                  0.0s
 => [2/5] COPY index.html /data/web/html/                                                                          0.1s
 => [3/5] COPY ./yum.repos.d  /etc/yum.repos.d/                                                                    0.1s
 => [4/5] WORKDIR /huazi/home/                                                                                     0.0s
 => [5/5] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                                0.0s
 => exporting to image                                                                                             0.1s
 => => exporting layers                                                                                            0.1s
 => => writing image sha256:0259da332cba5bfcee40d9ebc6f0b39a9660a7f993c108747a65b462e6a1b23a                       0.0s
 => => naming to docker.io/library/busyboxhttpd:v6                                                                 0.0s



[root@server docker]# docker run --name web -P -itd busyboxhttpd:v6
56d99631ac8ce2af67cadb92d1ef0afb382ef3cfce4b0f934706a5ff9eb9d6ea
[root@server docker]# docker ps
CONTAINER ID   IMAGE             COMMAND                   CREATED         STATUS         PORTS
            NAMES
56d99631ac8c   busyboxhttpd:v6   "/docker-entrypoint.…"   8 seconds ago   Up 6 seconds   0.0.0.0:32769->80/tcp, :::32769->80/tcp   web

#另外打开一个终端,验证nginx服务的80端口
[root@server ~]# docker port web
80/tcp -> 0.0.0.0:32769
80/tcp -> [::]:32769
[root@server ~]# wget 127.0.0.1:32769
--2024-03-29 18:46:12--  http://127.0.0.1:32769/
正在连接 127.0.0.1:32769... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:615 [text/html]
正在保存至: “index.html”

index.html                    100%[=================================================>]     615  --.-KB/s  用时 0s

2024-03-29 18:46:12 (4.72 MB/s) - 已保存 “index.html” [615/615])

Dockerfile指令-env指令

  • Dockerfile中的env指令用于设置容器中的环境变量
  • 这些环境变量后续的指令(如run)和容器运行时都可以直接使用

env指令的基本语法格式如下:

ENV    key=value ...
  • 你可以在Dockerfile中设置单个或多个环境变量每个环境变量通过键值对形式进行定义。例如:
ENV VERSION=1.0 DEBUG=on
  • 此外,你也可以在一行中设置多个环境变量,只需用空格分隔即可:
ENV VAR1=value1 VAR2=value2
  • 如果环境变量的值包含格,你可以使用双引号将其括起来
ENV NAME="Happy Feet"
  • Dockerfile后续的指令中,你可以使用${variable_name}$variable_name的格式来引用这些环境变量。例如,在run指令中使用环境变量
ENV DIR=/app
RUN mkdir $DIR
  • 此外,env指令中的环境变量还支持一些bash修饰符,如${variable:-word},它表示如果variable设置了,则使用其值;如果未设置,则使用word作为默认值

示例

[root@server docker]# vim dockerfile
#description: test image
FROM busybox:latest
LABEL maintainer="huazi <huazi@163.com>"
ENV doc_root=/data/web/html/
COPY index.html $doc_root
COPY ./yum.repos.d  /etc/yum.repos.d/
WORKDIR /huazi/home/
ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/
VOLUME /data/mysql
EXPOSE 80/tcp



[root@server docker]# docker build -t busyboxhttpd:v7 ./
[+] Building 1.0s (11/11) FINISHED                                                                       docker:default
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 333B                                                                               0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                                  0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [1/5] FROM docker.io/library/busybox:latest                                                                    0.0s
 => [5/5] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                                0.9s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 198B                                                                                  0.0s
 => CACHED [2/5] COPY index.html /data/web/html/                                                                   0.0s
 => CACHED [3/5] COPY ./yum.repos.d  /etc/yum.repos.d/                                                             0.0s
 => CACHED [4/5] WORKDIR /huazi/home/                                                                              0.0s
 => CACHED [5/5] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                         0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:9bd4cbe6740c6519b6b4189763115957c11999d83ae2aeab811b86eb8f1da699                       0.0s
 => => naming to docker.io/library/busyboxhttpd:v7                                                                 0.0s


[root@server docker]# docker run --name web -itd busyboxhttpd:v7
acb15d9ed65706c625faeb297032de5cfe58fde50471d276cb58f5021fbbd29b
[root@server docker]# docker exec -it web sh
/huazi/home # cd /data/web/html
/data/web/html # ls
index.html
#在启动容器时,使用docker run -e 设置修改变量
[root@server docker]# docker run --name web -e doc_root=/huazi  -itd busyboxhttpd:v7

Dockerfile指令-run指令

  • Dockerfile中的run指令是用于在构建镜像执行命令的。
  • 这些命令可以是任何在基础镜像可用的命令,包括安装软件包、设置环境变量、复制文件等。
  • run指令执行的结果会被缓存,并作为新的镜像层提交。

run指令的基本语法如下:

  • Shell格式RUN <command>。这种格式会在一个shell环境中执行命令,类似于在终端中直接运行命令。
  • Exec格式RUN ["executable", "param1", "param2"]。这种格式不会启动shell环境,而是直接运行指定的可执行文件及其参数
  1. 复制文件或目录
    虽然通常使用COPY指令来复制文件或目录到镜像中,但RUN指令也可以结合shell命令来实现类似的操作,例如:
RUN mkdir /mydir && cp /source/file.txt /mydir/
  1. 执行脚本
RUN chmod +x /path/to/script.sh && /path/to/script.sh
  1. 使用Exec格式执行命令:
RUN ["/bin/bash", "-c", "echo Hello, World!"]
  • 在构建镜像时,Docker会按照Dockerfile中的顺序执行run指令。每次run指令执行后,都会创建一个新的镜像层。因此,为了保持镜像的轻量级和高效,应尽量减少不必要的run指令,并将多个命令合并成一个run指令执行,这样可以减少镜像的层数,从而提高构建和运行的效率

需要注意的是,run指令构建镜像时执行,而不是在容器运行时执行。因此,它主要用于构建镜像时的配置和准备工作,而不是用于定义容器运行时的行为。

  • 容器运行时的行为通常由cmd指令entrypoint指令来定义。

示例

  • 通过run解压add指令URL的.tar.gz压缩包
[root@server docker]# vim dockerfile
#description: test image
FROM busybox:latest
LABEL maintainer="huazi <huazi@163.com>"
ENV doc_root=/data/web/html/ web_server_package="nginx-1.15.8.tar.gz"
COPY index.html $doc_root
COPY ./yum.repos.d  /etc/yum.repos.d/
WORKDIR /huazi/home/
ADD http://nginx.org/download/${web_server_package}  ./src/
VOLUME /data/mysql
EXPOSE 80/tcp
RUN cd ./src && tar -zxvf ${web_server_package}
#run后直接跟shell命令


[root@server docker]# docker build -t busyboxhttpd:v8 ./
[+] Building 2.5s (12/12) FINISHED                                                                       docker:default
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 423B                                                                               0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                                  0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [1/6] FROM docker.io/library/busybox:latest                                                                    0.0s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 198B                                                                                  0.0s
 => [5/6] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                                0.8s
 => CACHED [2/6] COPY index.html /data/web/html/                                                                   0.0s
 => CACHED [3/6] COPY ./yum.repos.d  /etc/yum.repos.d/                                                             0.0s
 => CACHED [4/6] WORKDIR /huazi/home/                                                                              0.0s
 => CACHED [5/6] ADD http://nginx.org/download/nginx-1.15.8.tar.gz  ./src/                                         0.0s
 => [6/6] RUN cd ./src && tar -zxvf nginx-1.15.8.tar.gz                                                            1.4s
 => exporting to image                                                                                             0.2s
 => => exporting layers                                                                                            0.2s
 => => writing image sha256:055e6f67f2af7679593b2b35c34d426cc1d6f0a6bd1d2fcc9150141f4b6e450a                       0.0s
 => => naming to docker.io/library/busyboxhttpd:v8                                                                 0.0s



[root@server docker]# docker run --name web -itd busyboxhttpd:v8
d181e873b02bc901205015043398ef51531e5a87e1720f8515dc93b105c8175b
[root@server docker]# docker exec -it web sh
/huazi/home # cd src
/huazi/home/src # ls
nginx-1.15.8         nginx-1.15.8.tar.gz
/huazi/home/src # cd nginx-1.15.8/
/huazi/home/src/nginx-1.15.8 # ls   #可以看到已经解压了
CHANGES     LICENSE     auto        configure   html        src
CHANGES.ru  README      conf        contrib     man

Dockerfile指令-cmd指令

  • Dockerfile中的cmd指令用于容器启动时要执行的命令及其参数。
  • 这个指令在构建镜像时不会执行,而是启动容器执行
  • 一个Dockerfile中只能有一个cmd指令,如果写了多个,那么只有最后一个会生效

cmd指令有三种格式:

  1. exec格式CMD ["executable","param1","param2"]。这是首选的格式,因为它避免了shell字符串解析的问题,并且它是以exec方式运行的,这意味着它不会启动一个额外的shell

  2. shell格式CMD command param1 param2。在这种格式中,命令会在/bin/sh -c中执行,这意味着它会启动一个shell。注意,如果你的命令依赖于shell的特性(如变量替换或通配符扩展),那么你应该使用shell格式

一个Dockerfile中只能有一个cmd指令,如果写了多个,那么只有最后一个会生效。当运行容器时,可以使用docker run命令的命令行参数覆盖cmd指令指定的默认命令

下面是一个简单的示例,展示了如何在Dockerfile中使用cmd指令

# 基础镜像
FROM ubuntu:latest

# 安装所需的软件包
RUN apt-get update && apt-get install -y nginx

# 将nginx的配置文件复制到容器中
COPY nginx.conf /etc/nginx/nginx.conf

# 定义容器启动时执行的命令
CMD ["nginx", "-g", "daemon off;"]
  • 在这个例子中,当基于这个Dockerfile构建的镜像创建并启动容器时,nginx会以守护进程模式关闭的方式启动。
  • 需要注意的是,cmd指令定义的命令可以被docker run命令行的参数所覆盖。例如,你可以使用docker run -d myimage /bin/bash来启动一个基于myimage镜像的容器,并运行/bin/bash,而不是cmd指令中定义的命令。
  • 此外,cmd指令也可以与entrypoint指令结合使用,以提供更灵活的容器启动配置。entrypoint指令用于配置容器,使其可执行化
  • cmd指令则可以为entrypoint提供默认参数或定义容器启动时要执行的命令。

示例

  • cmd指令Dockerfile中用于定义容器启动时的默认命令和参数。当容器以docker run命令启动并且没有指定其他命令时,cmd中定义的命令会被执行
  • 以下是一些使用cmd指令的示例:

示例1:运行一个简单的echo命令

FROM ubuntu:latest

# 定义CMD指令来运行echo命令
CMD ["echo", "Hello, World!"]

当你基于这个Dockerfile构建并启动一个容器时,它将输出Hello, World!

示例2:启动一个Web服务器

FROM nginx:latest

# 复制配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 容器启动时启动nginx
CMD ["nginx", "-g", "daemon off;"]

在这个例子中,我们使用了官方的nginx镜像,并复制了一个自定义的配置文件cmd指令确保了当容器启动时,nginx会以非守护进程模式运行。

示例3:运行一个Python脚本

FROM python:3.8

# 将工作目录设置为/app
WORKDIR /app

# 将当前目录内容复制到容器的/app内
COPY . /app

# 安装任何需要的包
RUN pip install --no-cache-dir -r requirements.txt

# 定义CMD指令来运行Python脚本
CMD ["python", "app.py"]

在这个例子中,我们基于python:3.8镜像构建了一个容器,其中包含了Python环境和一个名为app.pyPython脚本cmd指令确保当容器启动时,app.py脚本会被执行。

示例4:使用shell格式运行命令

FROM ubuntu:latest

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

# 使用shell格式定义CMD
CMD echo "Fetching Google" && curl http://google.com

在这个例子中,cmd指令使用了shell格式运行两个命令。首先,它输出一条消息,然后使用curl命令访问Google。请注意,使用shell格式时,整个命令字符串会被/bin/sh -c解释,这可能会导致一些特殊字符或变量扩展被处理。

示例5:结合entrypointcmd

entrypointcmd同时存在时,CMD的内容会被作为参数传递给entrypoint

FROM ubuntu:latest

# 复制脚本到容器中
COPY entrypoint.sh /entrypoint.sh

# 设置ENTRYPOINT为脚本
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]

# CMD指令定义的参数会被传递给ENTRYPOINT的脚本
CMD ["arg1", "arg2"]

在这个例子中,如果entrypoint.sh是一个bash脚本,它可以使用$@来获取所有传递给它的参数,这些参数在docker run命令中没有额外指定的情况下,将是CMD指令中定义的arg1arg2

CMD指令在Dockerfile中提供了很大的灵活性,允许你定义容器启动时的默认行为。但是,需要注意的是,CMD指令可以被docker run命令中的参数所覆盖。如果需要更稳定的容器启动行为,可以考虑使用ENTRYPOINT

Dockerfile指令-entrypoint指令

  • Dockerfile中的entrypoint指令用于配置容器启动时执行的命令及其参数。与CMD指令类似
  • entrypoint也是定义容器启动行为的指令,但两者在功能和用法上有一些区别。

entrypoint指令有两种格式:

  1. exec格式ENTRYPOINT ["executable", "param1", "param2"]这是推荐的方式,因为它不会通过shell来执行,而是直接调用exec函数来启动程序,这样可以避免shell解析带来的问题,并减少容器启动时的开销。
  2. shell格式ENTRYPOINT command param1 param2。这种格式会在/bin/sh -c中执行,即会启动一个shell来执行命令。这种格式在某些情况下可能更灵活,但请注意它可能带来额外的开销和安全问题。

CMD指令不同的是,entrypoint指令配置的命令是容器启动时一定会执行的,即使运行docker run时没有指定其他命令。这使得entrypoint非常适合用于设置容器为可执行文件,并将容器转变为一个特定的应用或服务。

  • 此外,entrypoint指令还允许在运行docker run时传递参数给entrypoint命令。这些参数会作为entrypoint命令的额外参数。例如,如果Dockerfile中的entrypoint指令设置为ENTRYPOINT ["/bin/echo", "Hello"],那么在运行docker run image -it world时,输出将会是Hello world

  • 另外,需要注意的是,entrypoint指令定义的命令也可以通过docker run命令的--entrypoint参数进行覆盖。这意味着你可以在运行容器时动态地替换entrypoint指令中定义的命令。

示例

entrypoint指令Dockerfile中非常有用,它允许你定义容器启动时默认执行的命令。下面是一些使用entrypoint指令的示例:

示例1:使用exec格式运行一个可执行文件

假设你有一个名为my_app的可执行文件,你想要在容器启动时运行它:

FROM ubuntu:latest

# 将可执行文件复制到容器中
COPY my_app /usr/local/bin/my_app

# 设置ENTRYPOINT为my_app
ENTRYPOINT ["/usr/local/bin/my_app"]

当你基于这个Dockerfile构建并运行一个容器时,my_app会自动执行。

示例2:传递参数给entrypoint

你可以在docker run命令后面添加参数,这些参数将会传递给entrypoint指令指定的命令。

FROM ubuntu:latest

# 复制脚本到容器中
COPY entrypoint.sh /entrypoint.sh

# 设置ENTRYPOINT为脚本,并传递参数
ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh可能看起来像这样:

#!/bin/bash
echo "Running with arguments: $@"
exec "$@"

运行容器时,你可以传递额外的参数给ENTRYPOINT

docker run -it --name mycontainer myimage arg1 arg2 arg3

在这个例子中,arg1, arg2, 和 arg3 将会被传递给/entrypoint.sh脚本,并且脚本中的$@会扩展为这些参数。

示例3:结合cmd和entrypoint

CMD指令可以作为entrypoint指令的默认参数。如果entrypoint是一个可执行文件,那么CMD将作为默认参数传递给这个文件。如果entrypoint一个shell脚本,那么CMD会被当作是传递给shell脚本参数

FROM ubuntu:latest

# 复制脚本到容器中
COPY my_cmd.sh /my_cmd.sh

# 设置ENTRYPOINT为shell脚本
ENTRYPOINT ["/bin/bash", "/my_cmd.sh"]

# CMD指令定义的参数会被传递给ENTRYPOINT的脚本
CMD ["arg1", "arg2"]

在这个例子中,如果你运行容器时没有提供任何额外的参数,arg1arg2会被传递给/my_cmd.sh脚本。如果你提供了额外的参数,它们会覆盖CMD指令中定义的参数。

示例4:使用entrypoint运行服务

如果你正在构建一个运行服务的容器(比如一个web服务器),你可能会使用entrypoint来启动这个服务。

FROM nginx:latest

# 复制配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 设置ENTRYPOINT来启动nginx服务
ENTRYPOINT ["nginx", "-g", "daemon off;"]

在这个例子中,容器启动时会直接运行nginx命令,并且以非守护进程模式运行,这样可以让nginx在前台运行,避免容器立即退出。

cmd和entrypoint总结

  • CMD命令会被命令行的中的命令替代,如果不想被替代,需要ENTRYPOINT

Dockerfile指令-HEALTHCHECK指令

healthcheck

介绍

Dockerfile中的HEALTHCHECK指令是用于配置容器健康检查的。通过HEALTHCHECK指令,可以定义容器运行时的健康检查行为,以便及时监控容器的状态,并在发现问题时进行处理。

HEALTHCHECK指令有两种形式:

  1. HEALTHCHECK [options] CMD :这种形式包含一个或多个选项,如interval(间隔)、timeout(超时)等。从容器运行起来开始计时,每隔interval秒进行一次健康检查。如果命令执行超过timeout秒,则视为超时并标记为错误状态。

例如:

HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/ || exit 1

在这个例子中,容器每5秒执行一次健康检查,如果curl命令在3秒内没有响应,则认为容器不健康。

  1. HEALTHCHECK NONE:这种形式用于禁止从父镜像继承的HEALTHCHECK指令生效。如果基础镜像中已经定义了健康检查,而你不希望使用它,可以在你的Dockerfile中使用这个指令来禁用它。

HEALTHCHECK指令的返回值决定了该次健康检查的成功与否:

  • 0:表示健康检查成功,容器状态为healthy。
  • 1:表示健康检查失败,容器状态可能变为unhealthy(如果连续失败次数达到一定阈值)。
  • 2:保留值,不要使用这个返回值。

只有当HEALTHCHECK指定的命令返回0时,Docker才认为容器已经处于正常状态。否则,Docker会认为容器还在启动中。

通过合理配置HEALTHCHECK指令,可以确保容器在运行过程中保持健康状态,从而提供稳定可靠的服务。

示例

Dockerfile中的HEALTHCHECK指令允许你指定一个命令来检查容器是否健康。这对于确保服务在运行并且能够响应请求非常有用。以下是一些HEALTHCHECK指令的示例:

示例1:简单HTTP检查

如果你正在运行一个Web服务器,你可以使用curl命令来检查服务是否正在运行并响应HTTP请求。

FROM nginx:latest

# 复制自定义的nginx配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 健康检查:检查nginx是否响应HTTP请求
HEALTHCHECK --interval=5s --timeout=3s --retries=3 \
  CMD curl --fail http://localhost/ || exit 1

在这个例子中,HEALTHCHECK指令设置了三个重要的参数:

  • interval=5s:每5秒检查一次。
  • timeout=3s:每次健康检查命令运行的最大时间为3秒。
  • retries=3:如果命令失败,则重试3次。

如果curl命令返回非零状态码(由于服务器未响应或返回了错误),则容器被视为不健康。

示例2:脚本检查

你可以编写一个脚本来执行更复杂的健康检查,并在HEALTHCHECK指令中调用这个脚本。

FROM ubuntu:latest

# 安装必要的工具
RUN apt-get update && apt-get install -y curl

# 复制自定义的健康检查脚本
COPY healthcheck.sh /healthcheck.sh
RUN chmod +x /healthcheck.sh

# 健康检查:运行自定义脚本
HEALTHCHECK --interval=30s --timeout=10s --retries=5 \
  CMD ["/healthcheck.sh"]

healthcheck.sh脚本中,你可以编写逻辑来检查服务的状态,比如:

#!/bin/bash
# healthcheck.sh

# 检查服务的逻辑...
if [ some_condition ]; then
    exit 0  # 健康
else
    exit 1  # 不健康
fi

示例3:禁用继承的健康检查

如果你基于一个带有HEALTHCHECK指令的基础镜像构建镜像,但你想要禁用这个健康检查,你可以使用HEALTHCHECK NONE

FROM some-base-image-with-healthcheck

# 禁用继承的健康检查
HEALTHCHECK NONE

# ... 其他指令 ...

在上面的示例中,some-base-image-with-healthcheck是一个带有健康检查指令的基础镜像,通过在新的Dockerfile中使用HEALTHCHECK NONE,你禁用了这个继承的健康检查。

通过合理地使用HEALTHCHECK指令,你可以确保你的容器在出现问题时能够被及时发现,并采取适当的措施,比如重启容器或触发警报。

Dockerfile指令-ONBUILD指令

onbuild

介绍

ONBUILD 是 Dockerfile 中的一个指令,它用于定义触发器,这些触发器将在构建的子镜像中执行。换句话说,当当前镜像作为其他镜像的基础镜像时,ONBUILD 指令后面的命令会被执行。

ONBUILD 指令的基本语法是:

ONBUILD <INSTRUCTION>

这里的 <INSTRUCTION> 可以是任何有效的 Dockerfile 指令,如 RUNCOPYADD 等。当一个新的镜像基于当前镜像构建时,这些指令会被插入到子镜像的 Dockerfile 中,并在适当的时机执行。

这个特性对于构建可复用的基础镜像特别有用,比如创建一个包含特定配置或依赖的基础镜像,其他项目可以直接基于这个基础镜像构建,无需重复相同的配置和依赖安装步骤。

下面是一个简单的 ONBUILD 指令的示例:

FROM ubuntu:latest

# 假设这是一个基础镜像,我们希望在其上自动执行一些命令
ONBUILD RUN apt-get update && apt-get install -y some-package
ONBUILD COPY ./some-directory /app/some-directory

# ... 其他基础配置 ...

在这个例子中,当另一个 Dockerfile 使用 FROM 指令基于这个镜像构建时,RUNCOPY 指令会在子镜像的构建过程中自动执行。

需要注意的是,ONBUILD 指令的触发时机是在子镜像的 FROM 指令之后,但在子镜像的其他指令之前。因此,它们可以用于在子镜像的构建过程中添加一些前置操作。

使用 ONBUILD 指令时要谨慎,因为它可能会引入一些难以察觉的副作用,特别是当基础镜像的 ONBUILD 指令与子镜像的指令发生冲突或产生不必要的重复时。因此,在创建基础镜像时,最好明确文档化 ONBUILD 指令的用途和行为,以便其他开发者能够理解和正确使用。

示例

ONBUILD 指令在 Dockerfile 中用于定义一些指令,这些指令将在基于当前镜像构建的子镜像时自动执行。这在创建可复用的基础镜像时非常有用,因为你可以将通用的配置和安装步骤放在基础镜像中,并在派生镜像中自动应用这些步骤。

下面是一个 ONBUILD 指令的示例:

# 基础镜像,这里以 Ubuntu 为例
FROM ubuntu:latest

# 设置工作目录
WORKDIR /app

# 使用 ONBUILD 指令来定义一个 RUN 指令,该指令将在基于这个镜像构建的新镜像中执行
ONBUILD RUN apt-get update && apt-get install -y curl

# 使用 ONBUILD 指令来复制一个文件到派生镜像中
ONBUILD COPY ./config.json /app/config.json

# 基础镜像的其它配置和安装步骤...

假设我们有一个名为 my-base-image 的镜像,它是基于上面的 Dockerfile 构建的。现在,如果我们想要创建一个新的镜像,并且希望自动执行在 my-base-image 中定义的 ONBUILD 指令,我们可以这样做:

# 新的镜像,基于 my-base-image
FROM my-base-image

# 由于 my-base-image 中有 ONBUILD 指令,下面的步骤会在构建时自动执行
# RUN apt-get update && apt-get install -y curl
# COPY ./config.json /app/config.json

# 新镜像的其它配置和步骤...

在构建基于 my-base-image 的新镜像时,ONBUILD 指令中定义的 RUNCOPY 会自动执行。这意味着,尽管这些指令没有直接写在新镜像的 Dockerfile 中,但它们仍然会被执行。

请注意,ONBUILD 指令只会在基于当前镜像构建新的镜像时触发,并不会在当前镜像的构建过程中执行。因此,在编写 ONBUILD 指令时,要确保它们是针对派生镜像有意义的,并且不会产生不必要的副作用。

最后,当使用 ONBUILD 指令时,务必在文档中清晰地说明这些指令的用途和行为,以便其他开发者能够理解和正确使用它们。

综合示例

  • run镜像构建过程中执行命令
[root@docker-node1 docker]# vim dockerfile
FROM busybox
RUN touch /huazi   #在镜像构建过程中执行touch /huazi


[root@docker-node1 docker]# docker build -t busybox:v2 .


[root@docker-node1 docker]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED         SIZE
busybox                           v2        04838520814b   5 seconds ago   4.26MB
busybox                           latest    65ad0d468eb1   16 months ago   4.26MB


[root@docker-node1 docker]# docker history busybox:v2
IMAGE          CREATED          CREATED BY                               SIZE      COMMENT
04838520814b   25 seconds ago   RUN /bin/sh -c touch /huazi # buildkit   0B        buildkit.dockerfile.v0
<missing>      16 months ago    BusyBox 1.36.1 (glibc), Debian 12        4.26MB


[root@docker-node1 docker]# docker run -it --name test1 busybox:v2
/ # ls   #发现有huazi这个文件
bin    dev    etc    home   huazi  lib    lib64  proc   root   sys    tmp    usr    var
  • -f指定文件
[root@docker-node1 docker]# mv dockerfile huazi
[root@docker-node1 docker]# ls
huazi

[root@docker-node1 docker]# docker build -f /root/docker/huazi -t busybox:v3 .

[root@docker-node1 docker]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED         SIZE
busybox                           v2        04838520814b   8 minutes ago   4.26MB
busybox                           v3        04838520814b   8 minutes ago   4.26MB
busybox                           latest    65ad0d468eb1   16 months ago   4.26MB
#发现制作成功
  • label提示镜像说明
[root@docker-node1 docker]# vim dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com

[root@docker-node1 docker]# docker build -t busybox:v3 .


[root@docker-node1 docker]# docker history busybox:v3
IMAGE          CREATED          CREATED BY                               SIZE      COMMENT
7c0775bd7fa8   12 minutes ago   LABEL USER=huazi@163.com                 0B        buildkit.dockerfile.v0
<missing>      12 minutes ago   RUN /bin/sh -c touch /huazi # buildkit   0B        buildkit.dockerfile.v0
<missing>      16 months ago    BusyBox 1.36.1 (glibc), Debian 12        4.26MB
  • copy宿主机文件复制到镜像
[root@docker-node1 docker]# cp /etc/passwd .


[root@docker-node1 docker]# ls
dockerfile  passwd


[root@docker-node1 docker]# cat dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd


[root@docker-node1 docker]# docker build -t busybox:v3 .



[root@docker-node1 docker]# docker history busybox:v3
IMAGE          CREATED          CREATED BY                               SIZE      COMMENT
162b31c7cc6a   14 seconds ago   COPY passwd /passwd # buildkit           2.15kB    buildkit.dockerfile.v0
<missing>      14 seconds ago   LABEL USER=huazi@163.com                 0B        buildkit.dockerfile.v0
<missing>      16 minutes ago   RUN /bin/sh -c touch /huazi # buildkit   0B        buildkit.dockerfile.v0
<missing>      16 months ago    BusyBox 1.36.1 (glibc), Debian 12        4.26MB


[root@docker-node1 docker]# docker run -it --name test1 busybox:v3
/ # ls    #我们发现了passwd文件和huazi文件
bin     etc     huazi   lib64   proc    sys     usr
dev     home    lib     passwd  root    tmp     var
  • addcopy类似,又有解压功能
[root@docker-node1 docker]# tar -zcvf test.tar.gz dockerfile passwd
dockerfile
passwd
[root@docker-node1 docker]# ls
dockerfile  passwd  test.tar.gz


[root@docker-node1 docker]# vim dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd
ADD test.tar.gz /mnt



[root@docker-node1 docker]# docker build -t busybox:v4 .


[root@docker-node1 docker]# docker history busybox:v4
IMAGE          CREATED          CREATED BY                               SIZE      COMMENT
bc5e70c055d5   36 seconds ago   ADD test.tar.gz /mnt # buildkit          2.23kB    buildkit.dockerfile.v0
<missing>      9 minutes ago    COPY passwd /passwd # buildkit           2.15kB    buildkit.dockerfile.v0
<missing>      9 minutes ago    LABEL USER=huazi@163.com                 0B        buildkit.dockerfile.v0
<missing>      25 minutes ago   RUN /bin/sh -c touch /huazi # buildkit   0B        buildkit.dockerfile.v0
<missing>      16 months ago    BusyBox 1.36.1 (glibc), Debian 12        4.26MB


[root@docker-node1 docker]# docker run -it --name test1 busybox:v4
/ # ls
bin     etc     huazi   lib64   passwd  root    tmp     var
dev     home    lib     mnt     proc    sys     usr
/ # cd /mnt/
/mnt # ls    #发现已经解压
dockerfile  passwd
  • cmd容器启动运行时执行
[root@docker-node1 docker]# vim dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd
ADD test.tar.gz /mnt
CMD ["/bin/sh","-c","echo 'hello world'"]


[root@docker-node1 docker]# docker build -t busybox:v5 .


[root@docker-node1 docker]# docker history busybox:v5
IMAGE          CREATED          CREATED BY                                  SIZE      COMMENT
2fd18841a015   9 minutes ago    CMD ["/bin/sh" "-c" "echo 'hello world'"]   0B        buildkit.dockerfile.v0
<missing>      9 minutes ago    ADD test.tar.gz /mnt # buildkit             2.23kB    buildkit.dockerfile.v0
<missing>      17 minutes ago   COPY passwd /passwd # buildkit              2.15kB    buildkit.dockerfile.v0
<missing>      17 minutes ago   LABEL USER=huazi@163.com                    0B        buildkit.dockerfile.v0
<missing>      33 minutes ago   RUN /bin/sh -c touch /huazi # buildkit      0B        buildkit.dockerfile.v0
<missing>      16 months ago    BusyBox 1.36.1 (glibc), Debian 12           4.26MB


[root@docker-node1 docker]# docker run -it --name test1 busybox:v5
hello world
  • cmd只能有一个,多了会被覆盖cmd也可以被命令行的命令覆盖
  • cmd调用的是镜像内核的命令,不是宿主机的命令
[root@docker-node1 docker]# vim dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd
ADD test.tar.gz /mnt
CMD ["/bin/sh","-c","echo 'hello world'"]   #exec格式
CMD ip a    #shell格式


[root@docker-node1 docker]# docker build -t busybox:v6 .


#我们可以看到shell格式的cmd被自动转换为exec格式
[root@docker-node1 docker]# docker history busybox:v6
IMAGE          CREATED          CREATED BY                                  SIZE      COMMENT
9ba7e024d5f7   20 minutes ago   CMD ["/bin/sh" "-c" "ip a"]                 0B        buildkit.dockerfile.v0
<missing>      20 minutes ago   CMD ["/bin/sh" "-c" "echo 'hello world'"]   0B        buildkit.dockerfile.v0
<missing>      20 minutes ago   ADD test.tar.gz /mnt # buildkit             2.23kB    buildkit.dockerfile.v0
<missing>      28 minutes ago   COPY passwd /passwd # buildkit              2.15kB    buildkit.dockerfile.v0
<missing>      28 minutes ago   LABEL USER=huazi@163.com                    0B        buildkit.dockerfile.v0
<missing>      44 minutes ago   RUN /bin/sh -c touch /huazi # buildkit      0B        buildkit.dockerfile.v0
<missing>      16 months ago    BusyBox 1.36.1 (glibc), Debian 12           4.26MB


[root@docker-node1 docker]# docker run -it --name test1 busybox:v6
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
58: eth0@if59: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

#cmd被覆盖,cat /passwd是镜像内核的命令
[root@docker-node1 docker]# docker run -it --name test2 busybox:v6 cat /passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
  • env指定环境变量
[root@docker-node1 docker]# vim dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd
ADD test.tar.gz /mnt
CMD ["/bin/sh","-c","echo 'hello world'"]
ENV name=huazi    #设置变量
CMD echo $name     #引用变量



[root@docker-node1 docker]# docker build -t busybox:v1 .


[root@docker-node1 docker]# docker history busybox:v1
IMAGE          CREATED         CREATED BY                                  SIZE      COMMENT
b9479035470a   2 hours ago     CMD ["/bin/sh" "-c" "echo $name"]           0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ENV name=huazi                              0B        buildkit.dockerfile.v0
<missing>      2 hours ago     CMD ["/bin/sh" "-c" "echo 'hello world'"]   0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ADD test.tar.gz /mnt # buildkit             2.23kB    buildkit.dockerfile.v0
<missing>      2 hours ago     COPY passwd /passwd # buildkit              2.15kB    buildkit.dockerfile.v0
<missing>      2 hours ago     LABEL USER=huazi@163.com                    0B        buildkit.dockerfile.v0
<missing>      2 hours ago     RUN /bin/sh -c touch /huazi # buildkit      0B        buildkit.dockerfile.v0
<missing>      16 months ago   BusyBox 1.36.1 (glibc), Debian 12           4.26MB


[root@docker-node1 docker]# docker run -it --name test1 busybox:v1
huazi
  • cmd命令会被命令行的中的命令替代,如果不想被替代,需要使用entrypoint
[root@docker-node1 docker]# vim dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd
ADD test.tar.gz /mnt
CMD ["/bin/sh","-c","echo 'hello world'"]
ENV name=huazi
CMD echo $name
ENTRYPOINT ["/bin/sh","-c","echo 'hello world'"]



[root@docker-node1 docker]# docker build -t busybox:v2 .


[root@docker-node1 docker]# docker history busybox:v2
IMAGE          CREATED         CREATED BY                                       SIZE      COMMENT
5c9aed681a78   2 hours ago     ENTRYPOINT ["/bin/sh" "-c" "echo 'hello worl…   0B        buildkit.dockerfile.v0
<missing>      2 hours ago     CMD ["/bin/sh" "-c" "echo $name"]                0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ENV name=huazi                                   0B        buildkit.dockerfile.v0
<missing>      2 hours ago     CMD ["/bin/sh" "-c" "echo 'hello world'"]        0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ADD test.tar.gz /mnt # buildkit                  2.23kB    buildkit.dockerfile.v0
<missing>      2 hours ago     COPY passwd /passwd # buildkit                   2.15kB    buildkit.dockerfile.v0
<missing>      2 hours ago     LABEL USER=huazi@163.com                         0B        buildkit.dockerfile.v0
<missing>      2 hours ago     RUN /bin/sh -c touch /huazi # buildkit           0B        buildkit.dockerfile.v0
<missing>      16 months ago   BusyBox 1.36.1 (glibc), Debian 12                4.26MB


#发现没有被ip a显示的内容覆盖
[root@docker-node1 docker]# docker run -it --name test1 busybox:v2 ip a
hello world
  • 当我们在查看镜像层数时,发现没有端口暴露,这时就要使用expose指令
[root@docker-node1 docker]# vim dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd
ADD test.tar.gz /mnt
CMD ["/bin/sh","-c","echo 'hello world'"]
ENV name=huazi
CMD echo $name
ENTRYPOINT ["/bin/sh","-c","echo 'hello world'"]
EXPOSE 80/tcp 443/tcp    #暴露两个端口



[root@docker-node1 docker]# docker build -t busybox:v3 .


#我们发现了暴露出来的端口信息
[root@docker-node1 docker]# docker history busybox:v3
IMAGE          CREATED         CREATED BY                                       SIZE      COMMENT
a7803a89ebd6   2 hours ago     EXPOSE map[443/tcp:{} 80/tcp:{}]                 0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ENTRYPOINT ["/bin/sh" "-c" "echo 'hello worl…   0B        buildkit.dockerfile.v0
<missing>      2 hours ago     CMD ["/bin/sh" "-c" "echo $name"]                0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ENV name=huazi                                   0B        buildkit.dockerfile.v0
<missing>      2 hours ago     CMD ["/bin/sh" "-c" "echo 'hello world'"]        0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ADD test.tar.gz /mnt # buildkit                  2.23kB    buildkit.dockerfile.v0
<missing>      2 hours ago     COPY passwd /passwd # buildkit                   2.15kB    buildkit.dockerfile.v0
<missing>      2 hours ago     LABEL USER=huazi@163.com                         0B        buildkit.dockerfile.v0
<missing>      2 hours ago     RUN /bin/sh -c touch /huazi # buildkit           0B        buildkit.dockerfile.v0
<missing>      16 months ago   BusyBox 1.36.1 (glibc), Debian 12                4.26MB
  • 添加sleep进行休眠,相当于后台运行docker容器
[root@docker-node1 docker]# cat dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd
ADD test.tar.gz /mnt
CMD ["/bin/sh","-c","echo 'hello world'"]
ENV name=huazi
CMD echo $name
ENTRYPOINT ["/bin/sh","-c","echo 'hello world'"]
EXPOSE 80/tcp 443/tcp
ENTRYPOINT ["/bin/sh","-c","sleep 10"]   #维持后台运行10秒



[root@docker-node1 docker]# docker history busybox:v4
IMAGE          CREATED         CREATED BY                                       SIZE      COMMENT
2d55a269bbfc   2 hours ago     ENTRYPOINT ["/bin/sh" "-c" "sleep 10"]           0B        buildkit.dockerfile.v0
<missing>      2 hours ago     EXPOSE map[443/tcp:{} 80/tcp:{}]                 0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ENTRYPOINT ["/bin/sh" "-c" "echo 'hello worl…   0B        buildkit.dockerfile.v0
<missing>      2 hours ago     CMD ["/bin/sh" "-c" "echo $name"]                0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ENV name=huazi                                   0B        buildkit.dockerfile.v0
<missing>      2 hours ago     CMD ["/bin/sh" "-c" "echo 'hello world'"]        0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ADD test.tar.gz /mnt # buildkit                  2.23kB    buildkit.dockerfile.v0
<missing>      2 hours ago     COPY passwd /passwd # buildkit                   2.15kB    buildkit.dockerfile.v0
<missing>      2 hours ago     LABEL USER=huazi@163.com                         0B        buildkit.dockerfile.v0
<missing>      2 hours ago     RUN /bin/sh -c touch /huazi # buildkit           0B        buildkit.dockerfile.v0
<missing>      16 months ago   BusyBox 1.36.1 (glibc), Debian 12                4.26MB


[root@docker-node1 docker]# docker run -d --name test1 busybox:v4
1df271d73bc733897d1e84f03230039d27c1e6b6da744535c51016d8981d7617
[root@docker-node1 docker]# docker ps
CONTAINER ID   IMAGE        COMMAND                   CREATED         STATUS         PORTS             NAMES
1df271d73bc7   busybox:v4   "/bin/sh -c 'sleep 1…"   3 seconds ago   Up 2 seconds   80/tcp, 443/tcp   test1
#等待10秒后结束
[root@docker-node1 docker]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
  • workdir设置容器工作目录
[root@docker-node1 docker]# cat dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd
ADD test.tar.gz /mnt
EXPOSE 80/tcp 443/tcp
WORKDIR /mnt   #设置工作目录


[root@docker-node1 docker]# docker build -t busybox:v5 .


[root@docker-node1 docker]# docker history busybox:v5
IMAGE          CREATED         CREATED BY                               SIZE      COMMENT
daf3308a5024   9 seconds ago   WORKDIR /mnt                             0B        buildkit.dockerfile.v0
<missing>      2 hours ago     EXPOSE map[443/tcp:{} 80/tcp:{}]         0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ADD test.tar.gz /mnt # buildkit          2.23kB    buildkit.dockerfile.v0
<missing>      2 hours ago     COPY passwd /passwd # buildkit           2.15kB    buildkit.dockerfile.v0
<missing>      2 hours ago     LABEL USER=huazi@163.com                 0B        buildkit.dockerfile.v0
<missing>      3 hours ago     RUN /bin/sh -c touch /huazi # buildkit   0B        buildkit.dockerfile.v0
<missing>      16 months ago   BusyBox 1.36.1 (glibc), Debian 12        4.26MB


#我们可以发现,刚进入docker容器中,就在/mnt目录下
[root@docker-node1 docker]# docker run -it --name test1 busybox:v5
/mnt #
  • volume声明数据卷,并没有创建数据卷不会实现数据的持久化
  • 如果没有目录,会自动创建
[root@docker-node1 docker]# vim dockerfile
FROM busybox
RUN touch /huazi
LABEL USER=huazi@163.com
COPY passwd /passwd
ADD test.tar.gz /mnt
EXPOSE 80/tcp 443/tcp
WORKDIR /mnt
VOLUME /lee    #声明的挂载目录


[root@docker-node1 docker]# docker build -t busybox:v6 .


[root@docker-node1 docker]# docker history busybox:v6
IMAGE          CREATED         CREATED BY                               SIZE      COMMENT
4e2f6155ae35   8 minutes ago   VOLUME [/lee]                            0B        buildkit.dockerfile.v0
<missing>      8 minutes ago   WORKDIR /mnt                             0B        buildkit.dockerfile.v0
<missing>      2 hours ago     EXPOSE map[443/tcp:{} 80/tcp:{}]         0B        buildkit.dockerfile.v0
<missing>      2 hours ago     ADD test.tar.gz /mnt # buildkit          2.23kB    buildkit.dockerfile.v0
<missing>      3 hours ago     COPY passwd /passwd # buildkit           2.15kB    buildkit.dockerfile.v0
<missing>      3 hours ago     LABEL USER=huazi@163.com                 0B        buildkit.dockerfile.v0
<missing>      3 hours ago     RUN /bin/sh -c touch /huazi # buildkit   0B        buildkit.dockerfile.v0
<missing>      16 months ago   BusyBox 1.36.1 (glibc), Debian 12        4.26MB


[root@docker-node1 docker]# docker run -it --name test1 busybox:v6
/mnt # cd /
/ # ls
bin     etc     huazi   lib     mnt     proc    sys     usr
dev     home    lee     lib64   passwd  root    tmp     var
/ # [root@docker-node1 docker]# docker ps
CONTAINER ID   IMAGE        COMMAND   CREATED              STATUS              PORTS             NAMES
271b5d49ef95   busybox:v6   "sh"      About a minute ago   Up About a minute   80/tcp, 443/tcp   test1

#查看test1容器的详细信息
#Source是宿主机上的位置
#Destination是容器中的位置
#两个文件位置相互共享
[root@docker-node1 docker]# docker inspect test1
        "Mounts": [
            {
                "Type": "volume",
                "Name": "843dd1ca476b666f046bf627d85a5ece5f64e0a8167df44c9f5fb6fb15e40aa5",
                "Source": "/var/lib/docker/volumes/843dd1ca476b666f046bf627d85a5ece5f64e0a8167df44c9f5fb6fb15e40aa5/_data",
                "Destination": "/lee",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],


[root@docker-node1 docker]# cd /var/lib/docker/volumes/843dd1ca476b666f046bf627d85a5ece5f64e0a8167df44c9f5fb6fb15e40aa5/_data
[root@docker-node1 _data]# ls
[root@docker-node1 _data]# touch file111  #创建file111文件
[root@docker-node1 _data]# docker attach test1
/ # ls
bin     etc     huazi   lib     mnt     proc    sys     usr
dev     home    lee     lib64   passwd  root    tmp     var
/ # cd lee/
/lee # ls   #我们可以发现file111文件
file111

#当删掉容器后,宿主上共享的目录也会被删掉
[root@docker-node1 ~]# docker rm -f test1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

^~^前行者~~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值