Docker 数据卷

文章介绍了Docker数据卷的概念和重要性,它是解决容器数据丢失和跨容器共享数据的解决方案。数据卷可以在容器之间共享和重用,其生命周期独立于容器,确保数据持久化。文中通过实例展示了如何使用数据卷进行MySQL的数据持久化,并提到了数据卷容器和匿名/具名挂载的方式,强调了数据卷在容器间共享和数据迁移中的作用。
摘要由CSDN通过智能技术生成

问题:通过镜像创建一个容器。容器一旦被销毁,则容器内的数据将一并被删除。但有些情况下,通过服务器上传的图片出会丢失。容器中的数据不是持久化状态的。

那有没有一种独立于容器、提供持久化并能服务于多个容器的东西呢?

什么是数据卷

数据卷 : 是一个可供一个或多个容器使用的特殊目录

特性:

· 数据卷可以在容器之间共享和重用
· 对数据卷的修改会立马生效
· 对数据卷的更新,不会影响镜像
· 数据卷默认会一直存在,即使容器被删除

为什么需要数据卷?

这得从 docker 容器的文件系统说起。出于效率等一系列原因,docker 容器的文件系统在宿主机上存在的方式很复杂,这会带来下面几个问题:

· 不能在宿主机上很方便地访问容器中的文件。
· 无法在多个容器之间共享数据。
· 当容器删除时,容器中产生的数据将丢失。

为了解决这些问题,docker 引入了数据卷(volume) 机制。数据卷是存在于一个或多个容器中的特定文件或文件夹,这个文件或文件夹以独立于 docker 文件系统的形式存在于宿主机中。

数据卷的最大特定是:其生存周期独立于容器的生存周期。

使用数据卷的最佳场景

· 在多个容器之间共享数据,多个容器可以同时以只读或者读写的方式挂载同一个数据卷,从而共享数据卷中的数据。

· 当宿主机不能保证一定存在某个目录或一些固定路径的文件时,使用数据卷可以规避这种限制带来的问题。

· 当你想把容器中的数据存储在宿主机之外的地方时,比如远程主机上或云存储上。

· 当你需要把容器数据在不同的宿主机之间备份、恢复或迁移时,数据卷是很好的选择。

数据卷应用

路径方式

将项目案例放入指定路径中,-v数据卷。启动Tomcat。

docker run -d -p 8080:8080 --name tomcat-8080 -v /opt/volumn_exam:/usr/local/tomcat/webapps tomcat

查看数据卷是否挂载成功

docker inspect 容器id

 

测试容器和宿主机之间数据共享:可以发现,在容器中,创建的会在宿主机中看到!

 测试容器停止退出后,主机修改数据是否会同步?

  1. 停止容器
  2. 在宿主机上修改文件,增加些内容
  3. 启动刚才停止的容器
  4. 然后查看对应的文件,发现数据依旧同步!ok

docker run -d -v /home/samve/centos:/home centos /bin/bash -c "while true; do echo test; sleep 1; done" 

使用 docker 安装 mysql

思考:mysql 数据持久化的问题!

