小鲸鱼历险记(五)【容器数据卷】

| 本篇文章共2.6k字,预计阅读12分钟

本文最后更新于 <span id="expire-date"></span> 天前,文中部分描述可能已经过时。

1、什么是容器数据卷

docker的理念回顾:

将应用和运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对于数据的要求,是希望能够 持久化的!

就好比,你安装一个MySQL,结果你把容器删了,就相当于删库跑路了,这TM也太扯了吧!

所以我们希望容器之间有可能可以共享数据,Docker容器产生的数据,如果不通过docker commit 生成 新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行不通的!

为了能保存数据在Docker中我们就可以使用卷!让数据挂载到我们本地!这样数据就不会因为容器删除 而丢失了!

作用: 卷就是目录或者文件,存在一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此 能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性。

卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。

特点:

1、数据卷可在容器之间共享或重用数据

2、卷中的更改可以直接生效

3、数据卷中的更改不会包含在镜像的更新中

4、数据卷的生命周期一直持续到没有容器使用它为止

所以:总结一句话: 就是容器的持久化,以及容器间的继承和数据共享!

2、使用数据卷

方式一:容器中直接使用命令来添加

挂载

# 命令
docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名

# 测试
[root@kuangshen ~]# docker run -it -v /home/ceshi:/home centos /bin/bash

查看数据卷是否挂载成功 docker inspect 容器id

image-20210311215030464

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

image-20210311215659297

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

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

image-20210311215947085

使用 Docker 安装 MySQL

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

# 1、搜索镜像
[root@ziyang ~]# docker search mysql
NAME                              DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql                             MySQL is a widely used, open-source relation…   10600               [OK]   

