Docker 存储卷:本地文件与容器内部文件建立绑定关系

Docker Volume(存储卷)

什么是存储卷?

存储卷将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。

在宿主机上的这个与容器形成绑定关系的目录被称作存储卷 。卷的本质是文件或者目录,它可以绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上。

宿主机的/data/web目录与容器中的/container/data/web目录绑定关系,然后容器中的进程向这个目录中写数据时,直接写在宿主机的/data/web目录下,这样容器和宿主机的文件系统就建立了"数据共享"关系,使得可以在宿主机和容器内共享数据库内容 ,让容器直接访问宿主机中的内容,也可以宿主机向容器写入内容,容器和宿主机的数据读写是同步的

为什么需要存储卷?

  1. 数据丢失问题
    Docker 容器的文件系统是分层 UnionFS ,所有运行时写入的数据都存在最上层的读写层 ,而读写层的生命周期与容器完全一致 ,这就会导致:
    • 容器删除 → 读写层被彻底删除 → 所有数据永久丢失
    • 容器重启 → 读写层保留,但重建容器(如升级镜像、迁移节点)数据依然丢失

没有存储卷的话,任何需要持久化数据的业务都无法在容器中运行:

  • 数据库(MySQL/PostgreSQL/Redis):删容器 = 删库
  • 日志服务:容器重启日志全没
  • 文件存储服务:用户上传的文件随容器销毁
  • 配置文件:每次重建容器都要重新配置

存储卷将数据直接写入宿主机的本地文件系统(或外部存储),数据可以完整保留。

  1. 性能问题

    UnionFS对于修改删除效率非常低,如果对于I/O要求比较高的应用,如redis在实现持久化存储时,是在底层存储时的性能要求比较高。

  2. 宿主机访问容器或者容器互访不方便 以及容器和容器共享不方便

存储卷分类

为什么不能只用一种存储卷?

  • 有些数据需要永久保存 (数据库数据),有些数据用完即丢(临时缓存)
  • 有些数据需要跨容器共享 (应用配置),有些数据绝对不能共享(敏感令牌)
  • 有些数据需要最高性能 (计算中间结果),有些数据需要最高可移植性(集群部署)
  • 开发时需要灵活修改 (代码),生产时需要严格隔离(避免误改宿主机)

单一存储方案无法兼顾所有这些矛盾,因此Docker分化出了三种定位完全不同的存储卷。

三种存储卷分别解决什么问题?

  1. Volume(Docker管理卷):

设计初衷:

容器本身是临时的,删除容器数据就会永久丢失。如果直接把数据存在容器内部,容器一旦崩溃或重建,所有数据都会消失。

而如果用绑定挂载,数据依赖宿主机的特定路径,换一台机器就无法运行,完全不适合集群和生产环境。

因此Docker需要一种独立于容器生命周期、由Docker统一管理、与宿主机解耦的存储方案,这就是Volume。

  1. Bind Mount(绑定挂载):

设计初衷:

开发阶段,我们需要频繁修改代码,然后立即在容器中看到效果。如果用Volume,代码会被复制到Docker的专属目录里,修改起来非常麻烦,每次修改都要重新构建镜像,效率极低。

因此需要一种直接映射宿主机文件系统的方式,让宿主机上的代码修改能实时同步到容器内,无需重新构建镜像。

  1. Tmpfs Mount(临时挂载):

设计初衷:

有些数据完全不需要持久化:比如应用的临时缓存、计算中间结果、上传文件的临时目录。这些数据如果写入磁盘,会浪费IO性能,而且容器停止后就没用了。

还有一些敏感数据:比如数据库密码、API令牌、会话密钥。这些数据如果写入磁盘,会留下永久痕迹,存在安全风险。

因此需要一种完全基于内存、不写入磁盘、随容器销毁自动消失的存储方案,这就是Tmpfs Mount。

