华子目录
- docker镜像结构
- 镜像运行的基本原理
- 镜像获得方式
- 制作镜像
- 基于`dockerfile`制作镜像
- Dockerfile指令-`from`指令
- Dockerfile指令-`maintainer`指令
- Dockerfile指令-`copy`指令
- Dockerfile指令-`add`指令
- Dockerfile指令-`workdir`指令
- Dockerfile指令-`volume`指令
- Dockerfile指令-`expose`指令
- Dockerfile指令-`env`指令
- Dockerfile指令-`run`指令
- Dockerfile指令-`cmd`指令
- Dockerfile指令-`entrypoint`指令
- Dockerfile指令-HEALTHCHECK指令
- Dockerfile指令-ONBUILD指令
- 综合示例
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镜像
是一个特殊的文件系统
,除了提供容器运行时所需的程序,库,资源,配置等
文件外,还包含了一些为运行时
准备的一些==配置参数
(如匿名卷,环境变量,用户
等==)。镜像不包含任何动态数据
,其内容在构建之后
也不会被改变
。镜像的定制
实际上就是定制每一层所添加的配置,文件
。如果我们可以把每一层修改,安装,构建,操作的命令
都写入一个脚本,用这个脚本来构建,定制镜像
。那么之前提及的无法重复
的问题,镜像构建透明性
的问题,体积
的问题就都会解决。这个脚本就是dockerfile
。dockerfile
是一个文本文件
,其内包含了一条条的指令
(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
用于指定镜像的名称和标签
。 -
PATH
是Dockerfile 所在的目录路径
。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命令
这样的客户端工具
,则是通过这组API
与Docker引擎
交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种docker功能
,但实际上,一切都是使用的远程调用
形式在服务端
(Docker引擎
)完成。也因为这种C/S
设计,让我们操作远程服务器的Docker引擎
变得轻而易举。 - 经常会需要将一些本地文件复制进镜像,比如通过
COPY
指令,当我们进行镜像构建的时候,并非所有定制都会通过RUN 指令
完成,会ADD 指令
等,而docker build
命令构建镜像、其实并非在本地构建,而是在服务端,也就是Docker引擎
中构建的。那么在这种客户端/服务端
的架构中,如何才能让服务端获得本地文件
呢? - 这就引入了
上下文
的概念。 当构建的时候,用户会指定构建镜像上下文的路径
,docker build
命令得知这个路径
后, 会将路径下
的所有内容打包
,然后上传给Docker引擎
。这样Docker 引擎
收到这个上下文包
后,展开就会获得构建镜像
所需的一切文件
。
上下文路径
-
在
Docker
构建过程中,上下文路径
是一个关键概念
。当用户执行docker build
命令时,需要指定一个构建镜像上下文
的路径
。Docker
会将这个路径下的所有内容
打包,然后上传给Docker引擎
。这个路径通常包含Dockerfile
,以及其他构建镜像所需的文件和目录
。 -
默认情况下,如果不额外指定
Dockerfile
,Docker
会在上下文目录
下查找名为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
中非注释
行的第一个指令
,即一个Dockerfile
从FROM
语句开始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
指令的示例:
复制单个文件
到镜像的根目录
:
COPY myfile.txt /
- 复制
多个文件
到镜像的某个目录
:
COPY file1.txt file2.txt /mydir/
- 使用
通配符
复制多个文件
到镜像中
:
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 3月 29 16:47 dockerfile
-rw-r--r-- 1 root root 12 3月 29 16:36 index.html
drwxr-xr-x 2 root root 70 3月 29 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>
指定了在镜像
中的目标路径
。
功能特性:
自动解压
:如果源文件(本地系统上,不是URL上的)是tar类型的压缩文件,ADD指令会自动解压它到目标路径。网络资源支持
:add指令
可以从URL
获取文件并添加到镜像
中,类似于wget
命令。然而,为了保持镜像尽可能小,官方推荐在获取网络资源后使用RUN命令结合curl或wget来删除不再需要的文件,以避免在镜像中额外添加不必要的层。路径创建
:如果目标路径
不存在,add指令
会自动创建它
。
与copy指令
的区别:
COPY指令
与ADD指令
在功能和使用方式上类似,但COPY指令不支持自动解压和从网络获取文件
。因此,在不需要这些额外功能的情况下,使用COPY
指令更为简单和直接。
示例:
- 将
本地文件
添加到镜像
:
ADD myfile.txt /mydir/
- 将
目录及其内容
添加到镜像
:
ADD mydir/ /mydir/
- 从
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
,然后在这个目录下执行RUN
和COPY
指令。最后,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环境
,而是直接运行指定的可执行文件及其参数
。
复制文件或目录
:
虽然通常使用COPY
指令来复制文件或目录到镜像中,但RUN
指令也可以结合shell命令
来实现类似的操作,例如:
RUN mkdir /mydir && cp /source/file.txt /mydir/
执行脚本
:
RUN chmod +x /path/to/script.sh && /path/to/script.sh
- 使用
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指令
有三种格式:
-
exec格式:
CMD ["executable","param1","param2"]
。这是首选的格式
,因为它避免了shell字符串
解析的问题,并且它是以exec方式
运行的,这意味着它不会启动一个额外的shell
。 -
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.py
的Python脚本
。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:结合entrypoint
和cmd
当entrypoint
和cmd
同时存在时,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
指令中定义的arg1
和arg2
。
CMD
指令在Dockerfile中提供了很大的灵活性,允许你定义容器启动时的默认行为。但是,需要注意的是,CMD
指令可以被docker run
命令中的参数所覆盖。如果需要更稳定的容器启动行为,可以考虑使用ENTRYPOINT
。
Dockerfile指令-entrypoint
指令
Dockerfile
中的entrypoint指令
用于配置容器启动时
执行的命令及其参数。与CMD指令
类似entrypoint
也是定义容器启动
行为的指令,但两者在功能和用法上有一些区别。
entrypoint指令
有两种格式:
exec格式
:ENTRYPOINT ["executable", "param1", "param2"]
。这是推荐的方式
,因为它不会通过shell来执行,而是直接调用exec函数
来启动程序,这样可以避免shell解析带来的问题,并减少容器启动时的开销。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"]
在这个例子中,如果你运行容器时没有提供任何额外的参数,arg1
和arg2
会被传递给/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指令有两种形式:
- HEALTHCHECK [options] CMD :这种形式包含一个或多个选项,如interval(间隔)、timeout(超时)等。从容器运行起来开始计时,每隔interval秒进行一次健康检查。如果命令执行超过timeout秒,则视为超时并标记为错误状态。
例如:
HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/ || exit 1
在这个例子中,容器每5秒执行一次健康检查,如果curl命令在3秒内没有响应,则认为容器不健康。
- 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 指令,如 RUN
、COPY
、ADD
等。当一个新的镜像基于当前镜像构建时,这些指令会被插入到子镜像的 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
指令基于这个镜像构建时,RUN
和 COPY
指令会在子镜像的构建过程中自动执行。
需要注意的是,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
指令中定义的 RUN
和 COPY
会自动执行。这意味着,尽管这些指令没有直接写在新镜像的 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
add
和copy
类似,又有解压功能
[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