引言:为何持久化存储是Docker应用的生命线?
在容器化应用中,数据持久化是保障业务连续性的核心环节。Docker容器默认的临时存储特性虽适合无状态应用,但对于数据库、配置中心、日志服务等有状态服务,必须通过持久化存储确保数据在容器重启、迁移或崩溃后不丢失。结合生产环境案例与代码示例,助您构建安全可靠的数据管理体系。
Docker 数据管理

Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即"写时复制(COW copy on write)"机制。
如果将正在运行中的容器修改生成了新的数据,那么新产生的数据将会被复制到读写层,进行持久化保存,这个读写层也就是容器的工作目录,也为写时复制(COW) 机制。COW机制节约空间,但会导致性低下,虽然关闭重启容器,数据不受影响,但会随着容器的删除,其对应的可写层也会随之而删除,即数据也会丢失。如果容器需要持久保存数据,并不影响性能可以用数据卷技术实现。
如下图是将对根的数据写入到了容器的可写层,但是把/data 中的数据写入到了一个另外的volume 中用于数据持久化。

容器的数据管理介绍
Docker镜像是分层设计的,镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层中。
Docker容器的分层
容器的数据分层目录
- LowerDir:image 镜像层,即镜像本身,只读
- UpperDir:容器的上层,可读写,容器变化的数据存放在此处
- MergedDir:容器的文件系统,使用Union FS(联合文件系统)将lowerdir 和upperdir 合并完成后给容器使用,最终呈现给用户的统一视图
- WorkDir:容器在宿主机的工作目录,挂载后内容会被清空,且在使用过程中其内容用户不可见
查看指定容器数据分层
bash
[root@ubuntu2404 ~]#docker inspect nginx
"GraphDriver": {
"Data": {
"ID": "660581654f6ffea0f212d0a21a36cbd3922671a774ca70c0a7297db0c0a9b52c",
"LowerDir": "/var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce-init/diff:/var/lib/docker/overlay2/607e85ed7f725d1b01ed6009ce54f1e65e61f08998ec9242476709a770e9aa96/diff:/var/lib/docker/overlay2/e222bfa7d82bb3a7e45c75d01b3356aadf699c9355797e1daf8294fad83bdea3/diff:/var/lib/docker/overlay2/a691a846c3d41fcdcdb4a60f696f47c9633a7d35ea48023e4051e664e3d0870c/diff:/var/lib/docker/overlay2/1ae4dbe4c4ab9425102b23595002d317d2b272e8b1772d157e58d9d2b8c03a8e/diff:/var/lib/docker/overlay2/15df0f71eb95878219824a12d8d71983832263fda8e168178d9f4d1e236fed5f/diff:/var/lib/docker/overlay2/2a69175cf068a1af9d6036137c402558ed85c632198280f473e992ae3c212c49/diff:/var/lib/docker/overlay2/2b7f5cb956e775221f563178bcde0ca160368f476699c51745265d0a6995d1ef/diff",
"MergedDir": "/var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce/merged",
"UpperDir": "/var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce/diff",
"WorkDir": "/var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce/work"
},
"Name": "overlay2"
[root@ubuntu2404 ~]#ll -i /var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce
total 28
5253677 drwx--x--- 5 root root 4096 Aug 7 21:27 ./
5246322 drwx--x--- 13 root root 4096 Aug 7 21:27 ../
5253690 drwxr-xr-x 5 root root 4096 Aug 7 21:27 diff/
5253692 -rw-r--r-- 1 root root 26 Aug 7 21:27 link
5253695 -rw-r--r-- 1 root root 231 Aug 7 21:27 lower
5253690 drwxr-xr-x 1 root root 4096 Aug 7 21:27 merged/
5253693 drwx------ 3 root root 4096 Aug 7 21:27 work/
[root@ubuntu2404 ~]#tree /var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce|head -n 50
/var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce
├── diff
│ ├── etc
│ │ └── nginx
│ │ └── conf.d
│ │ └── default.conf
│ ├── run
│ │ └── nginx.pid
│ └── var
│ └── cache
│ └── nginx
│ ├── client_temp
│ ├── fastcgi_temp
│ ├── proxy_temp
│ ├── scgi_temp
│ └── uwsgi_temp
├── link
├── lower
├── merged
│ ├── bin -> usr/bin
│ ├── boot
│ ├── dev
│ │ ├── console
│ │ ├── pts
│ │ └── shm
│ ├── docker-entrypoint.d
│ │ ├── 10-listen-on-ipv6-by-default.sh
│ │ ├── 15-local-resolvers.envsh
│ │ ├── 20-envsubst-on-templates.sh
│ │ └── 30-tune-worker-processes.sh
│ ├── docker-entrypoint.sh
│ ├── etc
│ │ ├── adduser.conf
│ │ ├── alternatives
│ │ │ ├── awk -> /usr/bin/mawk
│ │ │ ├── awk.1.gz -> /usr/share/man/man1/mawk.1.gz
......
[root@ubuntu2404 ~]#docker run -it alpine:3.3 sh
/ # dd if=/dev/zero of=/root/test.img bs=1M count=10
10+0 records in
10+0 records out
/ #
[root@ubuntu2404 ~]#find /var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/ -name test.img -ls
5253773 10240 -rw-r--r-- 1 root root 10485760 Aug 7 21:37 /var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/merged/root/test.img
5253773 10240 -rw-r--r-- 1 root root 10485760 Aug 7 21:37 /var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/diff/root/test.img
[root@ubuntu2404 ~]#mount
overlay on /var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/USTJFL335JN3Q4BAN53KOGJL6Q:/var/lib/docker/overlay2/l/6UF7GTJ5W5UEWP3E7KQ5ELA4EN:/var/lib/docker/overlay2/l/Z43FX27QMTNF5OXX3J4AG2OKAO:/var/lib/docker/overlay2/l/5TPFU53RY5EA6FVXJPEHXESDJV:/var/lib/docker/overlay2/l/ZPIGD7KO2TXQ3BNK4PISSR4YKB:/var/lib/docker/overlay2/l/XFMKVWYYU3PEE5J7WT4OL54LZQ:/var/lib/docker/overlay2/l/WRAXF4ASIXY4TVGP2ZRSFI3SE2:/var/lib/docker/overlay2/l/N2VYVGZG546MSVAKB4DNHM2CNY,upperdir=/var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce/diff,workdir=/var/lib/docker/overlay2/f48612e5f634574856956b172dba0081a1260ada85145f20d41107bb506a9fce/work,nouserxattr)
nsfs on /run/docker/netns/4bdd1076075c type nsfs (rw)
overlay on /var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/5J33RFRVKFDA43PRA2HZOHRU6K:/var/lib/docker/overlay2/l/D3HUNLXCPOTQYQXGTXL6HDSFTO,upperdir=/var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/diff,workdir=/var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/work,nouserxattr)
nsfs on /run/docker/netns/88a706c41efc type nsfs (rw)
[root@ubuntu2404 ~]#tree /var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/diff/root/
/var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/diff/root/
└── test.img
1 directory, 1 file
[root@ubuntu2404 ~]#ls /var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/merged/
bin dev etc home lib linuxrc media mnt proc root run sbin sys tmp usr var
[root@ubuntu2404 ~]#docker run -it alpine:3.3 sh
/ # echo welcome to docker >>/etc/issue
/ # cat /etc/issue
Welcome to Alpine Linux 3.3
Kernel \r on an \m (\l)
welcome to docker
/ #
[root@ubuntu2404 ~]#tree /var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/diff/
/var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14/diff/
├── etc
│ └── issue
└── root
└── test.img
3 directories, 2 files
#删除容器后,所有容器数据目录都随之而删除
[root@ubuntu2404 ~]#docker rm nervous_brahmagupta
nervous_brahmagupta
[root@ubuntu2404 ~]#ls /var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14
ls: cannot access '/var/lib/docker/overlay2/c3085a747c41b3254c0dd7f18d55af94997e995bdeb3e2f1287b2593d787bf14': No such file or directory
哪些数据需要持久化
有状态的协议
matlab
有状态协议就是就通信双方要记住双方,并且共享一些信息。而无状态协议的通信每次都是独立的,与上一次
的通信没什么关系。
"状态"可以理解为"记忆",有状态对应有记忆,无状态对应无记忆

