Docker Volume 解密

本文详细介绍了Docker数据卷(Volume)的概念、特点及使用方法,包括如何创建、管理、清理数据卷,以及匿名卷和命名卷的区别。通过数据卷,实现了容器数据的持久化和容器间的共享,确保了应用与数据的解耦。同时,对比了bindmounts的使用和区别,强调了数据卷在容器数据管理中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Docker Volume 解密

@(容器技术)[Docker 数据卷, 帮助]

什么是数据卷Volume

  • Docker 镜像被存储在一系列的只读层。当我们开启一个容器时,Docker读取只读镜像并在顶部添加一个读写层,如果正在运行的容器修改了现有的文件,该文件将从底层的只读层拷贝到最顶部的读写层,在读写层中的旧版文件隐藏于该文件之下,并没有被破坏,仍然存在于镜像下。
  • 当Docker 容器被删除,然后重新启动镜像时,将开启一个没有任何更改的新容器。这些更改会被丢失
  • 只读层以及顶部的读写层的组合被Docker称为Union File System联合文件系统

  • 为了能够持久保存数据以及共享容器间的数据,Docker提出了Volume的概念:
    • volume是存在一个或多个容器中的特定文件或文件夹,这个目录能够独立于联合文件系统的形式在宿主机中存在,并为数据的共享与持久提供一下便利

数据卷Volume的特点

  • volume在容器创建时就初始化,在容器运行时就可以使用其中的文件
  • 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效方便
  • 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作
  • 对volume中数据操作不会影响到镜像本身,解耦了应用和数据
  • volume的生存周期独立于容器的生存周期,即使删除容器,volume仍然会存在,没有任何容器使用的volume也不会被Docker删除

将Docker 数据挂载到容器

  • 在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着Container的生命周期结束而结束),需要将数据从宿主机挂载到容器中。目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中:

    • 第一种[volume]:Docker管理宿主机文件系统的一部分,默认位于/var/lib/docker/volumes目录中,所有Container的数据都保存在了这个目录下边,由于没有在创建时指定卷,所以Docker帮我们默认创建许多匿名(就一堆很长ID的名字)卷
    • 第二种[bind mounts]:意为着可以存储在宿主机系统的任意位置。bind mount在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。
    • 第三种[tmpfs]:挂载存储在宿主机系统的内存中,而不会写入宿主机的文件系统
      在这里插入图片描述

Volume的基本使用

管理卷
# 创建自定义卷
root@dengbiao:/home/dengbiao# docker volume create edc-nginx-vol
edc-nginx-vol
# 查看所有容器卷
root@dengbiao:/home/dengbiao# docker volume ls
DRIVER              VOLUME NAME
local               edc-nginx-vol

# 查看指定卷的详细信息
root@dengbiao:/home/dengbiao# docker inspect edc-nginx-vol
[
    {
        "CreatedAt": "2020-11-13T13:31:13+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/DATA/lib/docker-lib/volumes/edc-nginx-vol/_data",
        "Name": "edc-nginx-vol",
        "Options": {},
        "Scope": "local"
    }
]

创建使用指定卷的容器
  • 如果有了自定义容器卷,我们就可以创建使用这个容器卷的容器
    • -v 代表挂载数据卷,这里使用容器卷edc-nginx-vol表示宿主机挂载点,/usr/share/nginx/html是yum安装nginx的默认网页目录
docker run -d -it --name=edc-nginx -p 8800:80 -v edc-nginx-vol:/usr/share/nginx/html nginx
  • 从宿主机挂载点查看
root@dengbiao:/DATA/lib/docker-lib/volumes/edc-nginx-vol/_data# pwd
/DATA/lib/docker-lib/volumes/edc-nginx-vol/_data
root@dengbiao:/DATA/lib/docker-lib/volumes/edc-nginx-vol/_data# ls
50x.html  index.html
  • 在容器里边的改动,宿主机可以感知,反之宿主机里面的改动,容器里边同样可以感知到。
  • 如果我们手动stop并且remove当前nginx容器,宿主机查看发现容器卷里面的文件还在,并没有被删除掉
清理卷
  • 如果不再使用自定义数据卷了,那么可以手动清理掉
root@dengbiao:~# docker volume rm edc-nginx-vol
edc-nginx-vol

Bind Mounts 的基本使用

使用卷创建一个容器
  • 将宿主机上的 /app/wwwroot 目录(如果没有会自动创建)挂载到 /usr/share/nginx/html (这个目录是yum安装nginx的默认网页目录)
root@dengbiao:~# docker run -d -it --name=edc-nginx -v /app/wwwroot:/usr/share/nginx/html nginx
c4ccddb7b472e08ac82fd80f6d2b6c7ee10611351039bea6539df1cbef2f3669

  • 与volumes不同,bind mounts的方式会隐藏掉被挂载目录里面的内容(容器里面,如果非空的话),这里是/usr/share/nginx/html 目录下的内容被隐藏掉了,因此我们看不到
root@dengbiao:/app/wwwroot# ls
root@dengbiao:/app/wwwroot# 
  • 反之,我们可以将宿主机的文件随时挂载到容器中
# 宿主机创建index.html文件
root@dengbiao:/app/wwwroot# touch index.html
root@dengbiao:/app/wwwroot# vim index.html 