# 2、拉取镜像
[root@ziyang ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
a076a628af6f: Already exists 
f6c208f3f991: Pull complete 
88a9455a9165: Pull complete 
406c9b8427c6: Pull complete 
7c88599c0b25: Pull complete 
25b5c6debdaf: Pull complete 
43a5816f1617: Pull complete 
1831ac1245f4: Pull complete 
37677b8c1f79: Pull complete 
27e4ac3b0f6e: Pull complete 
7227baa8c445: Pull complete 
Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

# 3、启动容器 -e 环境变量!
# 注意: mysql的数据应该不丢失!先体验下 -v 挂载卷! 参考官方文档
[root@ziyang ~]# 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

5ead80e1817123ead63ad82c66027d4f887688d4b5681d1a23b56fc6ca3bc992

# 4、使用本地的navicat连接测试一下 3310

# 5、查看本地的 /home/mysql 目录
[root@ziyang ~]# cd /home/mysql
[root@ziyang mysql]# ls
conf  data
[root@ziyang mysql]# cd data
[root@ziyang data]# ls
... test  # 可以看到我们刚刚建立的mysql数据库在本地存储着

# 6、删除mysql容器
[root@ziyang data]# docker rm -f mysql01  # 删除容器,然后发现远程连接失败!
mysql01
[root@ziyang data]# ls
... test  # 可以看到我们刚刚建立的mysql数据库在本地存储着
image-20210312110251009 image-20210312110700008

通过Docker File 来添加(了解)

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

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

# 1、我们在宿主机 /home 目录下新建一个 docker-test-volume文件夹
[root@ziyang home]# mkdir docker-test-volume

# 说明:在编写DockerFile文件中使用 VOLUME 指令来给镜像添加一个或多个数据卷
VOLUME["/volume01","/volume02"]
# 出于可移植和分享的考虑,我们之前使用的 -v 主机目录:容器目录 这种方式不能够直接在DockerFile中实现。
# 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有宿主机上都存在这样的特定目录.

# 2、编写DockerFile文件
[root@ziyang docker-test-volume]# pwd
/home/docker-test-volume
[root@ziyang docker-test-volume]# vim dockerfile1
[root@ziyang docker-test-volume]# cat dockerfile1 
FROM centos

VOLUME ["volume01", "volume02"]

CMD echo "----end----"
CMD /bin/bash

# 3、build后生成镜像,获得一个新镜像 ziyang/centos
[root@ziyang docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t ziyang/centos .  #注意最后有个.
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 300e315adb2f
Step 2/4 : VOLUME ["volume01", "volume02"]
 ---> Running in a9d5b1f79d56
Removing intermediate container a9d5b1f79d56
 ---> 82615cf5371d
Step 3/4 : CMD echo "----end----"
 ---> Running in 8b2595396683
Removing intermediate container 8b2595396683
 ---> 969129b3ef79
Step 4/4 : CMD /bin/bash
 ---> Running in fabc600aceab
Removing intermediate container fabc600aceab
 ---> 9960194139cf
Successfully built 9960194139cf
Successfully tagged ziyang/centos:latest

image-20210312111425618

# 4、启动容器
[root@ziyang docker-test-volume]# docker run -it 9960194139cf /bin/bash  #启动容器

[root@520d32c4888c /]# ls -l
total 56
...
drwxr-xr-x   2 root root 4096 Mar 12 03:15 volume01 # 数据卷目录
drwxr-xr-x   2 root root 4096 Mar 12 03:15 volume02 # 数据卷目录

# 问题:通过上述步骤,容器内的卷目录地址就已经知道了,但是对应的主机目录地址在哪里呢?

# 5、我们在数据卷中新建一个文件
[root@520d32c4888c volume01]# pwd
/volume01
[root@520d32c4888c volume01]# touch container.txt
[root@520d32c4888c volume01]# ls -l
total 0
-rw-r--r-- 1 root root 0 Mar 12 03:18 container.txt

# 6、查看下这个容器的信息
[root@ziyang ~]# docker inspect 9960194139cf
# 查看输出的Volumes
"Volumes": {
    "volume01": {},
    "volume02": {}
},

# 7、这个卷在主机对应的默认位置
image-20210312202654803 image-20210312202819978

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

解决办法:在挂载目录后多加一个 --privileged=true 参数即可

3、匿名和具名挂载

# 匿名挂载
-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

# 查看挂载的路径
[root@ziyang /]# docker volume inspect nginxconfig
[
    {
        "CreatedAt": "2021-03-12T20:32:45+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

4、数据卷容器

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

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

"/volume01"
"/volume02"

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

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

image-20210312203838170

image-20210312204705309

退出不停止:ctrl+P+Q

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

[root@ziyang ~]# docker run -it --name docker02 --volumes-from docker01 ziyang/centos
[root@a6e6dd4697b2 volume02]# cd volume01
[root@a6e6dd4697b2 volume01]# ls
docker01.txt
[root@a6e6dd4697b2 volume01]# touch docker02.txt
[root@a6e6dd4697b2 volume01]# ls
docker01.txt  docker02.txt

[root@ziyang ~]# docker run -it --name docker03 --volumes-from docker01 ziyang/centos
[root@2ea7c524f6f1 /]# cd volume01
[root@2ea7c524f6f1 volume01]# ls
docker01.txt  docker02.txt
[root@2ea7c524f6f1 volume01]# touch docker03.txt
[root@2ea7c524f6f1 volume01]# ls
docker01.txt  docker02.txt  docker03.txt

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

[root@ziyang /]# docker attach docker01
[root@7d45b803d2e0 volume01]# ls -l
total 0
-rw-r--r-- 1 root root 0 Mar 12 12:46 docker01.txt
-rw-r--r-- 1 root root 0 Mar 12 12:51 docker02.txt
-rw-r--r-- 1 root root 0 Mar 12 12:53 docker03.txt

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

[root@ziyang /]# docker rm -f docker01
docker01
[root@ziyang /]# docker attach docker02
[root@a6e6dd4697b2 volume01]# ls -l
total 0
-rw-r--r-- 1 root root 0 Mar 12 12:46 docker01.txt
-rw-r--r-- 1 root root 0 Mar 12 12:51 docker02.txt
-rw-r--r-- 1 root root 0 Mar 12 12:53 docker03.txt
[root@a6e6dd4697b2 volume01]# ls -a
.  ..  docker01.txt  docker02-update.txt  docker02.txt	docker03.txt
[root@a6e6dd4697b2 volume01]# Ctrl+P+Q 退出容器

[root@ziyang /]# docker attach docker03
[root@2ea7c524f6f1 volume01]# ls -l
total 0
-rw-r--r-- 1 root root 0 Mar 12 12:46 docker01.txt
-rw-r--r-- 1 root root 0 Mar 12 12:58 docker02-update.txt
-rw-r--r-- 1 root root 0 Mar 12 12:51 docker02.txt
-rw-r--r-- 1 root root 0 Mar 12 12:53 docker03.txt

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

[root@ziyang ~]# docker rm -f docker02
docker02

[root@ziyang /]# docker attach docker03
[root@2ea7c524f6f1 volume01]# ls -l
total 0
-rw-r--r-- 1 root root 0 Mar 12 12:46 docker01.txt
-rw-r--r-- 1 root root 0 Mar 12 12:58 docker02-update.txt
-rw-r--r-- 1 root root 0 Mar 12 12:51 docker02.txt
-rw-r--r-- 1 root root 0 Mar 12 12:53 docker03.txt
[root@2ea7c524f6f1 volume01]# touch docker03-update.txt
[root@2ea7c524f6f1 volume01]# ls 
docker01.txt  docker02-update.txt  docker02.txt  docker03-update.txt  docker03.txt

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

[root@ziyang /]# docker run -it --name docker04 --volumes-from docker03 ziyang/centos
[root@0f2ab8092be0 /]# ls -l
total 56
...
drwxr-xr-x   2 root root 4096 Mar 12 13:01 volume01
drwxr-xr-x   2 root root 4096 Mar 12 12:37 volume02
[root@0f2ab8092be0 /]# cd volume01
[root@0f2ab8092be0 volume01]# ls -l
total 0
-rw-r--r-- 1 root root 0 Mar 12 12:46 docker01.txt
-rw-r--r-- 1 root root 0 Mar 12 12:58 docker02-update.txt
-rw-r--r-- 1 root root 0 Mar 12 12:51 docker02.txt
-rw-r--r-- 1 root root 0 Mar 12 13:01 docker03-update.txt
-rw-r--r-- 1 root root 0 Mar 12 12:53 docker03.txt

# 查看当前运行的容器
[root@ziyang ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                NAMES
0f2ab8092be0        ziyang/centos       "/bin/sh -c /bin/bash"   About a minute ago   Up About a minute                        docker04
2ea7c524f6f1        ziyang/centos       "/bin/sh -c /bin/bash"   12 minutes ago       Up 12 minutes                            docker03

# 继续删除docker03
[root@ziyang ~]# docker rm -f docker03
docker03

[root@ziyang ~]# docker attach docker04
[root@0f2ab8092be0 volume01]# ls -l
total 0
-rw-r--r-- 1 root root 0 Mar 12 12:46 docker01.txt
-rw-r--r-- 1 root root 0 Mar 12 12:58 docker02-update.txt
-rw-r--r-- 1 root root 0 Mar 12 12:51 docker02.txt
-rw-r--r-- 1 root root 0 Mar 12 13:01 docker03-update.txt
-rw-r--r-- 1 root root 0 Mar 12 12:53 docker03.txt

得出结论:

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

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

本文作者:ZYang

本文链接: https://luziyangde.cn/2021/03/06/%E5%B0%8F%E9%B2%B8%E9%B1%BC%E5%8E%86%E9%99%A9%E8%AE%B0%EF%BC%88%E4%BA%94%EF%BC%89%E3%80%90%E5%AE%B9%E5%99%A8%E6%95%B0%E6%8D%AE%E5%8D%B7%E3%80%91/

文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。