【Docker基础】深入解析 Docker 存储卷:管理、绑定与实战应用
文章目录
- 一、什么是存储卷
- 二、为什么需要存储卷
- 三、存储卷分类
- 四、管理卷 Volume
- 方式一:Volume 命令操作
- 方式二:使用 `-v` 或 `--mount` 参数指定卷
- 方式三:Dockerfile 匿名卷
- 五、操作案例
- Docker 命令创建管理卷
- Docker -v 创建管理卷
- Docker 卷生命周期
- Docker 卷共享
- 六、绑定卷 bind mount
- 创建卷
- 使用 `-v` 参数创建卷
- 使用 `--mount` 参数创建绑定卷
- 操作案例
- 使用 `--mount` 方式创建容器
- 使用 `-v` 创建绑定卷
- 绑定卷共享
- 七、临时卷 `tmpfs`
- 创建临时卷
- 方式一:使用 `--tmpfs` 参数创建
- 方式二:使用 `--mount` 参数创建
- 操作案例
- `tmpfs` 参数创建临时卷
- `mount` 创建临时卷
- `tmpfs` 失踪
- 八、实战练习:Mysql 灾难恢复
- 九、关于 Volume 的一些问题
- 什么时候使用 Volume、Bind/Mount 和 tmpfs?
- 存储卷在实际研发中的问题
一、什么是存储卷
存储卷是指将宿主机的本地文件系统中的某个目录与容器内部文件系统中的目录建立绑定关系。
具体来说,当我们在容器中的某个目录下写入数据时,容器会将数据直接写入宿主机上与该容器绑定的目录。
宿主机上与容器形成绑定关系的 目录 被称为存储卷。存储卷的本质是文件或目录,它绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上。
例如,宿主机的 /data/web
目录与容器的 /container/data/web
目录形成绑定关系。当容器中的进程向该目录写入数据时,数据会直接写入宿主机的 /data/web
目录。通过这种方式,容器文件系统和宿主机文件系统建立了关联,实现了容器和宿主机之间的数据共享。
这种机制使得容器可以直接访问宿主机中的内容,同时宿主机也可以向容器写入内容。容器和宿主机的数据读写是同步的。
二、为什么需要存储卷
- 数据丢失问题
容器按照业务类型,总体可以分为两类:
- 无状态的(数据不需要被持久化)
- 有状态的(数据需要被持久化
容器更擅长无状态应用。因为未持久化数据的容器根目录的生命周期与容器的
生命周期一样,容器文件系统的本质是在镜像层上面创建的读写层,运行中的容器对
任何文件的修改都存在于该读写层,当容器被删除时,容器中的读写层也会随之消失
虽然容器希望所有的业务都尽量保持无状态,这样容器就可以开箱即用,并且可以任
意调度,但实际业务总是有各种需要数据持久化的场景,比如 MySQL、Kafka 等有状
态的业务。因此为了解决有状态业务的需求,Docker 提出了卷(Volume)的概念。
- 性能问题
UnionFS 在处理修改、删除等操作时,效率较低。对于 I/O 要求较高的应用,如 Redis,在实现持久化存储时,底层存储的性能要求非常高,UnionFS 可能无法满足这些需求。
- 宿主机和容器互访不方便
宿主机访问容器,或容器访问宿主机时,通常需要通过 docker cp
等命令来完成,这使得操作变得复杂且不便于应用程序直接访问文件系统。
- 容器和容器共享不方便
容器之间共享数据时,也存在不便之处。由于每个容器都有独立的文件系统,容器间的直接共享和数据交换变得复杂且不容易操作。
三、存储卷分类
Docker 提供了三种方式将数据从宿主机挂载到容器中:
-
Volume(卷)
由 Docker 管理的卷,默认映射到宿主机的/var/lib/docker/volumes
目录下。在容器内,只需指定挂载点,容器引擎会自动创建一个空目录,或使用已存在的目录与宿主机建立存储关系。这种方式解耦了用户与存储目录的关系,适合临时存储。缺点是用户无法指定具体使用的目录。 -
Bind Mount(绑定数据卷)
绑定数据卷将宿主机的指定路径映射到容器。宿主机上的路径需要用户手动指定,并且容器中也需要指定对应路径。两个已知的路径建立关联关系。 -
Tmpfs Mount(临时数据卷)
将数据映射到宿主机的内存中。一旦容器停止运行,tmpfs
卷会被移除,数据丢失。此方式用于高性能的临时数据存储。
四、管理卷 Volume
存储卷可以通过命令创建,也可以在创建容器时通过 -v
或 --mount
进行指定。
方式一:Volume 命令操作
命令清单如下:
命令 | 别名 | 功能 | 备注 |
---|---|---|---|
docker volume create | — | 创建存储卷 | — |
docker volume inspect | — | 显示存储卷详细信息 | 显示卷的元数据和配置 |
docker volume ls | docker volume list | 列出存储卷 | — |
docker volume prune | — | 清理所有无用数据卷 | 删除未使用的卷 |
docker volume rm | — | 删除存储卷 | 无法删除正在使用中的卷 |
Docker Volume 操作解释
-
docker volume create
功能:创建存储卷
语法:docker volume create [OPTIONS] [VOLUME]
关键参数:
-d, --driver
:指定驱动,默认是local
--label
:指定元数据
示例:
docker volume create my-vol
-
docker volume inspect
功能:查看卷详细信息
语法:docker volume inspect [OPTIONS] VOLUME [VOLUME...]
关键参数:
-f
:指定输出格式,如json
示例:
docker volume inspect my-vol
-
docker volume ls
功能:列出卷
语法:docker volume ls [OPTIONS]
关键参数:
--format
:指定输出格式,如json
,table
--filter, -f
:过滤-q
:仅显示卷名称
示例:
docker volume ls
-
docker volume rm
功能:删除卷,容器不使用时才能删除
语法:docker volume rm [OPTIONS] VOLUME [VOLUME...]
关键参数:
-f, --force
:强制删除
示例:
docker volume rm hello
-
docker volume prune
功能:删除未使用的本地卷
语法:docker volume prune [OPTIONS]
关键参数:
--filter
:过滤-f, --force
:不提示确认删除
示例:
docker volume prune
方式二:使用 -v
或 --mount
参数指定卷
-v
和 --mount
都可以用于创建和管理卷。以下是两种方式的详细说明:
-v
参数
功能:完成目录映射
语法:
docker run -v name:directory[:options] ...
参数说明:
- 第一个参数:卷名称
- 第二个参数:卷映射到容器中的目录
- 第三个参数:选项,如
ro
表示只读模式
示例:
docker run -d --name devtest -v myvol2:/app nginx:latest
通过 docker inspect
可以看到:
"Mounts": [{"Type": "volume","Name": "myvol2","Source": "/var/lib/docker/volumes/myvol2/_data","Destination": "/app","Driver": "local","Mode": "","RW": true,"Propagation": ""}
]
-mount
参数
功能:完成目录映射
语法:
--mount '<key>=<value>,<key>=<value>'
关键参数:
- type:指定类型,可选
bind
、volume
或tmpfs
- source (src):对于命名卷,这是卷的名称;对于匿名卷,省略此字段
- destination (dst, target):容器中挂载的文件或目录路径
- ro, readonly:以只读方式挂载
示例:
采用 --mount
创建卷
docker run -d --name devtest --mount source=myvol2,target=/app nginx:latest
通过 docker inspect
可以看到:
"Mounts": [{"Type": "volume","Name": "myvol2","Source": "/var/lib/docker/volumes/myvol2/_data","Destination": "/app","Driver": "local","Mode": "","RW": true,"Propagation": ""}
]
方式三:Dockerfile 匿名卷
通过 Dockerfile 中的 VOLUME
指令,可以创建 Docker 管理的卷。
使用 VOLUME
指令可以在镜像中创建数据卷,确保每个通过该镜像创建的容器都会自动包含挂载点。但需要注意的是,通过 VOLUME
指令创建的挂载点无法指定主机上的具体目录,而是由 Docker 随机生成。
五、操作案例
Docker 命令创建管理卷
-
创建 Docker 管理卷
使用以下命令创建一个名为
test_volume
的管理卷,并通过 Docker 容器挂载该卷:
ubuntu@VM-8-2-ubuntu:~$ docker volume create test_volume
test_volumeubuntu@VM-8-2-ubuntu:~$ docker container run --name nginx1 -d -p 8080:80 -v test_volume:/usr/share/nginx/html nginx:1.24.0
b2148264eed78ff979945bd7bec1ca14c9158c596f7e509261acdbda9ac358f4
-
查看管理卷
使用以下命令查看所有 Docker 管理卷:
ubuntu@VM-8-2-ubuntu:~$ docker volume ls
DRIVER VOLUME NAME
local 1d853d8af50a81ef4f21a3984288cc19bb2beea754ebd997f6aab62e04bbc6a9
local ebf76ebf9a2b50aa1cadfb4d9d3610b2172f13fb33d3ed52db755900daf3c5e1
local myvol2
local test_volume
-
查看卷的详细信息
通过以下命令查看
test_volume
的详细信息,包括对应的宿主机目录:
ubuntu@VM-8-2-ubuntu:~$ docker volume inspect test_volume
[{"CreatedAt": "2025-03-17T16:14:48+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/test_volume/_data","Name": "test_volume","Options": null,"Scope": "local"}
]
-
查看宿主机目录内容
进入宿主机目录,查看卷挂载的数据:
ubuntu@VM-8-2-ubuntu:~$ sudo bash
root@VM-8-2-ubuntu:/home/ubuntu# cd /var/lib/docker/volumes/test_volume/_data
root@VM-8-2-ubuntu:/var/lib/docker/volumes/test_volume/_data# ls
50x.html index.html
-
查看容器的挂载信息
通过以下命令查看容器的挂载信息,确认卷挂载到容器:
ubuntu@VM-8-2-ubuntu:~$ docker inspect nginx1
[{"Id": "b2148264eed78ff979945bd7bec1ca14c9158c596f7e509261acdbda9ac358f4","Created": "2025-03-17T08:27:12.908655805Z","Path": "/docker-entrypoint.sh","Args": ["nginx","-g","daemon off;"],"State": {.....
-
修改文件
修改
index.html
文件的内容:
cd /data/var/lib/docker/volumes/test_volume/_dataecho "Hello Docker" > index.html
-
通过浏览器查看
访问容器的页面,通过浏览器查看内容,可以看到宿主机和容器中的数据是同步的。
-
停止容器并释放资源
停止并删除容器以释放占用的资源:
docker stop nginx1 docker rm nginx1
结论:
宿主机和容器之间的数据是同步的,修改宿主机目录中的文件,会实时反映到容器中的挂载位置。
Docker -v 创建管理卷
-v
创建管理卷,并启动容器
ubuntu@VM-8-2-ubuntu:~$ docker container run --name nginx2 -d -p 8080:80 -v test_volume2:/usr/share/nginx/html:ro nginx:1.24.0
b4e93a64a5f7f9c278bc5d7b6e26efb8932f2387406fe66ec4a22dc80df1be35
- 进入卷目录:
ubuntu@VM-8-2-ubuntu:~$ docker inspect test_volume2
[{"CreatedAt": "2025-03-17T17:04:09+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/test_volume2/_data","Name": "test_volume2","Options": null,"Scope": "local"}
]
ubuntu@VM-8-2-ubuntu:~$ sudo bash
root@VM-8-2-ubuntu:/home/ubuntu# cd /var/lib/docker/volumes/test_volume/_data
root@VM-8-2-ubuntu:/var/lib/docker/volumes/test_volume/_data#
- 修改
index.html
,随后在浏览器进行查看:
root@VM-8-2-ubuntu:/var/lib/docker/volumes/test_volume/_data# echo "Hello Docker from test_volume2" > index.html
- 在容器中尝试修改
index.html
,提示只读文件,无法修改:
root@VM-8-2-ubuntu:/var/lib/docker/volumes/test_volume/_data# docker exec -it nginx2 bash
root@b4e93a64a5f7:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@b4e93a64a5f7:/# cd /usr/share/nginx/html/
root@b4e93a64a5f7:/usr/share/nginx/html# rm index.html
rm: cannot remove 'index.html': Read-only file system
- 清理释放空间
docker stop nginx2
docker rm nginx2
结论:
使用 :ro
的卷挂载选项会让容器的文件系统无法修改挂载卷中的内容,但是宿主机仍然能修改卷中的内容。
Docker 卷生命周期
Docker 卷的生命周期包括以下几个关键阶段:
-
创建
使用docker volume create
命令创建一个新的 Docker 卷。例如,创建名为test_volume
的卷:docker volume create test_volume
这会在 Docker 引擎的存储位置(如
/var/lib/docker/volumes/
)下创建一个新的卷。 -
挂载与使用
卷创建后,可以在容器中挂载并使用。例如,通过以下命令将test_volume
卷挂载到容器的/usr/share/nginx/html
目录:docker container run --name nginx1 -d -p 8080:80 -v test_volume:/usr/share/nginx/html nginx:1.24.0
这样,卷
test_volume
就会与容器共享数据,并能够被容器中的应用程序访问。 -
数据读写
在容器中对挂载的卷进行数据的读写操作,任何对卷中文件的修改都会实时反映到容器内的挂载位置。如果使用:ro
(只读)选项挂载卷,容器内的进程将无法修改卷中的数据,但宿主机仍然可以进行修改。 -
删除卷
当不再需要卷时,可以使用docker volume rm
命令删除卷:docker volume rm test_volume
删除卷时,如果卷仍被某个容器使用,则无法删除,需先停止并删除相关容器。
-
自动清理
Docker 也提供了自动清理未使用卷的功能,通过以下命令删除所有未使用的卷:docker volume prune
Docker 卷共享
Docker 卷共享允许多个容器共享同一个卷中的数据。这对于不同容器之间的数据共享和持久化存储非常有用。
-
共享卷的创建
为了共享数据,可以在多个容器中使用同一个卷。例如,创建一个名为shared_volume
的卷:docker volume create shared_volume
-
挂载到多个容器
可以将同一个卷挂载到多个容器中,从而共享数据。例如,将shared_volume
同时挂载到两个容器:docker container run --name container1 -d -v shared_volume:/usr/share/nginx/html nginx:1.24.0 docker container run --name container2 -d -v shared_volume:/usr/share/nginx/html nginx:1.24.0
这两个容器都将访问到
shared_volume
卷中的数据,因此它们的数据会同步共享。 -
数据同步
如果容器中有应用程序修改了共享卷中的数据,这些更改会立即反映到所有使用该卷的容器中。例如,如果container1
修改了shared_volume
中的文件,container2
也能看到该文件的更改,因为它们都共享同一个卷。 -
共享卷的用途
- 日志共享:多个容器可以共享卷来写入日志文件,便于集中管理。
- 持久化存储:某些容器需要保存数据,例如数据库容器,可以将数据存储在卷中,以便容器重启后仍能保持数据。
六、绑定卷 bind mount
-v
和 -mount
都可以完成绑定卷的创建
创建卷
使用 -v
参数创建卷
功能:完成卷的映射。
语法:
docker run -v <宿主机目录>:<容器目录>[:options] ...
参数说明:
- 第一个参数:宿主机目录(与管理卷不同)。
- 第二个参数:卷映射到容器的目录。
- 第三个参数(可选):挂载选项,例如
ro
表示只读模式。
示例:
docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app \
nginx:latest
使用 --mount
参数创建绑定卷
功能:完成目录映射。
语法:
docker run --mount '<key>=<value>,<key>=<value>' ...
关键参数:
- type:类型,可以是
bind
、volume
或tmpfs
。 - source 或 src:宿主机目录(与管理卷不同)。
- destination、dst 或 target:容器中的文件或目录路径。
- ro 或 readonly:以只读方式挂载。
示例:
docker run -d \
-it \
--name devtest \
--mount type=bind,source="$(pwd)"/target,target=/app \
nginx:latest
结论:
-v
参数用于创建并映射卷,通常用于指定宿主机目录与容器目录之间的关系。--mount
参数提供了更详细的挂载选项,适用于绑定卷等更灵活的场景。
操作案例
使用 --mount
方式创建容器
-
创建 nginx 容器并挂载宿主机目录
使用
--mount
方式创建一个 nginx 容器,并将宿主机的/webapp1
目录挂载到容器的/usr/share/nginx/html
目录。如果宿主机的/webapp1
目录不存在,容器启动时会报错。
docker container run --name nginx_mount -d -p 8080:80 --mount type=bind,source=/data/myworkdir/fs/webapp1,target=/usr/share/nginx/html nginx:1.24.0
创建宿主机目录并启动容器:
root@VM-8-2-ubuntu:/home/ubuntu# mkdir -p /data/myworkdir/fs/webapp1
root@VM-8-2-ubuntu:/home/ubuntu# docker container run --name nginx_mount -d -p 8080:80 --mount type=bind,source=/data/myworkdir/fs/webapp1,target=/usr/share/nginx/html nginx:1.24.0
创建新的宿主机目录并启动另一个容器:
root@VM-8-2-ubuntu:/home/ubuntu# mkdir -p /data/myworkdir/fs/webapp1_new
root@VM-8-2-ubuntu:/home/ubuntu# docker run -d -p 8081:80 --name bind1 --mount type=bind,source=/data/myworkdir/fs/webapp1_new,target=/usr/share/nginx/html nginx:1.24.0
-
查看挂载信息
使用
docker inspect
查看容器的挂载信息。
root@VM-8-2-ubuntu:/home/ubuntu# docker inspect bind1
[{"Id": "c184c9db30fe849ea7ed5f8cd945bb3e3c51ad55edf6176c3d22d23cc4ead5d9","Created": "2025-03-18T07:20:17.73803812Z","Path": "/docker-entrypoint.sh","Args": ["nginx","-g","daemon off;"],"State": {...
-
进入容器查看挂载目录
进入容器终端,查看挂载点
/usr/share/nginx/html
,并在宿主机上查看挂载目录,发现文件并不存在。
root@VM-8-2-ubuntu:/home/ubuntu# docker exec -it bind1 ls /usr/share/nginx/html
root@VM-8-2-ubuntu:/data/myworkdir/fs# ls
webapp1 webapp1_new
root@VM-8-2-ubuntu:/data/myworkdir/fs# ll webapp1
total 8
drwxr-xr-x 2 root root 4096 Mar 18 15:12 ./
drwxr-xr-x 4 root root 4096 Mar 18 15:20 ../
可以发现容器中的文件已消失,这是 bind mount
和 volume
模式的主要区别。
-
宿主机文件更新,容器实时读取
在宿主机
/webapp1
目录添加index.html
文件,并通过浏览器访问容器,容器成功读取并显示宿主机的文件内容。
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# echo "Hello Bind Mount." >> index.html
通过浏览器访问容器时,可以看到宿主机的文件内容:
-
删除容器后,宿主机文件依然存在
删除容器后,宿主机上的文件保持不变,说明
bind mount
的挂载不受容器生命周期的影响。
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# docker stop bind1
bind1
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# docker rm bind1
bind1
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# ll
total 12
drwxr-xr-x 2 root root 4096 Mar 18 15:32 ./
drwxr-xr-x 4 root root 4096 Mar 18 15:20 ../
-rw-r--r-- 1 root root 18 Mar 18 15:32 index.html
总结:
- 使用
--mount
创建绑定卷时,容器会挂载宿主机的指定目录。 - 容器中的挂载目录会覆盖容器内的原有内容,这是与
volume
模式的主要区别。 - 宿主机文件的变化会立即反映到容器中,且容器删除后,宿主机文件仍然存在。
使用 -v
创建绑定卷
-
使用
-v
方式创建容器创建一个 nginx 容器,并将宿主机的
/webapp2
目录挂载到容器的/usr/share/nginx/html
目录。需要注意的是,如果宿主机的/webapp2
目录不存在,容器启动时不会报错。这是-v
和--mount
方式的区别:-v
会自动创建挂载目录,而--mount
需要宿主机目录存在。
docker run -d -p 8080:80 --name bind2 -v /data/myworkdir/fs/webapp2:/usr/share/nginx/html nginx:1.22.1
-
查看挂载信息
使用
docker inspect
命令查看容器的挂载信息。
root@VM-8-2-ubuntu:/data/myworkdir/fs# docker inspect bind2
[{"Id": "b9631fa3b8a122012d2c876ffdd5826d80dbdb9336b967017d96061f98e5434a","Created": "2025-03-18T10:20:52.43803812Z","Mounts": [{"Type": "bind","Source": "/data/myworkdir/fs/webapp2","Destination": "/usr/share/nginx/html","Mode": "","RW": true,"Propagation": "rprivate"}],...}
]
-
进入容器终端查看挂载点
进入容器终端,查看
/usr/share/nginx/html
目录,发现容器中的文件为空。同样,在宿主机上查看/webapp2
目录,也没有文件。这是bind mount
模式和volume
模式的区别:容器内原有文件会被挂载目录的内容覆盖。
root@VM-8-2-ubuntu:/data/myworkdir/fs# docker exec -it bind2 ls /usr/share/nginx/html
root@VM-8-2-ubuntu:/data/myworkdir/fs# ll webapp2
total 8
drwxr-xr-x 2 root root 4096 Mar 18 15:20 ./
drwxr-xr-x 4 root root 4096 Mar 18 15:20 ../
-
在宿主机添加
index.html
文件在宿主机
/webapp2
目录下创建一个index.html
文件,并写入内容。
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp2# echo "Hello Bind Mount in bind2" > index.html
-
通过浏览器访问
通过浏览器访问容器时,能够看到容器已经读取并显示了宿主机的共享内容。
-
删除容器后,宿主机文件依然存在
删除容器后,宿主机上的文件仍然存在,证明容器删除并不影响
bind mount
映射。
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp2# docker stop bind2
bind2
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp2# docker rm bind2
bind2
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp2# ll
total 12
drwxr-xr-x 2 root root 4096 Mar 18 15:32 ./
drwxr-xr-x 4 root root 4096 Mar 18 15:20 ../
-rw-r--r-- 1 root root 21 Mar 18 15:32 index.html
总结:
- 使用
-v
创建绑定卷时,如果宿主机目录不存在,容器启动时不会报错。 - 容器内的挂载目录内容会被宿主机目录内容覆盖,这是
bind mount
模式与volume
模式的主要区别。 - 宿主机文件的变化会实时反映到容器中,且容器删除后,宿主机的文件依然存在,
bind mount
映射不会受到容器生命周期的影响。
绑定卷共享
- 启动两个绑定卷,绑定到宿主机的同一个目录:
ubuntu@VM-8-2-ubuntu:~$ docker run -d -p 8082:80 --name bind3 -v /data/myworkdir/fs/webapp1:/usr/share/nginx/html nginx:1.24.0
7e23e9cf779c21fa4c1cf1982953c79c13564876cd2bfce60fe1fefddb2d1ef5
ubuntu@VM-8-2-ubuntu:~$ docker run -d -p 8083:80 --name bind4 -v /data/myworkdir/fs/webapp1:/usr/share/nginx/html nginx:1.24.0
0794b4c804ca3ab938a5023756c59e515047821eaead81b69774a883e27b17a8
- 访问这两个页面可以查到相同的内容:
ubuntu@VM-8-2-ubuntu:~$ curl 127.0.0.1:8082
Hello Bind Mount.
ubuntu@VM-8-2-ubuntu:~$ curl 127.0.0.1:8083
Hello Bind Mount.
- 修改 index.html 后,再次访问两界面,可以发现 其index.html 都进行了修改,即实现了容器间的共享:
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# echo "changed bind mount" > index.html
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# curl 127.0.0.1:8082
changed bind mount
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# curl 127.0.0.1:8083
changed bind mount
- 最后不要忘记清理资源
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# docker stop bind2
bind2
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# docker stop bind3
bind3
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# docker rm bind2
bind2
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# docker rm bind3
bind3
七、临时卷 tmpfs
tmpfs
临时卷是位于内存中的卷,存储在容器和宿主机的外部。
tmpfs
的局限性:
- 与卷和绑定挂载不同,
tmpfs
挂载不能在多个容器之间共享。 - 仅在 Linux 系统上运行 Docker 时支持此功能。
创建临时卷
方式一:使用 --tmpfs
参数创建
- 功能:将临时卷挂载到容器指定目录。
- 语法:
--tmpfs /app
- 示例:
docker run -d \-it \--name tmptest \--tmpfs /app \nginx:1.22.1
方式二:使用 --mount
参数创建
- 功能:完成目录的临时卷映射。
- 语法:
--mount '<key>=<value>,<key>=<value>'
-
关键参数:
type
:指定挂载类型,支持bind
、volume
或tmpfs
。destination
、dst
、target
:容器中挂载的目标路径。tmpfs-size
:指定tmpfs
挂载的大小(以字节为单位),默认没有限制。tmpfs-mode
:指定tmpfs
的文件模式(以八进制表示),例如700
或0770
,默认1777
,全局可写。
-
示例:
docker run -d \-it \--name tmptest \--mount type=tmpfs,destination=/app \nginx:latest
总结:
tmpfs
提供了一个高效的内存存储方式,适用于不需要持久化存储的临时数据。- 使用
--tmpfs
或--mount
都可以创建临时卷,选择方式依据需求而定。
操作案例
tmpfs
参数创建临时卷
- 创建临时卷并启动容器
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# docker container run --name tmpfs1 -d -p 8080:80 --tmpfs /usr/share/nginx/html nginx:1.24.0
a350249d8cf5efce441dac30059c8313aef9b6426ad4b8c9bb55a588a704f41a
- 进入容器可以发现 nginx 中的文件被覆盖了,即 tmpfs 会覆盖容器里的文件
root@VM-8-2-ubuntu:/data/myworkdir/fs/webapp1# docker exec -it tmpfs1 bash
root@a350249d8cf5:/# cd /usr/share/nginx/html/
root@a350249d8cf5:/usr/share/nginx/html# ls -l
total 0
- 添加首页并进行访问:
root@a350249d8cf5:/usr/share/nginx/html# echo "Hello docker from tmpfs" > index.html
root@a350249d8cf5:/usr/share/nginx/html# curl 127.0.0.1 :8080
Hello docker from tmpfs
- 停止容器并再次启动,进行查询后会发现tmpfs的内容完全消失了,即 tmpfs 的内容是存在内存中的:
root@VM-8-2-ubuntu:# docker stop tmpfs1
tmpfs1
root@VM-8-2-ubuntu:# docker start tmpfs1
tmpfs1
root@VM-8-2-ubuntu:# docker exec -it tmpfs1 bash
root@a350249d8cf5:/# ls -l /usr/share/nginx/html/
total 0
- 清理资源:
root@VM-8-2-ubuntu:/# docker stop tmpfs1
tmpfs1
root@VM-8-2-ubuntu:/# docker rm tmpfs1
tmpfs1
mount
创建临时卷
- 创建临时卷并启动容器
ubuntu@VM-8-2-ubuntu:~$ docker container run --name mtpfs1 -d -p 8080:80 --mount type=tmpfs,destination=/usr/share/nginx/html,tmpfs-size=1m nginx:1.24.0
817957a8e4bf52736f3e854efb3601a4b04f09be6d5247cff617ae6e14680d8e
- 进入容器可以发现nginx的内容被覆盖了,即
tmpfs
会覆盖容器
ubuntu@VM-8-2-ubuntu:~$ docker exec -it mtpfs1 bash
root@817957a8e4bf:/# ls
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib media opt root sbin sys usr
root@817957a8e4bf:/# ls -l /usr/share/nginx/html
total 0
- 添加首页并进行访问:
root@817957a8e4bf:/usr/share/nginx/html# echo "hello mount from tmpfs" > index.html
root@817957a8e4bf:/usr/share/nginx/html# curl 127.0.0.1
hello mount from tmpfs
- 剩下的步骤和 tmpfs 创建临时卷一样,就不再赘述了
tmpfs
失踪
- 创建一个普通的
docker
容器
ubuntu@VM-8-2-ubuntu:~$ docker run -d -it --name tmptest nginx:1.24.0
d4bb0cce7be8705d6e97d41e946b9c9e7d737416f6c8ff149e2d989f79ea7c2f
- 运行容器并写入文件:
ubuntu@VM-8-2-ubuntu:~$ docker exec -it tmptest bash
root@d4bb0cce7be8:/# mkdir -p /app
root@d4bb0cce7be8:/# echo 114 > /app/mylabel.txt
root@d4bb0cce7be8:/# exit
exit
- 在宿主机查找文件,是可以找到的,因为文件在容器的可写层
ubuntu@VM-8-2-ubuntu:~$ sudo find / -name mylabel.txt
/var/lib/docker/overlay2/c3cdefc3d23aa496e133c7a352028bcad779c1eebfa0f01e13097ae942bb24a7/merged/app/mylabel.txt
/var/lib/docker/overlay2/c3cdefc3d23aa496e133c7a352028bcad779c1eebfa0f01e13097ae942bb24a7/diff/app/mylabel.txt
- 创建一个临时卷并启动,
ubuntu@VM-8-2-ubuntu:~$ docker run -d --name tmptest2 --tmpfs /app nginx:1.24.0
10ce055a39d480fcdc00f00947c3eab4f981057021e61d9d8bfefe13bf59b4bc
ubuntu@VM-8-2-ubuntu:~$ docker exec -it tmptest2 bash
- 进入容器在 /app 目录下创建新文件 mynewlabel.txt
root@10ce055a39d4:/# ls app
root@10ce055a39d4:/# echo 514 > /app/mynewlabl.txt
root@10ce055a39d4:/# ls /app
mynewlabl.txt
root@10ce055a39d4:/# exit
exit
- 返回宿主机并查询 mynewlabel.txt ,发现找不到文件
ubuntu@VM-8-2-ubuntu:~$ sudo find / -name mynewlabel.txt
ubuntu@VM-8-2-ubuntu:~$
- 所以 tmpfs 的内容不是存储在容器的可写层里面的,最后释放容器
ubuntu@VM-8-2-ubuntu:~$ docker stop tmptest
tmptest
ubuntu@VM-8-2-ubuntu:~$ docker rm tmptest
tmptest
ubuntu@VM-8-2-ubuntu:~$ docker stop tmptest2
tmptest2
ubuntu@VM-8-2-ubuntu:~$ docker rm tmptest2
tmptest2
八、实战练习:Mysql 灾难恢复
练习目标:
本次练习旨在掌握挂载卷的使用,将 MySQL 的业务数据存储到外部。
操作步骤:
-
准备镜像
首先,我们拉取mysql:5.7
镜像。ubuntu@VM-8-2-ubuntu:~$ docker pull mysql:5.7 Using default tag: latest latest: Pulling from library/mysql 7b36eddb0393: Pull complete 9d96cf4d7877: Pull complete c06a2d8bb529: Pull complete 7d30ccf68828: Pull complete 169c64bfa9b4: Pull complete 03f81c404364: Pull complete Digest: sha256:0b536be69f66e91e56ac8dbf45d5f55e8f393c19c22c6747e1ac9f4fbd37c2e0 Status: Downloaded newer image for mysql:5.7
-
创建容器并挂载卷
创建一个名为mysql_demo
的容器,设置 MySQL 密码并将数据卷挂载到/data/myworkdir/mysql-data
目录。ubuntu@VM-8-2-ubuntu:~$ docker container run --name mysql_demo -e MYSQL_ROOT_PASSWORD=114514 -itd -v /data/myworkdir/mysql-data:/var/lib/mysql mysql:5.7
解释:
-e MYSQL_ROOT_PASSWORD=114514
:设置 MySQL 根用户密码为114514
。-v /data/myworkdir/mysql-data:/var/lib/mysql
:将宿主机的/data/myworkdir/mysql-data
目录挂载到容器的/var/lib/mysql
,保存数据库数据。
-
查看容器挂载信息
使用docker container inspect
命令查看容器的挂载信息。ubuntu@VM-8-2-ubuntu:~$ docker container inspect mysql_demo | grep "Mounts" -A 20 "Mounts": [{"Type": "volume","Name": "mysql-demo-mysql-data","Source": "/data/myworkdir/mysql-data","Destination": "/var/lib/mysql","Mode": "rw","RW": true,"Propagation": "rprivate"} ]
-
连接 MySQL 创建数据库和表
连接到容器并进入 MySQL Shell,使用之前设置的密码114514
。ubuntu@VM-8-2-ubuntu:~$ docker container exec -it mysql_demo /bin/bash root@mysql_demo:/# mysql -u root -p Enter password: 114514 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.7.34 MySQL Community Server (GPL)
创建
user
数据库和student
表,并插入一些数据。mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec)mysql> create database user; Query OK, 1 row affected (0.01 sec)mysql> use user; Database changedmysql> create table student(sno char(3), sname varchar(20)); Query OK, 0 rows affected (0.01 sec)mysql> insert into student values('1', '田所'),('2', '德川'); Query OK, 2 rows affected (0.01 sec)mysql> select * from student; +-----+--------+ | sno | sname | +-----+--------+ | 1 | 田所 | | 2 | 德川 | +-----+--------+ 2 rows in set (0.00 sec)mysql> exit Bye
在上述步骤中,我们创建了一个
user
数据库,在其中创建了student
表,并插入了两条数据。 -
查看宿主机上的数据卷内容
查看挂载到宿主机的mysql-data
目录,验证数据是否被持久化。ubuntu@VM-8-2-ubuntu:~$ ll /data/myworkdir/mysql-data/ total 96 drwxr-xr-x 6 root root 4096 Mar 23 10:00 . drwxr-xr-x 3 root root 4096 Mar 23 09:50 .. drwxr-xr-x 2 root root 4096 Mar 23 10:00 3306 drwxr-xr-x 2 root root 4096 Mar 23 10:00 lost+found -rw-r----- 1 root root 368 Mar 23 10:00 ib_logfile0 -rw-r----- 1 root root 368 Mar 23 10:00 ib_logfile1
-
删除容器
删除容器mysql_demo
,此时 MySQL 数据也会随容器一起清除。ubuntu@VM-8-2-ubuntu:~$ docker stop mysql_demo mysql_demo ubuntu@VM-8-2-ubuntu:~$ docker rm mysql_demo mysql_demo
-
恢复数据
通过再次运行容器并挂载相同的数据卷,数据可以恢复。ubuntu@VM-8-2-ubuntu:~$ docker container run --name mysql_demo_new -e MYSQL_ROOT_PASSWORD=114514 -itd -v /data/myworkdir/mysql-data:/var/lib/mysql mysql:5.7
-
重新连接 MySQL 查看数据
登录 MySQL,查看数据是否恢复。ubuntu@VM-8-2-ubuntu:~$ docker exec -it mysql_demo_new mysql -u root -p Enter password: 114514 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.7.34 MySQL Community Server (GPL)mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | user | +--------------------+ 5 rows in set (0.00 sec)mysql> use user; Database changedmysql> show tables; +-----------------+ | Tables_in_user | +-----------------+ | student | +-----------------+ 1 row in set (0.00 sec)mysql> select * from student; +-----+--------+ | sno | sname | +-----+--------+ | 1 | 田所 | | 2 | 德川 | +-----+--------+ 2 rows in set (0.00 sec)mysql> exit Bye
数据成功恢复,
student
表中的数据仍然存在。 -
释放空间
删除新的容器以释放资源。ubuntu@VM-8-2-ubuntu:~$ docker stop mysql_demo_new mysql_demo_new ubuntu@VM-8-2-ubuntu:~$ docker rm mysql_demo_new mysql_demo_new
九、关于 Volume 的一些问题
什么时候使用 Volume、Bind/Mount 和 tmpfs?
-
Volume
Volume 是 Docker 容器与宿主机之间独立的存储区域,它位于宿主机的文件系统中。使用 Volume 时,Docker 会自动管理存储位置,不需要用户指定具体目录,适合不需要提前规划目录结构的场景。通常用于持久化容器数据,如数据库存储、日志文件等。 -
Bind Mount
Bind Mount 完全依赖于宿主机的目录结构和操作系统。它将宿主机的指定目录直接挂载到容器中,因此需要提前规划好宿主机上的目录。适用于需要容器与宿主机之间共享数据,或需要直接访问宿主机文件系统的场景。例如,开发环境中容器需要访问主机代码目录,或者需要挂载特定配置文件时,使用 Bind Mount 是一个合适的选择。 -
tmpfs
tmpfs 是一种将数据存储在内存中的临时存储方式,适用于不希望数据持久化到宿主机或容器可写层中的场景。使用 tmpfs 时,数据仅存在于容器生命周期内,当容器停止或删除时,数据会丢失。它适用于敏感数据存储、临时缓存等,不需要长期保存的数据。
存储卷在实际研发中的问题
-
跨主机使用问题
Docker 存储卷依赖于宿主机的本地文件系统,每个宿主机上的存储卷只能在该主机上使用,无法跨主机共享。
因此,当容器停止或删除后,虽然可以重新创建,但无法调度到其他主机。这是 Docker 默认存储卷的一个局限性。
为了实现跨主机的存储共享,通常需要搭建共享存储(如 NFS),但这种解决方案对运维人员的能力有较高要求。为了解决存储和数据的分离问题,越来越多的分布式存储方案(如 S3、NFS 等)应运而生。 -
启动参数管理
容器的启动选项相较于传统进程启动更加复杂,且容器在重启时常常无法记住上次启动时的参数。
为了确保容器能够以相同的配置启动,通常需要将启动参数保存在配置文件中。这正是容器编排工具(如 Kubernetes)发挥作用的地方。
虽然可以通过命令启动容器,并在文件中读取相关参数,但这种方式仅适用于单个容器的管理。对于需要管理几十或上百个容器的复杂应用,使用专业的容器编排工具(如 Kubernetes 或各大云厂商的企业版编排软件)是必不可少的。 -
复杂场景依赖运维经验
对于有状态且需要持久化的集群化组件(如 MySQL 主从复制),其部署和维护往往需要丰富的运维知识和经验。
例如,在部署、扩展、缩容或修复故障时,必须清楚集群规模、主从节点数量以及每个节点的具体配置。
这种复杂场景的管理对运维人员提出了高要求,目前还没有完美的自动化工具能够完全替代人工干预。因此,在这些复杂场景中,运维经验仍然至关重要。
相关文章:
【Docker基础】深入解析 Docker 存储卷:管理、绑定与实战应用
文章目录 一、什么是存储卷二、为什么需要存储卷三、存储卷分类四、管理卷 Volume方式一:Volume 命令操作方式二:使用 -v 或 --mount 参数指定卷方式三:Dockerfile 匿名卷 五、操作案例Docker 命令创建管理卷Docker -v 创建管理卷Docker 卷生…...
Python生成exe
其中的 -w 参数是 PyInstaller 用于窗口模式(Windowed mode),它会关闭命令行窗口的输出,这通常用于 图形界面程序(GUI),比如使用 PyQt6, Tkinter, PySide6 等。 所以: 如果你在没有…...
SpringBoot原理
配置优先级 SpringBoot项目当中支持的三类配置文件: 在SpringBoot项目当中,我们要想配置一个属性,可以通过这三种方式当中的任意一种来配置都可以,那么如果项目中同时存在这三种配置文件,且都配置了同一个属性&#x…...
Google 官方提示工程 (Prompt Engineering)白皮书 总结
《大语言模型的提示工程:从基础到最佳实践》 总结 本文围绕大语言模型的提示工程展开,介绍其是设计高质量提示引导 LLM 产生准确输出的过程。探讨了 LLM 输出配置如输出长度、温度、top-K 和 top-P 等设置及其相互影响,阐述了零样本、少样本…...
Python——numpy测试题目
题目: 生成一个2行3列随机整数二维数组a使用Numpy方法对(1)中数组a进行整体求积使用Numpy方法对(1)中数组a进行求每列最大值索引定义一个NumPy一维数组 b,元素为 1 到 10 的整数获取(4&#x…...
【SLAM】将realsense-viewer录制的rosbag视频导出成图片序列(RealSense D435)
本文介绍了如何将realsense-viewer录制的rosbag格式的视频导出成图片序列,方便合并成mp4视频或插入到论文中。 本文首发于❄慕雪的寒舍 说明 Intel提供的realsense-viewer软件录制的视频都是rosbag格式的,为了编写论文,需要从录制的视频中截…...
Unity6国际版下载
Unity6国际版下载下载地址 Hub下载地址:https://www.nounitycn.top/unityhub 先下载unity6启动器(下载速度很快),在去下载unity6000版本(下载速度慢) 下载速度很慢的话,有条件可以找梯子科学上网…...
2025认证杯挑战赛B题【 谣言在社交网络上的传播 】原创论文讲解(含完整python代码)
大家好呀,从发布赛题一直到现在,总算完成了认证杯数学中国数学建模网络挑战赛第一阶段B题目谣言在社交网络上的传播完整的成品论文。 给大家看一下目录吧: 目录 摘 要: 一、问题重述 二. 问题分析 2.1问题一 2.…...
后台进程管理之pstree 和 job
1. pstree 命令 功能 以树状结构显示进程间的父子关系,直观展示进程的层次结构。 常用选项 选项说明-p显示进程 PID-a显示完整命令行(包括参数)-u显示进程所属用户-n按 PID 排序(默认按进程名)-h高亮当前进程及其祖…...
波束形成(BF)从算法仿真到工程源码实现-第三节-延迟求和波束形成(DSB)
一、概述 本节我们讨论延迟求和波束形成算法,包括原理分析及代码实现。 更多资料和代码可以进入 https://t.zsxq.com/qgmoN ,同时欢迎大家提出宝贵的建议,以共同探讨学习。 二、原理分析 2.1 原理: 首先对不同麦克风信号之间的相…...
deepseek使用记录——拉美文学的且战且败和且败且战
一 拉美文学,且战且败,且败且战,有哪些比较深刻的文学作品,对当下的年轻人有何启示。 拉丁美洲文学以其对历史、政治、社会现实的深刻反思和独特的魔幻现实主义风格闻名于世。这些作品既记录了拉美大陆在殖民、独裁、全球化浪潮中…...
LeetCode 解题思路 37(Hot 100)
解题思路: 初始化: 初始化最大举行 max 和栈 stack。左右补零: 考虑柱子递增的边界情况, 初始化填充柱状图 newHeights。遍历处理: 对于每一根遍历到的柱子 newHeights[i],若柱子高度小于栈口索引…...
lvs+keepalived+dns高可用
1.配置dns相关服务 1.1修改ip地址主机名 dns-master: hostnamectl hostname lvs-master nmcli c modify ens160 ipv4.method manual ipv4.addresses 10.10.10.107/24 ipv4.gateway 10.10.10.2 ipv4.dns 223.5.5.5 connection.autoconnect yes nmcli c up ens160dns-salve: h…...
计算齿轮故障频率|平行轴|行星轮齿轮
一、平行轴齿轮故障频率 关键参数定义 Z:齿轮齿数 fs:轴旋转频率(Hz) N:啮合齿轮齿数(配对齿轮) 特征频率公式 软件页面截图 二、行星齿轮故障频率 系统组成参数 太阳轮齿数 齿圈齿数 …...
【技术派部署篇】云服务器部署技术派
1 环境搭建 1.1 JDK安装 # ubuntu sudo apt update # 更新apt apt install openjdk-8-jdk # 安装JDK安装完毕之后,执行 java -version 命令进行验证: 1.2 Maven安装 cd ~ mkdir soft cd soft wget https://dlcdn.apache.org/maven/maven-3/3.8.8/bina…...
Rasa中endpoints.yml文件信息详细解释
endpoints.yml 是 Rasa 项目中用于配置各类服务接口(endpoints)的文件,它告诉 Rasa: 去哪里加载模型自定义动作在哪个服务运行对话历史存储在哪(tracker store)是否要把事件推送到某个消息队列中ÿ…...
AI代理是大模型实现可扩展智能自动化的关键
AI 代理框架:实现可扩展智能自动化的关键 https://www.lyzr.ai/ 每个人都在谈论 AI 代理,例如 Sam Altman、Satya Nadella、Andrew Ng 和 Sundar Pichai 等行业领袖。 但这究竟是为什么呢? 因为这就是当今软件发展的方向,也是企…...
android中dp和px的关系
关于android的dp和px的关系是我刚开始学习android的第一个知识点,不知不觉学安卓也有一年了,但是偶然间我发现我理解的dp和px的关系一直是错的,真的是有一点搞笑,今天特意写一篇博客纪念一下这个我理解错一年的知识点。 dp和px之间…...
day32-动态规划__509. 斐波那契数__70. 爬楼梯__746. 使用最小花费爬楼梯
动态规划,一直是各种算法竞赛中难度较大的题目。在同学接触到动态规划的题目时,对于简单的动态规划问题,同学们常常轻易通过,而对于复杂的动态规划,却没有一个很好的思路,那么我们究竟有没有一种统一的思考…...
【Code】《代码整洁之道》笔记-Chapter12-迭进
第12章 迭进 12.1 通过迭进设计达到整洁目的 假使有4条简单的规则,跟着做就能帮助你创建优良的设计,会如何?假使遵循这些规则,你就能洞见代码的结构和设计,更能轻易地应用SRP和DIP之类的原则,便会如何&…...
Odoo 部署本地 把現時的excel計算表格部署上odoo 教程
要将现有的 Excel 计算表格部署到 Odoo 平台上,您可以按照以下步骤进行操作: 将 Excel 表格中的数据转移到 Odoo 模块中:首先,您需要将 Excel 表格中的数据导出为 CSV 格式,然后可以使用 Odoo 的数据导入功能将这些数据…...
【C语言-全局变量】
【C语言-全局变量】 1.能局部就局部,别啥都往全局塞2.尽量用结构体对零散变量封装3.函数传参4.静态变量模块化5 单例模式, 限制全局实例数量6. 配置化全局参数——集中管理可调参数7. 事件驱动架构:消息队列通信策略选择建议 参考https://mp.weixin.qq.c…...
Downlink Sensing in 5G-Advanced and 6G: SIB1-assisted SSB Approach
摘要——本文研究了利用现有5G NR信号进行网络侧集成感知与通信(ISAC)的潜力。通常,由于其频繁的周期性可用性和波束扫描特性,同步信号块(SSB)是适合用于下行感知的候选信号。然而,正如本文所示…...
PCIe 5.0光学SSD原型问世!
近日,Kioxia Corporation(铠侠)、AIO Core Co., Ltd. 和 Kyocera Corporation(京瓷)联合宣布成功开发了一款支持 PCIe 5.0 接口的光学 SSD 原型。该技术旨在通过光接口替换传统的电接口,从而显著增加计算设…...
JDK(Java Development Kit)从发布至今所有主要版本 的详细差异、新增特性及关键更新的总结,按时间顺序排列
以下是 JDK(Java Development Kit)从发布至今所有主要版本 的详细差异、新增特性及关键更新的总结,按时间顺序排列: 1. JDK 1.0 (1996) 发布年份:1996年1月23日关键特性: Java首次正式发布。核心语言特性…...
【3分钟准备前端面试】yarn
目录 Yarn核心概念核心机制解析工作流与命令详解高级功能剖析性能优化策略常见问题解决方案Yarn与...
[16届蓝桥杯 2025 c++省 B] 移动距离
思路:这题很多人肯定一眼就觉得是直线,因为无限方案,怎么走随便你,极限状态会误以为是直线,实际上你会发现,只有往右走是直线,往上走时一个弧线操作,就算你一下往右,一下…...
二叉树(中)-- 堆
堆是一个独立的数据结构,堆是一个二叉树。堆和栈几乎没有什么关联 堆是一个完全二叉树,可以用数组存储 大堆: 任何一个父亲都大于等于孩子小堆: 任何一个父亲都小于等于孩子 请注意,小堆大堆并不一定是升序或降序&…...
艾伦·图灵:计算机科学与人工智能之父
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 艾伦图灵:计算机科学与人工智能之父 一、天才的诞生与早期生涯 1912年6月…...
Doris 安装部署、实际应用及优化实践:对比 ClickHouse 的深度解析
在实时分析、报表系统以及高并发 OLAP 查询等场景中,列式存储数据库因其卓越的查询性能逐渐成为主流。Doris 和 ClickHouse 是近年来最受欢迎的两款开源 OLAP 引擎,本文将系统介绍 Doris 的安装部署、应用场景及优化实践,并与 ClickHouse 做一…...
Vue的学习总结-day02
一、Vue的基本语法 1、Vue.js 使用双大括号 {{ }} 来表示文本插值: <template><div class"demo">{{msg}}</div> </template> 2、指令 v-bind:动态绑定一个或多个特性,或一个组件 prop。 <template…...
MySQL 中查询 VARCHAR 类型 JSON 数据的
在数据库设计中,有时我们会将 JSON 数据存储在 VARCHAR 或 TEXT 类型字段中。这种方式虽然灵活,但在查询时需要特别注意。本文将详细介绍如何在 MySQL 中有效查询存储为 VARCHAR 类型的 JSON 数据。 一、问题背景 当 JSON 数据存储在 VARCHAR 列中时&a…...
Spring Boot 的启动流程
Spring Boot 是一个用于简化 Spring 应用程序开发的框架,它通过自动配置和约定优于配置的原则,大大降低了开发者的工作量。下面我们将深入探讨 Spring Boot 的启动流程,帮助你理解其背后的工作机制。 1. 启动入口 Spring Boot 应用的启动入…...
JMeter的接口测试步骤
创建测试计划 新建测试计划: 打开 JMeter,右键点击 Test Plan,选择 Add -> Threads (Users) -> Thread Group。双击 Thread Group,设置线程数(用户数)、循环次数等参数。 添加取样器(S…...
Linux基础14
一、搭建LAMP平台 安装包:mariadb-server、php、php-mysqlnd、php-xml、php-json 搭建平台步骤: php步骤: 创建网页:index.php 网页内编写php语言: > eg:<?p…...
七种数码管驱动/LED驱动综合对比——《器件手册--数码管驱动/LED驱动》
十四、数码管驱动/LED驱动 名称 工作原理 应用场景 优缺点 特点 LED驱动 LED驱动的核心是为发光二极管提供稳定的电流。LED的亮度与电流成正比,而其正向电压相对稳定。驱动电路需要根据电源电压和LED的正向电压,通过限流电阻或恒流芯片来控制电流。…...
【25软考网工笔记】第二章 数据通信基础(2) 信道延迟计算
目录 一、信道延迟 1. 线路延迟 1)线路延迟与传输距离的关系 2)光纤线路与电缆线路的传播速度 3)线路延迟计算示例:1000米电缆的延迟 2. 发送延迟 1)发送延迟的定义与计算 2)发送延迟的影响因素 3.…...
代码随想录第16天:(二叉树)
一、最大二叉树(Leetcode 654) class Solution:def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode:# 基础条件:当数组只有一个元素时,直接返回该元素构建的二叉树节点if len(nums) 1:return TreeNode(nums[…...
Android activity属性taskAffinity的作用
1. taskAffinity的基本概念 在Android开发中,taskAffinity是一个定义在标签中的属性,用于指定Activity与哪个任务(Task)相关联。默认情况下,应用的所有Activity都共享同一个任务堆栈,其taskAffinity值为应…...
Vuex Actions 多参数传递的解决方案及介绍
Vuex Actions 多参数传递的解决方案及介绍 引言 在Vuex状态管理模式中,Actions 扮演着至关重要的角色。它主要用于处理异步操作,并且可以提交 Mutations 来修改全局状态。然而,在实际开发中,我们常常会遇到需要向 Actions 传递多…...
SQL学习--基础语法学习
SQL和excle对比 学习目标 单表查询 项目背景 SQL 练习环境 SQL Online Compiler - Next gen SQL Editor 商品信息表:https://study-zhibo.oss-cn-shanghai.aliyuncs.com/test/%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF%E8%A1%A8.csv 订单明细表:https://…...
ProfibusDP转ModbusTCP接流量计技巧
ProfibusDP转ModbusTCP接流量计技巧 在现代工业自动化系统中,设备的互联互通至关重要。为了实现不同协议设备之间的数据交换与统一管理,Profibus DP主站转Modbus TCP网关成为了一个重要的解决方案。本文将详细介绍这一转换方案及其在电磁流量计中的应用…...
【数据结构与算法】ArrayList 和 顺序表
文章目录 🌲List🌲1. 线性表🌲2. 顺序表🌿2.1 MyArrayList2.1.1 类中重写所有接口方法1.新增元素2.在pos位置新增元素(指定位置)3.判定是否包含了某个特定元素 4.查找特定元素对应的位置 5.获取pos下标的元素 6.给pos位置的元素替…...
VMware Fusion Pro/Player 在 macOS 上的完整安装与使用指南
VMware Fusion Pro/Player 在 macOS 上的完整安装与使用指南—目录 一、VMware 产品说明二、下载 VMware Fusion三、安装前准备四、安装 VMware Fusion步骤 1:安装程序步骤 2:首次启动配置步骤 3:输入许可证 五、创建虚拟机步骤 1:…...
GESP2025年3月认证C++七级( 第三部分编程题(1)图上移动)
参考程序(动态规划) #include <cstdio> using namespace std; const int K 25; // 最大步数 多开一点 const int N 505; // 最大结点数 const int E N << 1; // 最多边数(因为是无向图,每条边…...
将LINUX系统本机文件上传到LINUX虚拟机,未联网的情况下
将LINUX系统本机文件上传到LINUX虚拟机,未联网的情况下 1.将需要上传的文件,归档为.iso镜像文件 命令:mkisofs -r -o myiso.iso /iso/tool 2.打开虚拟机,选择需要挂载的光盘 3.创建挂载点,一般在/mnt目录下 mkdir /mnt/tool 4.临时挂载镜像 mount /dev/cdrom /mnt/tool 5.需要…...
Selenium之Actions事件
鼠标、键盘组合键 在使用selenium的时候,有的时候我们需要鼠标单击、双击、拖动;或者是按下键盘的某个键,松开某个按键,以及组合键的使用;今天我们就来看一看,怎么样实现上面的操作 先把准备工作做好&…...
高等数学同步测试卷 同济7版 试卷部分 上 做题记录 第三章微分中值定理与导数的应用同步测试卷 A 卷
第三章微分中值定理与导数的应用同步测试卷 A 卷 一、单项选择题(本大题共5小题,每小题3分,总计15分) 1. 2. 3. 4. 5. 二、填空题(本大题共5小题,每小题3分,总计15分) 6. 7. 8. 9. 10. 三、求解下列各题(本大题共5小题,每小题6分,总计…...
使用Vscode排除一些子文件搜索
打开用户/工作区设置 全局生效:打开命令面板(CtrlShiftP 或 CmdShiftP),搜索并选择 Preferences: Open User Settings (JSON)。 仅当前项目生效:在项目根目录下创建 .vscode/settings.json 文件(如果不存在…...
《前端面试题之 CSS篇(第一集)》
目录 1、CSS的盒模型2、CSS选择器及其优先级3、隐藏元素的方法有那些4、px、em、rem的区别及使用场景5、重排、重绘有什么区别6、水平垂直居中的实现7、CSS中可继承与不可继承属性有哪些8、Sass、Less 是什么?为什么要使用他们?9、CSS预处理器/后处理器是…...