Docker提供了三种方式将数据从宿主机挂载到容器中:

  • volume docker 管理卷 :默认映射到宿主机的/var/lib/docker/volumes目录下,只需要在容器内指定容器的挂载点是什么,而被绑定宿主机下的那个目录,是由容器引擎daemon自行创建一个空的目录,或者使用一个已经存在的目录,与存储卷建立存储关系
  • bind mount 绑定数据卷:映射到宿主机指定路径下,在宿主机上的路径要人工的指定一个特定的路径,在容器中也需要指定一个特定的路径,两个已知的路径建立关联关系
  • tmpfs mount 临时数据卷:映射到宿主机内存中,一旦容器停止运行,tmpfs mounts会被移除,数据就会丢失,用于高性能的临时数据存储。

管理卷 Volume

创建卷

存储卷可以通过命令方式创建,也可以在创建容器的时候通过 -v--mount 指定。

方式一:Volume 命令操作

命令清单如下:

命令 别名 功能
docker volume create 创建存储卷
docker volume inspect 显示存储卷详细信息
docker volume ls docker volume list 列出存储卷
docker volume prune 清理所有无用数据卷
docker volume rm 删除卷,使用中的无法删除
docker volume create
  • 功能

    • 创建存c
  • 语法

    shell 复制代码
    docker volume create [OPTIONS] [VOLUME]
  • 关键参数

    • -d, --driver: 指定驱动,默认是local
    • --label: 打上标签(一般是对存储卷的说明信息)
  • 样例

    shell 复制代码
    drw@VM-0-14-ubuntu:~$ docker volume create myvolume1
    myvolume1
    drw@VM-0-14-ubuntu:~$ docker volume create
    aacdd3492697e50f6774500fab279881d8292fae86958fba67e7abe941522bef
docker volume inspect
  • 功能

    • 查看卷详细信息
  • 语法

    shell 复制代码
    docker volume inspect [OPTIONS] VOLUME [VOLUME...]
  • 关键参数

    • -f: 指定相应个格式,如json
  • 样例

    shell 复制代码
    drw@VM-0-14-ubuntu:~$ docker volume inspect myvolume1
    [
      {
          "CreatedAt": "2026-04-15T10:08:33+08:00",
          "Driver": "local",
          "Labels": null,
          "Mountpoint": "/data/docker/volumes/myvolume1/_data",
          "Name": "myvolume1",
          "Options": null,
          "Scope": "local"
      }
    ]
    drw@VM-0-14-ubuntu:~$ docker volume inspect aacdd3492697e50f6774500fab279881d8292fae86958fba67e7abe941522bef myvolume1
    [
      {
          "CreatedAt": "2026-04-15T10:04:45+08:00",
          "Driver": "local",
          "Labels": {
              "com.docker.volume.anonymous": ""
          },
          "Mountpoint": "/data/docker/volumes/aacdd3492697e50f6774500fab279881d8292fae86958fba67e7abe941522bef/_data",
          "Name": "aacdd3492697e50f6774500fab279881d8292fae86958fba67e7abe941522bef",
          "Options": null,
          "Scope": "local"
      },
      {
          "CreatedAt": "2026-04-15T10:08:33+08:00",
          "Driver": "local",
          "Labels": null,
          "Mountpoint": "/data/docker/volumes/myvolume1/_data",
          "Name": "myvolume1",
          "Options": null,
          "Scope": "local"
      }
    ]
docker volume ls
  • 功能

    • 列出卷
  • 语法

    shell 复制代码
    docker volume ls [OPTIONS]
  • 关键参数

    • --format: 指定相应个格式,如json,table
    • --filter, -f: 过滤
    • -q: 仅显示名称
  • 样例

    shell 复制代码
    drw@VM-0-14-ubuntu:~$ docker volume ls
    DRIVER    VOLUME NAME
    local     5f769cdbdc193a261df4ffc1cee0f05bc7545ba9d569f2e19d143ea336359533
    local     6cbae332303260ee173a296fd5094f36b0a23ab419deaabce1c6fd23f42de7b9
    local     4413f159aa933d0a80c634303b98743a0b217466ec4376b160fca697c04ae30d
    local     07313d2fa972a513862619a5ed71d5eda091beac5561f514a58823aba64e776c
    local     69832c0db9f6d0ee8be351c91a6739639cddc72e52795f0d33818b238913ac95
    local     6321320584ebe9fb569fbc70a50759aa6358c5840e390ec0d9c5a4b09e7a58fe
    local     aacdd3492697e50f6774500fab279881d8292fae86958fba67e7abe941522bef
    local     d0713539e599fe6bfbd754a24c310b9c1f4d38520fa388ef9587affea09567ba
    local     eba54f85ace58a2ae5343e552b8ce8dcf73bdb65dcbbdaacf7ee5b6c9358f837
    local     myvolume1