# 进入容器查看
root@dengbiao:/app/wwwroot# docker exec -it edc-nginx /bin/bash
root@c4ccddb7b472:/# cd /usr/share/nginx/html            
root@c4ccddb7b472:/usr/share/nginx/html# ls
index.html
验证绑定
root@dengbiao:/app/wwwroot# docker inspect edc-nginx

"HostConfig": {
            "Binds": [
                "/app/wwwroot:/usr/share/nginx/html"
            ],

清理
  • 同volumes一样,当我们清理掉容器之后,挂载目录里面的文件仍然还在,不会随着容器的结束而消失,从而实现数据持久化
docker rm edc-nginx

匿名卷(匿名挂载)和命名卷(具名挂载)

什么是匿名卷?具名挂载?

  • 匿名卷/匿名挂载:在进行数据卷挂载的时候不指定宿主机的数据卷目录-v命令后直接跟容器内数据卷路径
  • 命名卷/具名挂载:在进行数据卷挂载的时候既指定宿主机内数据卷所在路径,又指定容器数据内卷所在路径
#匿名挂载(匿名卷)
docker run -d -p 6379:6379 --name mycentos -v /src/volume01

#具名挂载(命名卷) -v 宿主机数据卷所在路径:容器数据卷所在路径
docker run -d -p 6379:6379 --name mycentos -v /home/docker_volume:/src/volume01
  • 也可以在在dockerfile构建docker镜像的时候使用VOLUME保留字来对数据卷进行挂载,此种挂载方式是匿名挂载的,我们可以指定一个或多个数据卷,这样只要启动了该自定义容器镜像,则会自动进行数据挂载,不会出现忘记挂载导致数据不安全的情况
VOLUME ["容器内数据卷路径1","容器内数据卷路径2"……]
  • 由于匿名卷挂载的时候只指定了容器内数据卷路径,至于该容器内数据卷的路径到底和宿主机中哪个目录进行数据挂载,可以通过docker inspect命令查看

匿名卷和命名卷的区别

  • 命名卷:在使用过一次后,以后挂载容器的时候还可以继续使用,一般需要保存数据的时候使用命令卷宿主机中数据卷的文件内容依然存在。
  • 容器间可以实现数据共享
# 启动一个容器,并指定挂载及映射
docker run -it --name mycentos -v /home/centos_volume:/usr/local/volume01 centos:latest /bin/bash

# 进入容器中数据卷目录下创建文件,内容随意填写
cd /usr/local/volume01
vim file.txt 

# 查看宿主机的数据卷路径下是否有创建的文件
dengbiao@dengbiao:~$ cd /home/centos_volume/
dengbiao@dengbiao:/home/centos_volume$ ll
总用量 12
drwxr-xr-x 2 root root 4096 11月 13 14:45 ./
drwxr-xr-x 4 root root 4096 11月 13 14:44 ../
-rw-r--r-- 1 root root   17 11月 13 14:45 file.txt

# 退出删除容器
 docker rm mycentos

# 再启动新容器
docker run -it --name mycentos -v /home/centos_volume:/usr/local/volume01 centos:latest /bin/bash


# 再次进入容器,查看容器中数据卷路径是否有被创建的文件
cd /usr/local/volume01/
ls
file.txt
  • 匿名卷:每次创建新的容器,Docker都会随机自动创建宿主机内的数据卷路径(那一大长串ID),不同的容器,宿主机内的数据卷路径均不相同。匿名卷一般用来存储无关痛痒的数据
  • 容器间不可以实现数据共享
# 启动一个容器,并指定挂载及映射
 docker run -it --name mycentos -v /usr/local/volume01 centos:latest /bin/bash
 
# 进入容器中数据卷目录下创建文件,内容随意填写
cd /usr/local/volume01/
vi file.tx

# inspect 查看宿主机的数据卷路径
docker inspect mycentos 

"Mounts": [
            {
                "Type": "volume",
                "Name": "2c90ceeb2597fdba5391e646e5a79d8f5c9dba816ace6fc34e30803a990377fe",
                "Source": "/DATA/lib/docker-lib/volumes/2c90ceeb2597fdba5391e646e5a79d8f5c9dba816ace6fc34e30803a990377fe/_data",
                "Destination": "/usr/local/volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]

# 查看宿主机的数据卷路径下是否有创建的文件
ls /DATA/lib/docker-lib/volumes/2c90ceeb2597fdba5391e646e5a79d8f5c9dba816ace6fc34e30803a990377fe/_data

file.txt

# 退出删除容器
exit
docker rm mycentos 

# 再启动新容器
 docker run -it --name mycentos -v /usr/local/volume01 centos:latest /bin/bash
 
# insepect 查看宿主机的数据卷路径
docker inspect mycentos 
 "Mounts": [
            {
                "Type": "volume",
                "Name": "e68db612cfe89440dfee3f4de14b47ba72b6617729c3da68ecce4f75eb336cb2",
                "Source": "/DATA/lib/docker-lib/volumes/e68db612cfe89440dfee3f4de14b47ba72b6617729c3da68ecce4f75eb336cb2/_data",
                "Destination": "/usr/local/volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]

# 观察两次容器的inspect信息:`宿主机内的数据卷路径`
Source 字段 均不相同

# 再次进入容器,查看容器中数据卷路径是否有被创建的文件
cd /usr/local/volume01/
无内容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值