Docker:Docker Volume存储卷-宿主机与容器的数据双向交流通道

Docker:Docker Volume存储卷-宿主机与容器的数据双向交流通道

一.什么是存储卷?意义?以及分类

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

在宿主机上的这个与容器形成绑定关系的目录被称作存储卷。卷的本质是文件或者目录,它可以绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上。宿主机的/data/web 目录与容器中的/container/data/web 目录绑定关系,然后容器中的进程向这个目录中写数据时,是直接写在宿主机的目录上的,绕过容器文件系统与宿主机的文件系统建立关联关系,使得可以在宿主机和容器内共享数据库内容,让容器直接访问宿主机中的内容,也可以宿主机向容器写入内容, 容器和宿主机的数据读写是同步的。

为什么需要存储卷呢?

  1. 数据丢失问题
    容器按照业务类型,总体可以分为两类:
    无状态的(数据不需要被持久化)
    有状态的(数据需要被持久化)
    显然,容器更擅长无状态应用。因为未持久化数据的容器根目录的生命周期与容器的生命周期一样,容器文件系统的本质是在镜像层上面创建的读写层,运行中的容器对任何文件的修改都存在于该读写层,当容器被删除时,容器中的读写层也会随之消失。
    虽然容器希望所有的业务都尽量保持无状态,这样容器就可以开箱即用,并且可以任意调度,但实际业务总是有各种需要数据持久化的场景,比如 MySQL、 Kafka 等有状态的业务。因此为了解决有状态业务的需求, Docker 提出了卷(Volume)的概念。
  2. 性能问题
    UnionFS(联合文件系统)对于修改删除等,一般效率非常低,如果对一于 I/O 要求比较高的应用,如redis 在实现持化存储时,是在底层存储时的性能要求比较高。
  3. 宿主机和容器互访不方便
    宿主机访问容器,或者容器访问要通过 docker cp 来完成,应用很难操作
  4. 容器和容器共享不方便

存储卷的分类

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

  • volume docker 管理卷,默认映射到宿主机的/var/lib/docker/volumes 目录下, 只需要在容器内指定容器的挂载点是什么,而被绑定宿主机下的那个目录,是由容器引擎 daemon 自行创建一个空的目录,或者使用一个已经存在的目录,与存储卷建立存储关系,这种方式极大解脱用户在使用卷时的耦合关系,缺陷是用户无法指定那些使用目录,临时存储比较适合;
  • bind mount 绑定数据卷,映射到宿主机指定路径下,在宿主机上的路径要人工的指定一个特定的路径, 在容器中也需要指定一个特定的路径, 两个已知的路径建立关联关系。我们一般多使用的也是绑定卷
  • tmpfs mount 临时数据卷,映射到于宿主机内存中,一旦容器停止运行, tmpfsmounts 会被移除,数据就会丢失,用于高性能的临时数据存储。

二.熟悉三种存储卷的常用命令及简单实践

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

2.1管理卷volume

2.1.1通过命令操作

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

docker volume create
功能

创建存储卷
语法

bash 复制代码
docker volume create [OPTIONS] [VOLUME]

关键参数

  • -d, --driver: 指定驱动,默认是 local
  • --label: 指定元数据

一般我们不会去修改驱动,如果想要了解-d选项的读者可以查看官方文档,我们下面只演示下无参与加--label的情况:

比如我们直接执行此命令,docker会直接创建一个匿名卷:

bash 复制代码
knd@NightCode:~$ sudo docker volume create
[sudo] password for knd:                                            
fe6721d49d3e3fa4794db8f5fd06c0c487f439041433a62953a7b376217fffc8

我们可以使用docker inspect查看此存储卷的详情:

bash 复制代码
knd@NightCode:~$ sudo docker inspect fe6721d49d3e3fa4794db8f5fd06c0c487f439041433a62953a7b376217fffc8
[
    {
        "CreatedAt": "2025-12-29T17:19:08+08:00",
        "Driver": "local",
        "Labels": {
            "com.docker.volume.anonymous": ""
        },
        "Mountpoint": "/var/lib/docker/volumes/fe6721d49d3e3fa4794db8f5fd06c0c487f439041433a62953a7b376217fffc8/_data",
        "Name": "fe6721d49d3e3fa4794db8f5fd06c0c487f439041433a62953a7b376217fffc8",
        "Options": null,
        "Scope": "local"
    }
]