左侧是无状态的http请求服务,右侧为有状态。
下层为不需要存储的服务,上层为需要存储的部分服务。
容器数据持久保存方式
如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录 Docker的数据类型分为两种:
数据卷(Data Volume):直接将宿主机目录挂载至容器的指定的目录 ,推荐使用此种方式,此方式较常用。
数据卷容器(Data Volume Container):间接使用宿主机空间,数据卷容器是将宿主机的目录挂载至一个专门的数据卷容器,然后让其他容器通过数据卷容器读写宿主机的数据,此方式不常用。

数据卷(data volume)
数据卷特点和使用
数据卷实际上就是宿主机上的目录或者是文件,可以被直接mount到容器当中使用。实际生成环境中,需要针对不同类型的服务、不同类型的数据存储要求做相应的规划,最终保证服务的可扩展性、稳定性以及数据的安全性。
数据卷使用场景
数据库
日志输出
静态web页面
应用配置文件
多容器间目录或文件共享
数据卷的特点
数据卷是目录或者文件,并且可以在多个容器之间共同使用,实现容器之间共享和重用,对数据卷更改数据在所有容器里面会立即更新。
数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。 在容器里面的写入数据不会影响到镜像本身,即数据卷的变化不会影响镜像的更新。
依赖于宿主机目录,宿主机出问题,上面容器会受影响,当宿主机较多时,不方便统一管理。
匿名和命名数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,会拷贝到新初始化的数据卷中。
数据卷分类
启动容器时,可以指定使用数据卷实现容器数据的持久化,数据卷有三种。
指定宿主机目录或文件:指定宿主机的具体路径和容器路径的挂载关系,此方式不会创建数据卷。
匿名卷:不指定数据名称,只指定容器内目录路径充当挂载点,docker自动指定宿主机的路径进行挂载,此方式会创建匿名数据卷,Dockerfile中VOLUME指定的卷即为此种。
命名卷:指定数据卷的名称和容器路径的挂载关系,此方式会创建命名数据卷。
数据卷使用方法
docker run 命令的以下格式可以实现数据卷
bash
-v, --volume list Bind mount a volume
<options>
ro 从容器内对此数据卷是只读,不写此项默认为可读可写
rw 从容器内对此数据卷可读可写,此为默认值
host-src 宿主机目录如果不存在,会自动创建
方式1
bash
#指定宿主机目录或文件格式:
-v <宿主机绝对路径的目录或文件>:<容器目录或文件>[:ro] #将宿主机目录挂载容器目录,两个目录
都可自动创建
#注意:如果初始容器中有旧数据,将被宿主机目录覆盖
方式2
bash
#匿名卷,只指定容器内路径,没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷ID>/_data目录,并挂载至容器指定路径
#注意:如果初始容器中有旧数据,将被复制到宿主机数据卷目录-v <容器内路径>
#示例:
docker run --name nginx -v /etc/nginx nginx
方式3
bash
#命名卷将固定的存放在/var/lib/docker/volumes/<卷名>/_data
#注意:如果初始容器中有旧数据,将被复制到宿主机数据卷目录
-v <卷名>:<容器目录路径>
#可以通过以下命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷
docker volume create <卷名>
#示例:
docker volume create vol1 #也可以事先不创建
docker run -d -p 80:80 --name nginx01 -v vol1:/usr/share/nginx/html nginx
docker rm 的 -v 选项可以删除容器时,同时删除相关联的匿名卷
bash
-v, --volumes Remove the volumes associated with the container
管理数据卷命令
bash
Usage: docker volume COMMAND
Manage volumes
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove unused local volumes
rm Remove one or more volumes
Run 'docker volume COMMAND --help' for more information on a command.
查看数据卷的挂载关系
bash
docker inspect --format="{{.Mounts}}" <容器ID>
删除所有数据卷
bash
[root@ubuntu2404 ~]# docker volume rm `docker volume ls -q`
创建命令卷并删除
bash
[root@ubuntu2404 ~]#docker volume create mysql
[root@ubuntu2404 ~]#docker volume ls
DRIVER VOLUME NAME
local 56f3dc469c3efac03cca72571968d38319cf5e8442147439dfa51cf13d06213c
local 69934bfa590a55f64566894e5839e5e1c3e20a7d13309ea4ce62be5a22eb11ab
local a1a11dcd7957d57c5811b0831d5d8738940076f3fcb206b3ce64dabc466662ee
local f402cae908ad3478caff992e80f15b2ace77d675a355d2694fd2379c54a62f5a
local mysql
[root@ubuntu2404 ~]#tree /var/lib/docker/volumes/
/var/lib/docker/volumes/
├── 56f3dc469c3efac03cca72571968d38319cf5e8442147439dfa51cf13d06213c
│ └── _data
│ └── f1
├── 69934bfa590a55f64566894e5839e5e1c3e20a7d13309ea4ce62be5a22eb11ab
│ └── _data
├── a1a11dcd7957d57c5811b0831d5d8738940076f3fcb206b3ce64dabc466662ee
│ └── _data
├── backingFsBlockDev
├── f402cae908ad3478caff992e80f15b2ace77d675a355d2694fd2379c54a62f5a
│ └── _data
│ ├── auto.cnf
│ ├── binlog.000001
│ ├── binlog.000002
│ ├── binlog.index
│ ├── ca-key.pem
│ ├── ca.pem
│ ├── client-cert.pem
│ ├── client-key.pem
│ ├── #ib_16384_0.dblwr
│ ├── #ib_16384_1.dblwr
[root@ubuntu2404 ~]#docker volume rm mysql
mysql
[root@ubuntu2404 ~]#docker volume ls
DRIVER VOLUME NAME
local 56f3dc469c3efac03cca72571968d38319cf5e8442147439dfa51cf13d06213c
local 69934bfa590a55f64566894e5839e5e1c3e20a7d13309ea4ce62be5a22eb11ab
local a1a11dcd7957d57c5811b0831d5d8738940076f3fcb206b3ce64dabc466662ee
local f402cae908ad3478caff992e80f15b2ace77d675a355d2694fd2379c54a62f5a
[root@ubuntu2404 ~]#docker volume rm `docker volume ls -q`
删除不再使用的数据卷
bash
[root@ubuntu2404 1.26]#docker volume ls
DRIVER VOLUME NAME
local 749a8bb98586cb3fa09660135f32e08c5d8403d34e8fc845722533ac2c1ebbe7
[root@ubuntu2404 1.26]#docker volume prune -f
Deleted Volumes:
749a8bb98586cb3fa09660135f32e08c5d8403d34e8fc845722533ac2c1ebbe7
Total reclaimed space: 0B
[root@ubuntu2404 1.26]#docker volume ls
DRIVER VOLUME NAME
关于匿名数据卷和命名数据卷
bash
命名卷就是有名字的卷,使用 docker volume create <卷名> 形式创建并命名的卷;而匿名卷就是没名
字的卷,一般是 docker run -v /data 这种不指定卷名的时候所产生,或者 Dockerfile 里面的定义
直接使用的。
有名字的卷,在用过一次后,以后挂载容器的时候还可以使用,因为有名字可以指定。所以一般需要保存的数
据使用命名卷保存。
而匿名卷则是随着容器建立而建立,随着容器消亡而淹没于卷列表中(对于 docker run 匿名卷不会被自动
删除)。 因此匿名卷只存放无关紧要的临时数据,随着容器消亡,这些数据将失去存在的意义。
Dockerfile中指定VOLUME为匿名数据卷,其目的只是为了将某个路径确定为卷。
按照最佳实践的要求,不应该在容器存储层内进行数据写入操作,所有写入应该使用卷。如果定制镜像的时
候,就可以确定某些目录会发生频繁大量的读写操作,那么为了避免在运行时由于用户疏忽而忘记指定卷,导
致容器发生存储层写入的问题,就可以在 Dockerfile 中使用 VOLUME 来指定某些目录为匿名卷。这样即
使用户忘记了指定卷,也不会产生不良的后果。
这个设置可以在运行时覆盖。通过 docker run 的 -v 参数或者 docker-compose.yml 的 volumes
指定。使用命名卷的好处是可以复用,其它容器可以通过这个命名数据卷的名字来指定挂载,共享其内容(不
过要注意并发访问的竞争问题)。
比如,Dockerfile 中说 VOLUME /data,那么如果直接 docker run,其 /data 就会被挂载为匿名
卷,向 /data 写入的操作不会写入到容器存储层,而是写入到了匿名卷中。但是如果运行时 docker run -v mydata:/data,这就覆盖了 /data 的挂载设置,要求将 /data 挂载到名为 mydata 的命名卷中。
所以说 Dockerfile 中的 VOLUME 实际上是一层保险,确保镜像运行可以更好的遵循最佳实践,不向容器
存储层内进行写入操作。
数据卷默认可能会保存于 /var/lib/docker/volumes,不过一般不需要、也不应该访问这个位置
实战案例:目录数据卷
在宿主机创建容器所使用的目录
bash
[root@ubuntu2404 ~]#mkdir /data/testdir
[root@ubuntu2404 ~]#echo "web ubuntu-nginx">/data/testdir/index.html
查看容器相关目录路径
bash
[root@ubuntu2404 ~]#docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx-ubuntu v1.1 99951e989855 4 hours ago 525MB
nginx-alpin v1.2 153846168892 7 hours ago 258MB
[root@ubuntu2404 ~]#docker run -it --rm nginx-alpin:v1.2 sh
/usr/local/src/nginx-1.26.3 # cat /data/nginx/html/index.html
hello nginx-alpine
/usr/local/src/nginx-1.26.3 # exit
引用宿主机的数据卷启动容器
引用同一个数据卷目录,开启多个容器,实现多个容器共享数据
bash
[root@ubuntu2404 ~]#docker run -d -v /data/testdir:/data/nginx/html/ -p 8080:80 nginx-alpin:v1.2
c6d2b90ea32488496ec76309b61f46311fa934cf8df7e7416a620d316ac9788e
[root@ubuntu2404 ~]#docker run -d -v /data/testdir:/data/nginx/html/ -p 8181:80 nginx-alpin:v1.2
47b0db70cf672391e5915662fb83f17d359be5c4bf13649244e933f2a931751b
[root@ubuntu2404 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
47b0db70cf67 nginx-alpin:v1.2 "nginx" 4 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:8181->80/tcp, [::]:8181->80/tcp stoic_tu
c6d2b90ea324 nginx-alpin:v1.2 "nginx" About an hour ago Up About an hour 443/tcp, 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp optimistic_grothendieck
[root@ubuntu2404 ~]#curl 127.0.0.1:8181
web ubuntu-nginx
[root@ubuntu2404 ~]#curl 127.0.0.1:8080
web ubuntu-nginx
进入到容器内测试写入数据
进入其中一个容器写入数据,可以其它容器的数据也变化
bash
[root@ubuntu2404 ~]#docker exec -it 47b0db70cf67 sh
/usr/local/src/nginx-1.26.3 # df
Filesystem 1K-blocks Used Available Use% Mounted on
overlay 101590008 12667924 83715456 13% /
tmpfs 65536 0 65536 0% /dev
shm 65536 0 65536 0% /dev/shm
/dev/mapper/ubuntu--vg-ubuntu--lv
101590008 12667924 83715456 13% /etc/resolv.conf
/dev/mapper/ubuntu--vg-ubuntu--lv
101590008 12667924 83715456 13% /etc/hostname
/dev/mapper/ubuntu--vg-ubuntu--lv
101590008 12667924 83715456 13% /etc/hosts
/dev/mapper/ubuntu--vg-ubuntu--lv
101590008 12667924 83715456 13% /data/nginx/html
tmpfs 1980504 0 1980504 0% /proc/asound
tmpfs 1980504 0 1980504 0% /proc/acpi
tmpfs 65536 0 65536 0% /proc/kcore
tmpfs 65536 0 65536 0% /proc/keys
tmpfs 65536 0 65536 0% /proc/latency_stats
tmpfs 65536 0 65536 0% /proc/timer_list
tmpfs 1980504 0 1980504 0% /proc/scsi
tmpfs 1980504 0 1980504 0% /sys/firmware
/usr/local/src/nginx-1.26.3 # cat /data/nginx/html/index.html
web02 nginx-ubuntu
/usr/local/src/nginx-1.26.3 # echo web03 ubuntu-nginx>/data/nginx/html/index.html
/usr/local/src/nginx-1.26.3 # exit
#进入另一个容器看到数据变化
[root@ubuntu2404 ~]#docker exec -it c6d2b90ea324 sh
/usr/local/src/nginx-1.26.3 # cat /data/nginx/html/index.html
web03 ubuntu-nginx
/usr/local/src/nginx-1.26.3 # exit
[root@ubuntu2404 ~]#curl 127.0.0.1:8080
web03 ubuntu-nginx
[root@ubuntu2404 ~]#curl 127.0.0.1:8181
web03 ubuntu-nginx
在宿主机修改数据
bash
[root@ubuntu2404 ~]#echo web05 nginx-ubuntu-2404 >/data/testdir/index.html
[root@ubuntu2404 ~]#cat /data/testdir/index.html
web05 nginx-ubuntu-2404
[root@ubuntu2404 ~]#curl 127.0.0.1:8181
web05 nginx-ubuntu-2404
[root@ubuntu2404 ~]#curl 127.0.0.1:8080
web05 nginx-ubuntu-2404
[root@ubuntu2404 ~]#docker exec -it optimistic_grothendieck sh
/usr/local/src/nginx-1.26.3 # cat /data/nginx/html/index.html
web05 nginx-ubuntu-2404
/usr/local/src/nginx-1.26.3 # exit
[root@ubuntu2404 ~]#docker exec -it stoic_tu sh
/usr/local/src/nginx-1.26.3 # cat /data/nginx/html/index.html
web05 nginx-ubuntu-2404
/usr/local/src/nginx-1.26.3 # exit
只读方法挂载数据卷
默认数据卷为可读可写,加ro选项,可以实现只读挂载,对于不希望容器修改的数据,比如:配置文件、脚本等,可以用此方式挂载。
bash
[root@ubuntu2404 ~]#docker run -d -p 8080:80 -v /data/testdir:/data/nginx/html/:ro --name nginx nginx-alpin:v1.2
f5a07691b0459cd73d686d9fec0bff4754e91f6c880a126a9bf8a00013b91e1d
[root@ubuntu2404 ~]#docker exec -it nginx sh
/usr/local/src/nginx-1.26.3 # cat /data/nginx/html/index.html
web05 nginx-ubuntu-2404
/usr/local/src/nginx-1.26.3 # echo hello>/data/nginx/html/index.html
sh: can't create /data/nginx/html/index.html: Read-only file system
/usr/local/src/nginx-1.26.3 # exit
[root@ubuntu2404 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5a07691b045 nginx-alpin:v1.2 "nginx" About a minute ago Up About a minute 443/tcp, 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp nginx
[root@ubuntu2404 ~]#curl 127.0.0.1:8080
web05 nginx-ubuntu-2404
删除容器
删除容器后,宿主机的数据卷还存在,可继续给新的容器使用
bash
root@ubuntu2404 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5a07691b045 nginx-alpin:v1.2 "nginx" 45 minutes ago Up 45 minutes 443/tcp, 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp nginx
[root@ubuntu2404 ~]#docker rm -f nginx
nginx
[root@ubuntu2404 ~]#cat /data/testdir/index.html
web05 nginx-ubuntu-2404
[root@ubuntu2404 ~]#docker run -d -p 80:80 -v /data/testdir:/data/nginx/html/ nginx-alpin:v1.2
00d907069643d1015df30e597d56c04a85d24502d1e06f7e66bd5a601468d36e
[root@ubuntu2404 ~]#curl 127.0.0.1:80
web05 nginx-ubuntu-2404
通过遵循上述最佳实践,您可构建高可用、易维护的Docker数据管理体系。数据持久化不仅是技术实现,更是业务连续性的保障。希望本文能为您提供实战指导,助您在容器化道路上走得更稳、更远。