Docker存储

Docker镜像采用分层构建的设计,这种设计使得镜像结构和容器的创建、共享和分发变得非常高效。每个镜像层被称为一个layer,这些layer存储在/var/lib/docker//目录下,其中storage-driver可以是AUFS、OverlayFS、VFS、Btrfs等。

可以通过docker info命令查看当前使用的存储驱动。通常,Ubuntu系统默认采用AUFS,而CentOS 7.1+系列默认采用OverlayFS。

OverlayFS是一种堆叠文件系统,它依赖并建立在其它的文件系统(例如ext4、xfs等)之上,并不直接参与磁盘空间结构的划分,而是将底层文件系统中不同的目录进行合并,然后向用户呈现,这种技术称为联合挂载。

Linux内核为Docker提供的OverlayFS驱动有两种:overlay和overlay2。overlay2是overlay的改进版,在inode利用率方面更高效。使用overlay2需要满足以下环境需求:

1.Docker版本17.06.02+

2.宿主机文件系统需要是ext4或xfs格式。

data volume

数据卷是 Docker 容器中用于持久化存储数据的特殊目录,它绕过联合文件系统(UFS),提供以下特性:

  • 数据持久化:容器删除后数据仍然保留
  • 数据共享:多个容器可以共享同一数据卷
  • 高性能:直接访问宿主机文件系统
  • 解耦设计:数据与容器生命周期分离
特性 Bind Mounts Docker Managed Volume
存储位置 宿主机任意路径 Docker 管理目录(/var/lib/docker/volumes/)
权限控制 依赖宿主机文件权限 Docker 管理,可设置只读等
可移植性 差(依赖宿主机路径) 好(与宿主机路径无关)
备份和迁移 需要手动处理 使用 docker 命令容易备份
性能 直接使用宿主机文件系统 直接使用宿主机文件系统(但可能经过一层虚拟化)
使用场景 开发环境、配置文件挂载 生产环境、数据持久化

bind mounts是从宿主机映射到容器内,而Docker Managed Volume是从容器映射到目录,二者的结果相同,但概念不同

Bind Mounts

1.在创建容器时使用 -v 参数来指定宿主机目录或文件与容器目录或文件的映射关系。

2.可以多次使用 -v 参数来映射多个目录或文件。

3.注意:目录只能映射到目录,文件只能映射到文件,否则会报错

示例

在docker host中创建一个/html的目录,与容器内/usr/share/nginx/html的目录做映射

[root@docker ~]# mkdir /html
[root@docker ~]# echo test1 > /html/index.html
[root@docker ~]# docker run -itd --name nginx1 -P -v /html:/usr/share/nginx/html nginx:latest 
2863f5bf76a87ed7a0e2259c002a4d7172d44465f92161d310212bbc50f86261
[root@docker ~]# curl http://192.168.100.10:32768
test1

当docker host上的数据发生变化时,容器内映射的数据也会发生变换,但是当容器出故障数据丢失时,docker host上的数据不会发生变化