可以看到此存储卷默认情况下是在/var/lib/docker/volumes/目录下的。

如果我们指定其--label属性,其实就像我们浏览视频网站时,不同的视频被划分到了不同的分类标签下,主要是为了方便查找目标存储卷而存在的,毕竟元数据本就是对数据描述的数据。

我们来使用此选项去创建一个存储卷,至于如何使用此'标签',我们到ls那里在演示:

bash 复制代码
knd@NightCode:~$ sudo docker volume create mytestvolume --label MYTEST=1
mytestvolume
knd@NightCode:~$ sudo docker volume inspect mytestvolume
[
    {
        "CreatedAt": "2025-12-29T17:26:10+08:00",
        "Driver": "local",
        "Labels": {
            "MYTEST": "1"
        },
        "Mountpoint": "/var/lib/docker/volumes/mytestvolume/_data",
        "Name": "mytestvolume",
        "Options": null,
        "Scope": "local"
    }
]
docker volume inspect

docker volume inspect
功能

查看卷详细信息
语法

bash 复制代码
docker volume inspect [OPTIONS] VOLUME [VOLUME...]

关键参数

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

emm,这里就不作演示了,详情可以看上面的create部分。

docker volume ls

功能

列出卷
语法

bash 复制代码
docker volume ls [OPTIONS]

关键参数

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

比如我想要查询所有的存储卷信息,不带任何参数:

bash 复制代码
knd@NightCode:~$ sudo docker volume ls
DRIVER    VOLUME NAME
local     fe6721d49d3e3fa4794db8f5fd06c0c487f439041433a62953a7b376217fffc8
local     mytestvolume

想让其以json格式输出:

bash 复制代码
knd@NightCode:~$ sudo docker volume ls --format json
{"Availability":"N/A","Driver":"local","Group":"N/A","Labels":"com.docker.volume.anonymous=","Links":"N/A","Mountpoint":"/var/lib/docker/volumes/fe6721d49d3e3fa4794db8f5fd06c0c487f439041433a62953a7b376217fffc8/_data","Name":"fe6721d49d3e3fa4794db8f5fd06c0c487f439041433a62953a7b376217fffc8","Scope":"local","Size":"N/A","Status":"N/A"}
{"Availability":"N/A","Driver":"local","Group":"N/A","Labels":"MYTEST=1","Links":"N/A","Mountpoint":"/var/lib/docker/volumes/mytestvolume/_data","Name":"mytestvolume","Scope":"local","Size":"N/A","Status":"N/A"}

想通过一定条件的过滤查询对应存储卷,比如我们使用label过滤:

bash 复制代码
knd@NightCode:~$ sudo docker volume ls -f label=MYTEST
DRIVER    VOLUME NAME
local     mytestvolume
knd@NightCode:~$ sudo docker volume ls -f label=MYTEST=1
DRIVER    VOLUME NAME
local     mytestvolume
knd@NightCode:~$ sudo docker volume ls -f label=MYTEST=0
DRIVER    VOLUME NAME
docker volume rm

功能

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

bash 复制代码
docker volume rm [OPTIONS] VOLUME [VOLUME...]

关键参数

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

这个命令不再多说,毕竟比较简单就不演示了。

docker volume prune

功能

删除不使用的本地卷
语法

bash 复制代码
docker volume prune [OPTIONS]

关键参数

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

常规的prune不带任何参数的使用就不展示了,加-f则是不弹出任何删除提醒,并不会删除正在使用的存储卷 。我们这里展示下标签过滤删除的情况:

需要注意的一个问题是,默认的 prune 命令不处理未被使用的具名卷!!!

此时则需要加上--all或-a选项,此选项的作用是:在api:1.42+中官网文档中描述如下:Remove all unused volumes, not just anonymous ones