# 1、搜索镜像
[root@kuangshen ~]# docker search mysql
NAME DESCRIPTION
STARS
mysql MySQL is a widely used, open-source
relation… 9488
# 2、拉取镜像
[root@kuangshen ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
54fec2fa59d0: Already exists
bcc6c6145912: Pull complete
951c3d959c9d: Pull complete
05de4d0e206e: Pull complete
319f0394ef42: Pull complete
d9185034607b: Pull complete
013a9c64dadc: Pull complete
e745b3361626: Pull complete
03145d87b451: Pull complete
3991a6b182ee: Pull complete
62335de06f7d: Pull complete

通过Docker File 来添加(了解)
DockerFile 是用来构建Docker镜像的构建文件,是由一些列命令和参数构成的脚本。
我们在这里,先体验下,后面我们会详细讲解 DockerFile !
测试:
Digest:
sha256:e821ca8cc7a44d354486f30c6a193ec6b70a4eed8c8362aeede4e9b8d74b8ebb
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
# 3、启动容器 -e 环境变量!
# 注意: mysql的数据应该不丢失!先体验下 -v 挂载卷! 参考官方文档
[root@kuangshen home]# docker run -d -p 3310:3306 -v
/home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e
MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
4763fa5c68c4323688102f57938fb10996a0fb902d2812349286529f9378f16c
# 4、使用本地的sqlyog连接测试一下 3310
# 5、查看本地的 /home/mysql 目录
[root@kuangshen data]# pwd
/home/mysql/data
[root@kuangshen data]# ls
.. ... . test # 可以看到我们刚刚建立的mysql数据库在本地存储着
# 6、删除mysql容器
[root@kuangshen data]# docker rm -f mysql01 # 删除容器,然后发现远程连接失败!
mysql01
[root@kuangshen data]# ls
.. ... . test # 可以看到我们刚刚建立的mysql数据库在本地存储着

通过Docker File 来添加(了解)

DockerFile 是用来构建Docker镜像的构建文件,是由一些列命令和参数构成的脚本。

我们在这里,先体验下,后面我们会详细讲解 DockerFile !

测试:

# 1、我们在宿主机 /home 目录下新建一个 docker-test-volume文件夹
[root@kuangshen home]# mkdir docker-test-volume
# 说明:在编写DockerFile文件中使用 VOLUME 指令来给镜像添加一个或多个数据卷
VOLUME["/dataVolumeContainer1","/dataVolumeContainer2","/dataVolumeContainer
3"]
# 出于可移植和分享的考虑,我们之前使用的 -v 主机目录:容器目录 这种方式不能够直接在
DockerFile中实现。
# 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有宿主机上都存在这样的特定目录.
# 2、编写DockerFile文件
[root@kuangshen docker-test-volume]# pwd
/home/docker-test-volume
[root@kuangshen docker-test-volume]# vim dockerfile1
[root@kuangshen docker-test-volume]# cat dockerfile1
# volume test
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "-------end------"
CMD /bin/bash
# 3、build后生成镜像,获得一个新镜像 kuangshen/centos
docker build -f /home/docker-test-volume/dockerfile1 -t kuangshen/centos . #
注意最后有个.

# 4、启动容器
[root@kuangshen docker-test-volume]# docker run -it 0e97e1891a3d /bin/bash #
启动容器
[root@f5824970eefc /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 2 root root 4096 May 11 11:55 dataVolumeContainer1 # 数据卷目录
drwxr-xr-x 2 root root 4096 May 11 11:55 dataVolumeContainer2 # 数据卷目录
drwxr-xr-x 5 root root 360 May 11 11:55 dev
drwxr-xr-x 1 root root 4096 May 11 11:55 etc
drwxr-xr-x 2 root root 4096 May 11 2019 home
.....
# 问题:通过上述步骤,容器内的卷目录地址就已经知道了,但是对应的主机目录地址在哪里呢?
# 5、我们在数据卷中新建一个文件
[root@f5824970eefc dataVolumeContainer1]# pwd
/dataVolumeContainer1
[root@f5824970eefc dataVolumeContainer1]# touch container.txt
[root@f5824970eefc dataVolumeContainer1]# ls -l
total 0
-rw-r--r-- 1 root root 0 May 11 11:58 container.txt
# 6、查看下这个容器的信息
[root@kuangshen ~]# docker inspect 0e97e1891a3d
# 查看输出的Volumes
"Volumes": {
"/dataVolumeContainer1": {},
"/dataVolumeContainer2": {}
},
# 7、这个卷在主机对应的默认位置

注意:如果访问出现了 cannot open directory: Permission denied

解决办法:

在挂载目录后多加一个 --privileged=true参数即可

匿名和具名挂载

# 匿名挂载
-v 容器内路径

docker run -d -P --name nginx01 -v /etc/nginx nginx

# 匿名挂载的缺点,就是不好维护,通常使用命令 docker volume维护

docker volume ls

# 具名挂载
-v 卷名:/容器内路径

docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx

# 查看挂载的路径

docker volume inspect nginxconfig

[
{
"CreatedAt": "2020-05-13T17:23:00+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data",
"Name": "nginxconfig",
"Options": null,
"Scope": "local"
}
]
# 怎么判断挂载的是卷名而不是本机目录名?
不是/开始就是卷名,是/开始就是目录名
# 改变文件的读写权限
# ro: readonly
# rw: readwrite
# 指定容器对我们挂载出来的内容的读写权限

docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx

数据卷容器

命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。

我们使用上一步的镜像:kuangshen/centos 为模板,运行容器 docker01,docker02,docker03,他们都会具有容器卷。

"/dataVolumeContainer1"
"/dataVolumeContainer2"

 我们来测试下,容器间传递共享

1、先启动一个父容器docker01,然后在dataVolumeContainer2新增文件

退出不停止:ctrl+P+Q

2、创建docker02,docker03 让他们继承docker01 --volumes-from

[root@kuangshen docker-test-volume]# docker run -it --name docker02 --
volumes-from docker01 kuangshen/centos
[root@ea4c82779077 /]# cd /dataVolumeContainer2
[root@ea4c82779077 dataVolumeContainer2]# ls
docker01.txt
[root@95164598b306 dataVolumeContainer2]# touch docker02.txt
[root@95164598b306 dataVolumeContainer2]# ls
docker01.txt docker02.txt
[root@kuangshen docker-test-volume]# docker run -it --name docker03 --
volumes-from docker01 kuangshen/centos
[root@ea4c82779077 /]# cd /dataVolumeContainer2
[root@ea4c82779077 dataVolumeContainer2]# ls
docker01.txt docker02.txt
[root@95164598b306 dataVolumeContainer2]# touch docker03.txt
[root@95164598b306 dataVolumeContainer2]# ls
docker01.txt docker02.txt docker03.txt

 3、回到docker01发现可以看到 02 和 03 添加的共享文件

[root@kuangshen docker-test-volume]# docker attach docker01
[root@799b6ea5db7c dataVolumeContainer2]# ls -l
total 0
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt

 4、删除docker01,docker02 修改后docker03还能不能访问

[root@kuangshen docker-test-volume]# docker rm -f docker01
docker01
[root@kuangshen docker-test-volume]# docker attach docker02
[root@ea4c82779077 dataVolumeContainer2]# ls -l
total 0
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt
[root@ea4c82779077 dataVolumeContainer2]# touch docker02-update.txt
[root@ea4c82779077 dataVolumeContainer2]# ls -a
. .. docker01.txt docker02.txt docker02-update.txt docker03.txt
[root@ea4c82779077 dataVolumeContainer2]# Ctrl+P+Q 退出容器

[root@kuangshen docker-test-volume]# docker attach docker03
[root@95164598b306 dataVolumeContainer2]# ls -l
total 0
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt
-rw-r--r-- 1 root root 0 May 11 13:29 docker02-update.txt
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt

5、删除docker02 ,docker03还能不能访问

[root@kuangshen docker-test-volume]# docker ps
CONTAINER ID IMAGE
95164598b306 kuangshen/centos
ea4c82779077 kuangshen/centos
[root@kuangshen docker-test-volume]# docker rm -f docker02
docker02
[root@kuangshen docker-test-volume]# docker attach docker03
[root@95164598b306 dataVolumeContainer2]# ls -l
total 0
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt
-rw-r--r-- 1 root root 0 May 11 13:29 docker02-update.txt
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt
[root@95164598b306 dataVolumeContainer2]# touch docker03-update.txt

6、新建docker04继承docker03,然后再删除docker03,看下是否可以访问!

[root@2119f4f23a92 /]# cd dataVolumeContainer2
[root@2119f4f23a92 dataVolumeContainer2]# ls -l
total 0
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt
-rw-r--r-- 1 root root 0 May 11 13:29 docker02-update.txt
-rw-r--r-- 1 root root 0 May 11 13:32 docker03-update.txt
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt
# 查看当前运行的容器
[root@kuangshen docker-test-volume]# docker ps
CONTAINER ID IMAGE NAMES
2119f4f23a92 kuangshen/centos docker04
95164598b306 kuangshen/centos docker03
# 继续删除docker03
[root@kuangshen docker-test-volume]# docker rm -f docker03
docker03
[root@kuangshen docker-test-volume]# docker attach docker04
[root@2119f4f23a92 dataVolumeContainer2]# ls -l
total 0
-rw-r--r-- 1 root root 0 May 11 13:20 docker01.txt
-rw-r--r-- 1 root root 0 May 11 13:22 docker02.txt
-rw-r--r-- 1 root root 0 May 11 13:29 docker02-update.txt
-rw-r--r-- 1 root root 0 May 11 13:32 docker03-update.txt
-rw-r--r-- 1 root root 0 May 11 13:24 docker03.txt

得出结论:

容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。

存储在本机的文件则会一直保留!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值