docker volume rm
  • 功能

    • 删除卷,需要容器不使用。
  • 语法

    shell 复制代码
    docker volume rm [OPTIONS] VOLUME [VOLUME...]
  • 关键参数

    • -f, --force: 强制删除
  • 样例

    shell 复制代码
    drw@VM-0-14-ubuntu:~$ docker volume rm -f aacdd3492697e50f6774500fab279881d8292fae86958fba67e7abe941522bef
    aacdd3492697e50f6774500fab279881d8292fae86958fba67e7abe941522bef
docker volume prune
  • 功能

    • 删除不使用的匿名卷,不能删除命名卷
  • 语法

    shell 复制代码
    docker volume prune [OPTIONS]
  • 关键参数

    • --filter: 过滤
    • -f, --force: 不提示是否删除
  • 样例

    shell 复制代码
    drw@VM-0-14-ubuntu:~$ docker volume prune
    WARNING! This will remove anonymous local volumes not used by at least one container.
    Are you sure you want to continue? [y/N] y
    Deleted Volumes:
    5f769cdbdc193a261df4ffc1cee0f05bc7545ba9d569f2e19d143ea336359533
    4413f159aa933d0a80c634303b98743a0b217466ec4376b160fca697c04ae30d
    6cbae332303260ee173a296fd5094f36b0a23ab419deaabce1c6fd23f42de7b9
    07313d2fa972a513862619a5ed71d5eda091beac5561f514a58823aba64e776c
    69832c0db9f6d0ee8be351c91a6739639cddc72e52795f0d33818b238913ac95
    eba54f85ace58a2ae5343e552b8ce8dcf73bdb65dcbbdaacf7ee5b6c9358f837
    6321320584ebe9fb569fbc70a50759aa6358c5840e390ec0d9c5a4b09e7a58fe
    d0713539e599fe6bfbd754a24c310b9c1f4d38520fa388ef9587affea09567ba
    Total reclaimed space: 625.6MB
方式二:-v 或者 --mount 指定

-v--mount 都可以完成管理卷的创建

-v 参数
  • 功能:
    完成目录映射

  • 语法

    shell 复制代码
    docker run -v name:directory[:options] ......
  • 参数

    • 第一个参数:卷名称
    • 第二个参数:卷映射到容器的目录
    • 第三个参数:选项,如ro表示readonly,选择后不能进行修改操作 (指定的宿主机可以修改,但是容器里面无法修改)
  • 样例

bash 复制代码
drw@VM-0-14-ubuntu:~$ docker run -d --name mynginx -v nginx:/usr/share/nginx/html/ nginx:1.24.0
1a699e92eae4b899c04ca292d782421e2a6fb49537bda733aad54580e592b3ff
drw@VM-0-14-ubuntu:~$ docker volume ls
DRIVER    VOLUME NAME
local     nginx
drw@VM-0-14-ubuntu:~$ sudo rm -rf /data/docker/volumes/nginx/_data/index.html
drw@VM-0-14-ubuntu:~$ docker exec -it mynginx bash
# 已经看不到index了
root@1a699e92eae4:/# ls /usr/share/nginx/html/
50x.html
--mount 参数
  • 功能:
    完成目录映射

  • 语法

    shell 复制代码
    --mount '<key>=<value>,<key>=<value>'
  • 关键参数

    • type: 类型表示bind, volume, or tmpfs
    • source, src: 对于命名卷,这是卷的名称。对于匿名卷,省略此字段。
    • destination, dst, target: 文件或目录挂载在容器中的路径
    • ro,readonly: 只读方式挂载
  • 样例