bash 复制代码
knd@NightCode:~$ sudo docker volume prune -f -a --filter label=MYTEST=1
Deleted Volumes:
mytestvolume

Total reclaimed space: 0B

2.1.2通过-v或--mount指定

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

-v 参数

功能

完成目录映射
语法

bash 复制代码
docker run -v name:directory[:options] .........

参数

  • 第一个参数:卷名称
  • 第二个参数:卷映射到容器的目录
  • 第三个参数:选项,如 ro 表示 readonly

这里需要说明的东西是,name位置如果给的是一个单纯的名字的话,它创建的是一个管理卷,但如果给的是宿主机上一个实际存在的文件目录的话,它创建的是一个绑定卷。

我们还是使用nginx来做下演示,比如我们让管理卷去映射其首页html文件所在的目录:

bash 复制代码
knd@NightCode:~$ sudo docker run -d --name nginx -v mytestvolume:/usr/share/nginx/html -p 8080:80 nginx:1.29.4
eaf2c4533235c8f267fc877a6baaca669e43c5091a1126d635076e941f622b84
knd@NightCode:~$ sudo docker inspect mytestvolume
[
    {
        "CreatedAt": "2025-12-29T18:31:12+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/mytestvolume/_data",
        "Name": "mytestvolume",
        "Options": null,
        "Scope": "local"
    }
]
knd@NightCode:~$ sudo docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                                     NAMES
eaf2c4533235   nginx:1.29.4   "/docker-entrypoint...."   22 seconds ago   Up 21 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   nginx
knd@NightCode:~$ sudo ls /var/lib/docker/volumes/mytestvolume/_data
50x.html  index.html

可以看到此时nginx容器的首页目录下的所有文件都映射到了Mountpoint后的目录下了。我们再看下容器的详细信息:

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

它立面也有一个Mounts,记录了对应的映射目录。

如果我们直接从宿主机上修改此index.html文件,则访问此容器的监听端口时内容也会发生改变:

bash 复制代码
knd@NightCode:~$ sudo vim /var/lib/docker/volumes/mytestvolume/_data/index.html
knd@NightCode:~$ curl 127.0.0.1:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx change not in container!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

所以等于说容器内我们指定的那个目录实际上往立面修改或新增删除数据时其实就是对宿主机中创建存储卷时所指定的目录进行响应操作。

如果我们在启动容器-v绑定存储卷时加上了ro/readonly,那么我们从容器内部对绑定目录下的文件进行修改时会爆如下错误,但是此时仍可以在宿主机上对相应文件进行修改:

bash 复制代码
root@de712d158b67:/# echo "hello world" > /usr/share/nginx/html/index.html 
bash: /usr/share/nginx/html/index.html: Read-only file system

这里再额外说一个点,如果指定的目录不存在,那么-v选项会自动在容器内部创建对应目录。下面的--mount则是直接报错。

--mount参数

功能

完成目录映射
语法

bash 复制代码
--mount <key>=<value>,<key>=<value>

关键参数

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

我们这里演示下使用--mount参数对容器绑定一个管理卷:

bash 复制代码
knd@NightCode:~$ sudo docker run --name=nginx -d -p 8080:80 --mount src=mytestvolume,dst=/usr/share/nginx/html,ro nginx:1.29.4
1e2101ec3f1ff17d6da3234212a030966aa495baf7a1386586e83fbcfe2cbf1f

当然这是个只读管理卷,所以情况和上面-v选项的最后部分说的一样,容器内无法进行修改。

dockerfile匿名卷

通过 Dockerfile 的 VOLUME 可以创建 docker 管理卷。这个我们后续在 Dockerfile中详细讲解。

我们也可以通过 dockerfile 的 VOLUME 指令在镜像中创建 Data Volume,这样只要通过该镜像创建的容器都会存在挂载点,但值得注意的是通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,而是由 docker 随机生成的

2.2绑定卷

-v参数创建

选项与语法与管理卷处展示一致。

需要提前说明一点的是,如果指定的宿主机路径不存在,-v则是会直接创建对应目录,而--mount不会,会直接报错。和上面dst指定不存在时一致。