[root@docker ~]# docker stop nginx1 
nginx1
[root@docker ~]# cat /html/index.html 
test1
[root@docker ~]# curl http://192.168.100.10:32768
curl: (7) Failed connect to 192.168.100.10:32768; Connection refused
[root@docke

当docker host上的数据发生变化时

[root@docker ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS          PORTS                                     NAMES
2863f5bf76a8   nginx:latest   "/docker-entrypoint.…"   4 minutes ago   Up 28 seconds   0.0.0.0:32769->80/tcp, :::32769->80/tcp   nginx1
[root@docker ~]# echo test222 > /html/index.html 
[root@docker ~]# curl http://192.168.100.10:32769
test222

bind mounts还可以指定数据读写权限,默认权限是可读可写,在映射时,可以指定容器内的文件权限只读,无法修改,但只是容器内的文件只读,在docker host上还是能够修改,这样也提高了容器的安全性。

但是bind mounts也有自身的不足之处,使用时需要指定Docker host上的文件或目录为源数据,这样就限制了容器的可移植性,如果需要将容器移植到其他的docker host上,对方没有相应的源数据库,或者路径不同,操作会失败

docker managed volume

与Bind mounts相比,Docker管理的volume在使用时不需要指 定Docker host路径,Docker管理的volume具有以下几个优点:

1、与Bind mounts相比,Docker管理的volume更易于备份或迁移。

2、用户可以使用Docker CLI命令或Docker API管理volume。

3、volume在Linux和Windows容器上均可工作。

4、可以在多个容器之间更安全地共享volume,提供volume加密功能。

示例
[root@docker ~]# docker run -itd --name nginx2 -P -v /usr/share/nginx/html nginx:latest 
a6b1a690aa21c3186c53a18cd90fc77ef3061283cb74ec0f432bc2e3281b9ab0

使用docker inspect查看容器的mounts部分

[root@docker ~]# docker inspect nginx2
"Mounts": [
            {
                "Type": "volume",
                "Name": "f9c94a0b5ad42edec6946c9e91f9df3716322b1010a6639e857aaf9f908291c5",
                "Source": "/var/lib/docker/volumes/f9c94a0b5ad42edec6946c9e91f9df3716322b1010a6639e857aaf9f908291c5/_data",
                "Destination": "/usr/share/nginx/html",

说使用Docker管理的volume,在做映射时,会把容器中的数据映射到Docker host。

[root@docker ~]# cd /var/lib/docker/volumes/f9c94a0b5ad42edec6946c9e91f9df3716322b1010a6639e857aaf9f908291c5/_data
[root@docker _data]# ls
50x.html  index.html

修改数据查看容器内数据是否发生改变

[root@docker _data]# echo test333 > index.html
[root@docker _data]# curl http://192.168.100.10:32770
test333

但是映射的名字太长了,我们可以自己创建volume

使用docker volume ls命令查看

[root@docker _data]# docker volume ls
DRIVER    VOLUME NAME
local     f9c94a0b5ad42edec6946c9e91f9df3716322b1010a6639e857aaf9f908291c5
[root@docker ~]# docker volume create kami
kami
[root@docker ~]# docker volume ls
DRIVER    VOLUME NAME
local     f9c94a0b5ad42edec6946c9e91f9df3716322b1010a6639e857aaf9f908291c5
local     kami
[root@docker ~]# docker run -itd --name nginx3 -P -v kami:/usr/share/nginx/html nginx:latest 
d3e974886cef08b56d01ce01643f41b325514cd0fd34b3658964ce868ec109aa
[root@docker ~]# cd /var/lib/docker/volumes/kami/
[root@docker kami]# ls
_data
[root@docker kami]# cd _data/
[root@docker _data]# ls
50x.html  index.html

修改数据查看容器内容是否发生改变

[root@docker _data]# echo test555 > index.html
[root@docker _data]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                                     NAMES
d3e974886cef   nginx:latest   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   0.0.0.0:32771->80/tcp, :::32771->80/tcp   nginx3
[root@docker _data]# curl http://192.168.100.10:32771
test555

在使用docker volume命令创建volume时,volume默认都是存在在本地的,实际上本地的volume就是一个目录。除此之外Docker还支持在外部存储系统上创建volume,比如:NFS、Ceph等

Docker数据共享

实现容器间数据共享的方法如下:

1.第一种方法是将共享数据放在volume中,然后将其mount到多个容器。

2.第二种方法是使用volume container,volume container是用来为其他容器提供volume的容器。 这样可以提高容器的可移植性。

3.第三种方法是将数据打包到镜像中,然后通过–volumes-from共享

第一种
[root@docker ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@docker ~]# docker run -itd --name nginx3 -p 8081:80 -v /html:/usr/share/nginx/html nginx:latest 
e16cf8a5a53951837907ac0d0fe042d782384afd5a74d28459c95ada569f984d
[root@docker ~]# docker run -itd --name nginx2 -p 8082:80 -v /html:/usr/share/nginx/html nginx:latest 
93bf09407a248740cf22d13a46d3e24b2a6957b0ae184b4243a8249b8eadf938
[root@docker ~]# docker run -itd --name nginx1 -p 8083:80 -v /html:/usr/share/nginx/html nginx:latest 
154c20a51b40ecd1cafe7f5561b7a24e5def58f1584d1408426b8aa560b0452a

查看

[root@docker ~]# curl http://192.168.100.10:8081
test222
[root@docker ~]# curl http://192.168.100.10:8082
test222
[root@docker ~]# curl http://192.168.100.10:8083
test222
第二种方法是使用volume container,volume container是用来为其他容器提供volume的容器。这样可以提高容器的可移植性

只需要创建一个容器提供html文件,其他容器指定这个提供html文件的容器就行

[root@docker ~]# docker pull busybox
[root@docker ~]# docker create --name kami1 -v /html:/usr/share/nginx/html busybox
1edf9ade5b9d3cf1517f8a6311f8a617a4af727138ab48add6c20aae8535e647
[root@docker ~]# docker run -itd --name nginx1 -p 8811:80 --volumes-from kami1 nginx
1c9606f160b03ca4c9da5453e39200a723f690d8b4fc22d02cfbd0962092052a
[root@docker ~]# docker run -itd --name nginx2 -p 8812:80 --volumes-from kami1 nginx
edd15acbe17ef5854e3ceef31f1bf682f12cfdff41a45a76a6478d9bed557d0b
[root@docker ~]# docker run -itd --name nginx3 -p 8813:80 --volumes-from kami1 nginx
ed2b88e4dfe4e95262a2a90e651a50de0ef2366a997f2a634d6133ad7d5731bc
[root@docker ~]# curl http://192.168.100.10:8811
test222
[root@docker ~]# curl http://192.168.100.10:8812
test222
[root@docker ~]# curl http://192.168.100.10:8813
test222

修改html内容

[root@docker ~]# echo agito > /html/index.html 
[root@docker ~]# curl http://192.168.100.10:8811
agito
[root@docker ~]# curl http://192.168.100.10:8812
agito
[root@docker ~]# curl http://192.168.100.10:8813
agito

与第一种实现数据共享的方法相比,不必再为每个容器指定volemu,所有volume都在volume container 中定义好了,容器只需与volume container关联,实现了容器与Docker host的解耦。

data-packed volume container

使用data-packed volume container,其原理是将数据打包到镜像中,然后通过–volumes-from共享

[root@docker ~]# vim Dockerfile

FROM busybox:latest
ADD html /usr/share/nginx/html
VOLUME /usr/share/nginx/html
CMD ["/bin/bash"]

[root@docker ~]# mkdir html
[root@docker ~]# echo test12341 > html/index.html
[root@docker ~]# docker build -t te .
[root@docker ~]# docker create --name xie1 te
70c6226aa81ed3cf27d484d13aac532f76fad02648054696fb6271dce3e82080
[root@docker ~]# docker run --name xnginx -itd -p 8881:80 --volumes-from xie1 nginx:latest 
69e6fd7553f7c03f6277d0c269eec74257d2abd36dd1bf915867fb07c47c9117

测试

[root@docker ~]# curl http://192.168.100.10:8881
test12341

容器能够正确读取volume中的数据。data-packed volume container是自包含的,不依赖Docker host提供数据,具有很强的移植性,非常适合只使用静态数据的场景,比如应用的配置信息、web server的静态文件等。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