bash 复制代码
drw@VM-0-14-ubuntu:~$ docker run -d --name mynginx --mount 'src=nginxvol,dst=/usr/share/nginx/html' nginx:1.24.0
be19f87bf403c8bd380dac0ca9439f4184d6a6d191eb5ffde5b49e2121ab4163
drw@VM-0-14-ubuntu:~$ docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
be19f87bf403   nginx:1.24.0   "/docker-entrypoint...."   2 seconds ago   Up 2 seconds   80/tcp    mynginx
drw@VM-0-14-ubuntu:~$ docker inspect mynginx
        "Mounts": [
            {
                "Type": "volume",
                "Name": "nginxvol",
                "Source": "/data/docker/volumes/nginxvol/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],
        
# 通过mounts目录来查看存储在哪个具体位置
方式三:Dockerfile 匿名卷

通过DockerfileVOLUME可以创建docker管理卷。后续在Dockerfile中详细讲解。

操作案例

1. 命令创建管理卷

bash 复制代码
# 创建一个名为test_volume1的卷
docker volume create test_volume1

# 查看所有卷
docker volume ls

# 查看卷的详细信息
docker volume inspect test_volume1

# 运行容器并挂载卷
docker run -d --name mynginx -p 8080:80 -v test_vol:/usr/share/nginx/html nginx:1.24.0

2. 内容已经被挂载

bash 复制代码
drw@VM-0-14-ubuntu:~$ sudo ls /data/docker/volumes/test_vol/_data
[sudo] password for drw: 
50x.html  index.html

3. 查看具体mount信息

bash 复制代码
 "Mounts": [
            {
                "Type": "volume",
                "Name": "test_vol",
                "Source": "/data/docker/volumes/test_vol/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],

4. 修改index.html

bash 复制代码
drw@VM-0-14-ubuntu:~$ docker exec -it mynginx bash
root@bbf02197525f:/# echo "nihao" > /usr/share/nginx/html/index.html 
root@bbf02197525f:/# exit
exit
drw@VM-0-14-ubuntu:~$ sudo cat /data/docker/volumes/test_vol/_data/index.html
nihao

5. 通过浏览器查看

访问 http://124.222.53.34:8080,可以看到页面显示:

6. 停止容器和删除容器

bash 复制代码
docker stop mynginx
docker rm mynginx

结论:指定的宿主机路径之间的数据是同步的,删除容器不会删除卷,这是docker数据持久化的一种方式。

Docker卷的生命周期

先让容器运行起来:

bash 复制代码
drw@VM-0-14-ubuntu:~$ docker run --name mynginx -d -p 8080:80 -v test_volume:/usr/share/nginx/html nginx:1.24.0
59cf454dd39e1fb1d5e7a82e5fa1ad8da64dfec07dac9ff5ee9a94ff505c4cb2

查看挂载信息:

bash 复制代码
"Mounts": [
            {
                "Type": "volume",
                "Name": "test_volume",
                "Source": "/data/docker/volumes/test_volume/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],

查看挂载信息,并删除容器查看信息,随后删除卷后再查看挂载信息:

bash 复制代码
drw@VM-0-14-ubuntu:~$ sudo ls /data/docker/volumes/test_volume/_data
[sudo] password for drw: 
50x.html  index.html
drw@VM-0-14-ubuntu:~$ docker rm -f mynginx
mynginx
drw@VM-0-14-ubuntu:~$ sudo ls /data/docker/volumes/test_volume/_data
50x.html  index.html
drw@VM-0-14-ubuntu:~$ docker volume rm test_volume
test_volume
drw@VM-0-14-ubuntu:~$ sudo ls /data/docker/volumes/test_volume/_data
ls: cannot access '/data/docker/volumes/test_volume/_data': No such file or directory

Docker卷共享

首先启动两个nginx容器,并绑定到同个目录:

bash 复制代码
drw@VM-0-14-ubuntu:~$ docker run --name mynginx1 -d -p 8080:80 -v test_volume:/usr/share/nginx/html nginx:1.24.0
3456a1efc289736083576fdcc00918a90e6e9c0c1c11fd68e92cb1468eafb7d0

drw@VM-0-14-ubuntu:~$ docker run --name mynginx2 -d -p 8081:80 -v test_volume:/usr/share/nginx/html nginx:1.24.0
85983d01316c195fae3c42020286afdfb57ba40495f7fa473e3a4d7d36c47cb8

修改目录下的文件:

bash 复制代码
root@VM-0-14-ubuntu:/home/drw# echo "hello world" > /data/docker/volumes/test_volume/_data/index.html

使用浏览器查看,两个端口显示的内容一致,说明都被修改了:


绑定卷 bind mount

-v--mount都可以完成绑定卷的创建

创建卷

-v 参数创建卷
  • 功能:完成卷映射
  • 语法
shell 复制代码
docker run -v name:directory[:options] .........
  • 参数
    • 第一个参数:宿主机目录,这个和管理卷不一样
    • 第二个参数:卷映射到容器的目录
    • 第三个参数:选项,如 ro 表示 readonly
  • 样例
shell 复制代码
docker run -d --name mynginx -v /home/drw/nginx:/usr/share/nginx/html/ nginx:1.24.0
--mount 参数创建绑定卷
  • 功能:完成目录映射
  • 语法
shell 复制代码
--mount '<key>=<value>,<key>=<value>'
  • 关键参数
    • type:类型表示 bind, volume, 或 tmpfs
    • source, src宿主机目录,这个和管理卷是不一样的
    • destination, dst, target:文件或目录挂载在容器中的路径
    • ro, readonly:只读方式挂载
  • 样例
shell 复制代码
docker run -d --name mynginx --mount type=bind,src=/home/drw/nginx,dst=/usr/share/nginx/html/ nginx:1.24.0

操作案例

mount 创建绑定卷

  1. 使用 --mount 方式创建容器:创建 nginx 容器,并将宿主机 /home/drw/nginx 目录挂载至容器 /usr/share/nginx/html 目录,注意如果 /home/drw/nginx 目录不存在会启动报错,如果目录已经存在并且已有文件,则以宿主机为准
shell 复制代码
drw@VM-0-14-ubuntu:~$ docker run -d --name mynginx --mount type=bind,src=/home/drw/nginx,dst=/usr/share/nginx/html/ nginx:1.24.0
67a56f630dd507466be5b0ab60986294fece37cae6fa10851e6ee6601460f7a9
  1. 查看挂载信息
shell 复制代码
drw@VM-0-14-ubuntu:~$ docker inspect mynginx
json 复制代码
 "Mounts": [
            {
                "Type": "bind",
                "Source": "/home/drw/nginx",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
  1. 进入容器的终端,查看挂载点目录,和在宿主机上查看里面都是没有文件
shell 复制代码
drw@VM-0-14-ubuntu:~$ docker exec -it mynginx ls /usr/share/nginx/html

-v 创建绑定卷

  1. 使用 -v 方式创建容器:注意如果目录不存在,启动不会报错,会自动创建,这是 -v 和 --mount 方式的区别,并且同个目录会以宿主机为准
shell 复制代码
docker run -d --name mynginx -v /home/drw/nginx:/usr/share/nginx/html/ nginx:1.24.0
  1. 查看挂载信息
shell 复制代码
drw@VM-0-14-ubuntu:~$ docker inspect mynginx
json 复制代码
"Mounts": [
            {
                "Type": "bind",
                "Source": "/home/drw/nginx",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

绑定卷共享

  1. 我们启动两个绑定卷,都绑定到宿主机的同一个目录
shell 复制代码
drw@VM-0-14-ubuntu:~$ docker run -d --name mynginx1 -v /home/drw/nginx:/usr/share/nginx/html nginx:1.24.0
ea6f8704e70c863ec9a5e01dc6065a0ceb5c55fb330baf8587be48b2955ebe39
drw@VM-0-14-ubuntu:~$ docker run -d --name mynginx2 -v /home/drw/nginx:/usr/share/nginx/html nginx:1.24.0
ed5fe72cc50a6c034e41a6d28bed9d5c2335bd8ce0eeadeebc5b2f15427249b4
  1. 我们访问2个页面可以看到相应内容一样
shell 复制代码
drw@VM-0-14-ubuntu:~$ docker exec -it mynginx1 cat /usr/share/nginx/html/index.html
hello
drw@VM-0-14-ubuntu:~$ docker exec -it mynginx2 cat /usr/share/nginx/html/index.html
hello
  1. 修改 index.html,再次访问两个页面就实现了容器间的数据共享

临时卷 tmpfs

临时卷数据位于内存中,在容器和宿主机之外。

tmpfs 局限性

  • 不同于卷和绑定挂载,不能在容器之间共享 tmpfs 挂载。
  • 这个功能只有在 Linux 上运行 Docker 时才可用

创建卷

方式一:指定--tmpfs 创建
  • 功能:完成一个临时卷挂载
  • 语法
shell 复制代码
--tmpfs /test
  • 样例
shell 复制代码
docker run -d --name mynginx1 --tmpfs /test -p 8080:80 nginx:1.24.0
方式二:--mount 指定参数创建
  • 功能:
    完成目录映射
  • 语法
shell 复制代码
--mount '<key>=<value>,<key>=<value>'
  • 关键参数
    • type:类型表示 bind, volume, or tmpfs
    • destinationdst, target:挂载在容器中的路径
    • tmpfs-size:tmpfs 挂载的大小(以字节为单位)。默认无限制。
    • tmpfs-mode:tmpfs 的八进制文件模式。例如,7000770。默认为 1777 或全局可写。
  • 样例
shell 复制代码
docker run --name mynginx1 -d -p 8080:80 --mount type=tmpfs,dst=/test nginx:1.24.0

如果容器停止,再次启动容器时创建的临时卷会被清空
如果指定了tmpfs挂载的大小,随后又放入一个超过限制的文件,会提示空间不足

综合实战-MySQL 灾难恢复

实战步骤

使用MySQL 5.7的镜像创建容器并将一个普通数据卷mysql-data用来保存容器中产生的数据。需要在容器中连接MySQL服务,并创建数据库test,并在该数据库中创建一个简单的表并插入一些数据进来。

-e选项通过参数MYSQL_ROOT_PASSWORD来传递MySQL密码

1. 运行容器

bash 复制代码
drw@VM-0-14-ubuntu:~$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=dairenwen1092 -v /home/drw/mysql:/var/lib/mysql -d mysql:5.7
e9ec5e9d7bc07cfd982054db009e3eb803387814ca818d18a888172aa766f7d4

drw@VM-0-14-ubuntu:~$ docker exec -it mysql bash
bash-4.2# mysql -u root -p
Enter password: 

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database test;
Query OK, 1 row affected (0.00 sec)

mysql> use test;
Database changed
mysql> create table if not exists Student( id int comment "student id", name varchar(30) comment "student name", primary key (id) )charset = utf8,engine = InnoDB;
Query OK, 0 rows affected (0.02 sec)

mysql> insert into Student values(2,"allen"),(3,"Yuki");
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

3. 查看容器挂载信息

shell 复制代码
"Mounts": [
            {
                "Type": "bind",
                "Source": "/home/drw/mysql",
                "Destination": "/var/lib/mysql",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

4. 在宿主机中查看volume

shell 复制代码
drw@VM-0-14-ubuntu:~$ ls /home/drw/mysql
auto.cnf    ca.pem           client-key.pem  ibdata1      ib_logfile1  mysql       performance_schema  public_key.pem   server-key.pem  test
ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile0  ibtmp1       mysql.sock  private_key.pem     server-cert.pem  sys

可以看到容器中MySQL创建的数据库和表数据已经持久化到宿主机挂载的目录下了。

6. 模拟灾难场景

shell 复制代码
docker stop mysql
docker rm mysql

7. 数据恢复

bash 复制代码
drw@VM-0-14-ubuntu:~$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=dairenwen1092 -v /home/drw/mysql:/var/lib/mysql -d mysql:5.7
386298176f861067714bab604c078c7ebadc3d928bf08fa98d28925518d35926
drw@VM-0-14-ubuntu:~$ docker exec -it mysql bash
bash-4.2# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> use test;
Database changed
mysql> select * from Student;
+----+-------+
| id | name  |
+----+-------+
|  2 | allen |
|  3 | Yuki  |
+----+-------+
2 rows in set (0.00 sec) 

常见问题

什么时候用Volume,什么时候用bind、tmpfs?

  • Volume:Volume是Docker的宿主机文件系统一部分,用于不需要规划具体目录的场景
  • bind:bind mount完全依赖于主机的目录结构和操作系统,用于目录需要提前规划的场景,比如:bind的目录需要一个空间大的,其他服务不占用的时候,用Volume就不太合适了
  • tmpfs:用于敏感文件存储,文件不想存储在宿主机和容器的可写层之中,此时就去内存中存储

存储卷在实际研发中带来了哪些问题

  1. 跨主机使用

    Docker存储卷是使用其所在的宿主机上的本地文件系统目录,也就是宿主机有一块磁盘,这块磁盘并没有共享给其他的Docker主机,容器在这台主机上停止或删除,是可以重新再创建的,但是不能调度到其他的主机上,这也是Docker本身没有解决的问题。所以Docker衍生的集群也注重存储,越来越多的分布式存储方案出现,如S3系列、NFS等。

  2. 启动参数未知

    容器有一个问题,一般与进程的启动不太一样,就是容器启动时选项比较多,如果下次容器再启动,很容易忘记它的启动时的选项,所以最好有一个文件来保存容器的启动,这就是容器编排工具的作用。

    一般情况下,是存储卷等,启动它docker,但是可以通过文件来读,也就读这个文件,就需要专业的容器编排工具,各个厂商也有自己的企业版编排软件。

  3. 复杂场景仍然需要运维

    对于有状态要持久化的集群化组件,如mysql的主从。部署维护一个Mysql主从需要运维知识、经验整合进去才能实现所谓的部署,扩展或缩容,出现问题后修复,必须要这种集群的统一管理,才能将复杂的点,这些点有多少个从节点,主节点上有多少个库,这种挂载卷的使用往往还需要人为,很难有完美的工具出现。

相关推荐
可视化运维管理爱好者7 小时前
rg完整中文操作指南
linux·运维·服务器·ai
寒山独见君~7 小时前
自动化-消息推送Server酱3,APP推送
运维·数据库·python·自动化·通知
都在酒里7 小时前
在公共服务器上构建 RK3588 SDK 的纯净 Docker 方案
运维·服务器·docker
计算机安禾7 小时前
【Linux从入门到精通】第46篇:SELinux与AppArmor——Linux的安全增强模块
linux·运维·安全
jeCA EURG7 小时前
docker离线安装及部署各类中间件(x86系统架构)
docker·中间件·系统架构
TBrL7UtdTELTTdut4BAL7 小时前
F7015TV3 光猫 Telnet 命令配置 DHCP 服务器
运维·服务器·网络
海兰7 小时前
将 Cursor 连接到生产日志:通过 Elastic MCP 服务器
运维·服务器·elasticsearch
计算机安禾7 小时前
【Linux从入门到精通】第41篇:Linux内核编译初体验——裁剪属于你自己的内核
linux·运维·服务器
Elastic 中国社区官方博客7 小时前
2026 年金融服务可观测性现状:从实施到业务影响
大数据·运维·人工智能·elasticsearch·搜索引擎·金融·自动化