创建绑定卷很简单,只要把name的位置输入为宿主机上的一个目录即可:

bash 复制代码
knd@NightCode:~/dockertest$ ls
namespacets
knd@NightCode:~/dockertest$ sudo docker run -d -p 8080:80 --name=nginx -v ./test:/usr/share/nginx/html:ro nginx:1.29.4
fe04ea05bdb21a128092d84c326a8387002a6701a8b3f60b8d60d49aa79b7f28
knd@NightCode:~/dockertest$ ls
namespacets  test
knd@NightCode:~/dockertest$ sudo docker volume ls
DRIVER    VOLUME NAME
local     mytestvolume
knd@NightCode:~/dockertest$ sudo docker inspect nginx
...
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/home/knd/dockertest/test",
                "Destination": "/usr/share/nginx/html",
                "Mode": "ro",
                "RW": false,
                "Propagation": "rprivate"
            }
        ],
...

可以看到此时的Mounts中的type类型为bind。

--mount参数创建

选项与语法与管理卷处展示一致。

也很简单,我们这里使用--mount创建一个只读绑定卷出来,但是需要注意,创建管理卷时必须显示指定type为bind,否则docker会认为你创建的是一个volume管理卷,而且命名会直接报错:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker run -p 8080:80 --mount src=/home/knd/dockertest/test,dst=/usr/share/nginx/html,ro --name=nginx -d nginx:1.29.4
docker: Error response from daemon: create /home/knd/dockertest/test: "/home/knd/dockertest/test" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path

Run 'docker run --help' for more information
knd@NightCode:~/dockertest$ sudo docker run -p 8080:80 --mount type=bind,src=./test,dst=/usr/share/nginx/html,ro --name=nginx -d nginx:1.29.4
403cc6195b8ff5687bbf0aacd87cd6486c6f6d0c1458abdb1b0df6a320766bb1
knd@NightCode:~/dockertest$ sudo docker inspect nginx
...
            "Mounts": [
                {
                    "Type": "bind",
                    "Source": "/home/knd/dockertest/test",
                    "Target": "/usr/share/nginx/html",
                    "ReadOnly": true
                }
            ],
...
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/home/knd/dockertest/test",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",
                "RW": false,
                "Propagation": "rprivate"
            }
        ],
...

2.3临时卷

我们上面说过,临时卷实际上是存储在内存中的。而内存我们是无法轻松的访问到我们指定的内容的除非通过相应程序。也确保了数据的安全性。不过需要注意的是,创建临时卷时会清空容器内对应目录下的所有文件。

--tmpfs创建

功能

完成临时卷映射
语法

bash 复制代码
--tmpfs /app

我们使用run加--tmpfs为nginx首页目录指定一个临时卷:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker run --name nginx -d -p 8080:80 --tmpfs /usr/share/nginx/html nginx:1.29.4
dc2fb625d39233c528145e076cff21e651b6d8c70fa638d47eeeec0e8992a4ff
knd@NightCode:~/dockertest$ sudo docker exec -it nginx ls /usr/share/nginx/html
knd@NightCode:~/dockertest$ 

如果我们在宿主机中查找对应目录下的文件也是查找不到的:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker exec -it nginx bash
root@dc2fb625d392:/# cd /usr/share/nginx/html/
root@dc2fb625d392:/usr/share/nginx/html# touch mytest114514.txt
root@dc2fb625d392:/usr/share/nginx/html# echo 1 > mytest114514.txt
root@dc2fb625d392:/usr/share/nginx/html# exit
exit
knd@NightCode:~/dockertest$ sudo find / -name mytest114514.txt
knd@NightCode:~/dockertest$ 

--mount创建

功能

完成目录映射
语法

bash 复制代码
--mount  <key>=<value>,<key>=<value>

关键参数

  • type : 类型表示 bind, volume, or tmpfs
  • destination, dst,target:挂载在容器中的路径
  • tmpfs-size: tmpfs 挂载的大小(以字节为单位)。默认无限制。
  • tmpfs-mode: tmpfs 的八进制文件模式。例如, 700 或 0770。默认为 1777或全局可写。
    它当然也会覆盖容器内对应目录下的所有文件,这里我们就演示下tmpfs-size选项,如果我们放入了一个超出其限制的文件会怎么样?:
bash 复制代码
knd@NightCode:~/dockertest$ sudo docker cp ./card_normal_11.png  nginx:/usr/share/nginx/html
Successfully copied 2.56MB to nginx:/usr/share/nginx/html
knd@NightCode:~/dockertest$ sudo docker exec -it nginx ls /usr/share/nginx/html
knd@NightCode:~/dockertest$

实际上并没有拷过去,我们来看下具体原因,换种方式拷贝,先将此文件拷贝到容器内的一个临时目录下,然后再到容器内部进行拷贝:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker exec -it nginx mkdir /mytest
knd@NightCode:~/dockertest$ sudo docker cp ./card_normal_11.png  nginx:/mytest
Successfully copied 2.56MB to nginx:/mytest
knd@NightCode:~/dockertest$ sudo docker exec -it nginx bash
root@860bdfa81188:/# cd /usr/share/nginx/html/
root@860bdfa81188:/usr/share/nginx/html# cp /mytest/card_normal_11.png ./
cp: error writing './card_normal_11.png': No space left on device

他说没有足够的空间,便足以说明我们上面的设置起效果了。

2.4使用样例-多个容器共享一个存储卷(除临时卷)

我们可以让多个容器去使用同一个绑定/管理卷实现不同容器下的数据同步:

这里我们以比较复杂些的--mount及较为常用的绑定卷做一个示例:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker run --name nginx1 -d -p 8080:80 --mount type=bind,src=./test,dst=/usr/share/nginx/html nginx:1.29.4
e7ed6e95bf5c6b5d292d68d408ea2f6001465f5d7e60228f9916758ff0f93a8f
knd@NightCode:~/dockertest$ sudo docker run --name nginx2 -d -p 8081:80 --mount type=bind,src=./test,dst=/usr/share/nginx/html nginx:1.29.4
dfb5c9da06c61899d6590340ed6b632ef10fa1ecd5477e4fdb8453759f1221ef
knd@NightCode:~/dockertest$ sudo docker run --name nginx3 -d -p 8082:80 --mount type=bind,src=./test,dst=/usr/share/nginx/html nginx:1.29.4
eee3e7179def413e41ee2b722e5f846d66d68587872ac1dc777ad77d0a2e2aa7
knd@NightCode:~/dockertest$ ls ./test
knd@NightCode:~/dockertest$ echo "hello world" > ./test/index.html
knd@NightCode:~/dockertest$ curl 127.0.0.1:8080
hello world
knd@NightCode:~/dockertest$ curl 127.0.0.1:8081
hello world
knd@NightCode:~/dockertest$ curl 127.0.0.1:8082
hello world

可以看到不同的容器访问的结果却是一样的。

三.综合实践-Mysql灾难恢复

如果我们的mysql容器的数据库数据存放在容器内部,一旦不小心删除了容器,之前的文件就没有了,所以这里我们可以将mysql中的数据库数据在创建始就放到宿主机中实际存在的一个目录下最好:

我们根据官网给的提示进行存储卷绑定:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker run --name mysql -p 8080:3306 -e MYSQL_ROOT_PASSWORD=114514 -d -v ./mysql:/var/lib/mysql mysql:8.0.44
305b13110d9b3d135ade72443e00bf4806e31daab1817d111fea5ab20ccb4e5a

这时候我们进入容器随便给他创建一个表插入几条数据,我直接让ai给我生成了:

bash 复制代码
-- 1. 创建数据库
CREATE DATABASE demo_db
  DEFAULT CHARACTER SET utf8mb4
  COLLATE utf8mb4_general_ci;

-- 2. 使用数据库
USE demo_db;

-- 3. 创建表
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100),
    age INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 4. 插入 3 条数据
INSERT INTO users (username, email, age) VALUES
('alice', 'alice@example.com', 23),
('bob', 'bob@example.com', 30),
('charlie', 'charlie@example.com', 28);
bash 复制代码
knd@NightCode:~/dockertest$ ls
mysql  namespacets  test  test.sql
knd@NightCode:~/dockertest$ sudo docker cp ./test.sql mysql:/test.sql
Successfully copied 2.56kB to mysql:/test.sql
knd@NightCode:~/dockertest$ sudo docker exec -it mysql ls /
afs  bin  boot  dev  docker-entrypoint-initdb.d  entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  test.sql  tmp  usr  var
knd@NightCode:~/dockertest$ sudo docker exec -it mysql bash
bash-5.1# mysql -uroot -p < test.sql
Enter password: 
bash-5.1# exit
exit

可以在navicat中看到对应数据库与数据:

然后我们把这个容器删除了,再新启一个此容器:

bash 复制代码
knd@NightCode:~/dockertest$ sudo docker stop mysql
mysql
knd@NightCode:~/dockertest$ sudo docker rm mysql
mysql
knd@NightCode:~/dockertest$ sudo docker run --name mysql -v ./mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=114514 -d -p 8080:3306 mysql:8.0.44
a466d85bdec005497e2f9bd13400fd4b8b8e4dd930cd09d65c6bb49869198f18

此时我们发现我们之前的数据仍然存在!!!

四.其他常见问题及扩展思考

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

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

扩展思考:存储卷在实际研发中带来了哪些问题

  1. 跨主机使用
    docker 存储卷是使用其所在的宿主机上的本地文件系统目录,也就是宿主机有一块磁盘,这块磁盘并没有共享给其他的 docker 主机,容器在这宿主机上停止或删除,是可以重新再创建的,但是不能调度到其他的主机上,这也是 docker 本身没有解决的问题,所以 docker 存储卷默认就是 docker 所在主机的本地,但是自己搭建一个共享的 NFS来存储 docker 存储的数据,也可以实现, 但是这个过程强依赖于运维人员的能力。所以未来应用的存储和数据往往分离,越来越多的分布式存储方案出现,如 s3 系列,nfs 等。
  2. 启动参数未知
    容器有一个问题,一般与进程的启动不太一样,就是容器启动时选项比较多,如果下次再启动时,很容器会忘记它启动时的选项,所以最好有一个文件来保存容器的启动,这就是容器编排工具的作用。一般情况下,是使用命令来启动操作 docker,但是可以通过文件来读,也就读文件来启动,读所需要的存储卷等,但是它也只是操作一个容器,如果要几十上百个容器操作,就需要专业的容器编排工具这种一般像开源的 k8s,各个云厂商也有自己的企业版编排软件。
  3. 复杂场景仍然需要运维对于有状态要持久的集群化组件,如 mysql 的主从。部署维护一个 Mysql 主从需要运维知识、经验整合进去才能实现所谓的部署,扩展或缩容,出现问题后修复,必须要了解集群的规模有多大,有多少个主节点,有多少个从节点,主节点上有多少个库,这些都要一清二楚,才能修复故障,这些就强依赖于运维经验这种复杂的场景往往还是需要人力,很难有完美的工具出现。
相关推荐
破烂pan2 小时前
企业级 Docker 运维命令速查表
运维·docker
dddddppppp1232 小时前
c 模拟一个fat16文件系统1
linux·运维·服务器
活蹦乱跳酸菜鱼2 小时前
Linux开发板使用AI-通义千问
linux·运维·服务器
lihui_cbdd2 小时前
[故障排查] NFS 存储集群卡顿的完整排查记录:谁在深夜疯狂读写?
linux·运维
Samson Bruce2 小时前
【docker swarm】
java·docker·eureka
掘根2 小时前
【消息队列项目】客户端搭建与测试
运维·服务器·中间件
ONE_SIX_MIX2 小时前
debian 13 安装 nvidia-driver 后,登录后黑屏,只能看到左上角光标 或 一个鼠标 的问题解决
运维·debian
虹科数字化与AR2 小时前
安宝特方案丨AR电力·变电篇:筑牢变电站安全运维
运维·安全·ar
代码游侠2 小时前
应用——Linux Socket编程
运维·服务器·开发语言·笔记·网络协议·学习