Docker——Docker 容器数据卷(Volumes)

Docker 容器数据卷

  • 容器数据卷(Volumes)
    • 容器数据卷概述
    • 使用数据卷
    • 实现mysql数据同步
    • 具名挂载和匿名挂载
      • 匿名挂载
      • 具名挂载
    • DockerFile里写Volumes配置
    • 多个数据卷容器挂载
    • 多个mysql实现数据共享

容器数据卷(Volumes)

容器数据卷概述

  • Docker 镜像是分层结构,联合挂载,镜像中各层的文件都是只读的,容器中所有文件对外可见的状态是多层叠加后的可见状态。因此对于IO性能要求较高的容器,如果使用Overlayfs会严重影响容器的性能。
  • 另外,容器在生命周期结束的时候会被删除,对于有数据持久化要求的容器而言,容器运行中有价值的数据并需要存储在外部的逻辑卷中。如果由容器直接使用共享存储系统,那么每次容器启动后都需要挂载,而且还需要具备与外界通信的能力,不仅繁琐,而且损失性能。
  • 针对这种需求,docker推出了卷管理系统,在容器创建时直接使用宿主机的存储系统,当容器结束运行时,不会删除卷中的数据。
    Docker——Docker 容器数据卷(Volumes)_第1张图片
  • 如图中,宿主机将远程NFS服务器中的数据盘挂载到本地/data/目录下,创建httpd容器时,将本地的/data/盘映射到容器中的网站根目录:/data/html中。
  • 当httpd容器挂掉后,无论在哪台服务器,只要满足宿主机挂载NFS存储,并且httpd容器映射网站根目录到/data/html即可。针对不需要持久化存储的应用,则可以不使用存储卷管理。
  • 将宿主机上的目录挂载到容器中有两种方式:
    • Bind mount volume
      手动指定宿主机目录和容器中目录的映射关系,或使用容器编排工具(k8s或者docker-compose)指定
    • Docker-managed volume
      Docker自动管理的挂载关系,这种情况下宿主机目录不固定,后期维护成本高,仅用于存放一些临时数据

使用数据卷

直接使用命令来挂载 -v
docker run -it -p 主机端口:容器内端口
docker run -it -v 主机目录:容器内目录

docker run -it -v /home/ceshi:/home centos /bin/bash

docker inspect 容器id 	可以查看挂载信息
docker inspect 39f2fc482f42
...
"Mounts": [		挂载
            {
     
                "Type": "bind",
                "Source": "/home/ceshi",	主机内地址
                "Destination": "/home",		docker容器内的地址
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
...

测试,我们在主机的/home/ceshi下创建文件
[root@docker ceshi]# touch maomao.py

容器内数据同步
[root@39f2fc482f42 home]# ls
maomao.py

然后我们在容器内创建文件
[root@39f2fc482f42 home]# touch zhuzhu.py

主机内也同步了文件
[root@docker ceshi]# ls
maomao.py  zhuzhu.py

再次测试
将容器关闭,然后在maomao.py里面写入代码,再启动容器验证数据是否同步

vim maomao.py
#!/usr/bin/python3
print('hello maomao')

[root@docker ceshi]# python3 maomao.py 
hello maomao

验证成功
[root@39f2fc482f42 home]# cat maomao.py 
#!/usr/bin/python3
print('hello maomao')

实现mysql数据同步

搜索镜像
docker search mysql --limit 2

下载镜像
docker pull mysql:5.7

开启mysql容器
docker run -d -p 3310:3306 -v /home/mysql/my.cnf:/etc/my.cnf -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 --name mysql01 mysql:5.7

测试能否连接mysql

Docker——Docker 容器数据卷(Volumes)_第2张图片
Docker——Docker 容器数据卷(Volumes)_第3张图片

我们进入容器 连接数据库创建一个库
docker exec -it mysql01 /bin/bash

root@fecdbe5b8949:/# mysql -uroot -p
Enter password:

mysql> create database maomao;

查看主机挂载点
[root@docker data]# ls
auto.cnf    client-cert.pem  ibdata1      ibtmp1  performance_schema  server-cert.pem
ca-key.pem  client-key.pem   ib_logfile0  maomao  private_key.pem     server-key.pem
ca.pem      ib_buffer_pool   ib_logfile1  mysql   public_key.pem      sys

里面有maomao这个文件夹 就是容器内创建的库

最后删除容器
docker stop mysql01

docker rm mysql01

发现,挂载到本地的数据卷依然没有丢失,这就实现了容器数据持久化功能

具名挂载和匿名挂载

匿名挂载

-v 容器内地址
-P 随机映射端口
docker run -d -P --name nginx01 -v /etc/nginx nginx

查看所有volume的情况
docker volume ls
DRIVER    VOLUME NAME
local     9de966bc2f690dad1bc0aca3a374686d84f03e8e8bd32bfbefe5c663f52d1ed2
local     783326254c48003588c1633d52fd85579b07a0dd8fc3ef9e379cd9613d3ed0c7
local     a762d81d21a44050086711739c06ebed8426c1b118951766b1ad04421575f557

这种就是匿名挂载,我们在-v后 只写了容器内的地址,没有写容器外的地址

具名挂载

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

发现Volume name 变成了我们自己命名的name
docker volume ls
DRIVER    VOLUME NAME
local     9de966bc2f690dad1bc0aca3a374686d84f03e8e8bd32bfbefe5c663f52d1ed2
local     783326254c48003588c1633d52fd85579b07a0dd8fc3ef9e379cd9613d3ed0c7
local     a762d81d21a44050086711739c06ebed8426c1b118951766b1ad04421575f557
local     juming-nginx

查看挂载路径
docker volume inspect 挂载名字

docker volume inspect juming-nginx
[
    {
     
        "CreatedAt": "2021-04-22T10:52:20-04:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
        "Name": "juming-nginx",
        "Options": null,
        "Scope": "local"
    }
]

Mountpoint 就是挂载点

[root@docker ~]# cd /var/lib/docker/volumes/juming-nginx/_data/
[root@docker _data]# ls
conf.d  fastcgi_params  koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params  uwsgi_params  win-utf
  • 所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxx/_data

  • 我们通过具名挂载可以方便的找到我们的一个卷,大多数情况都使用具名挂载

  • 如何确定具名挂载或者匿名挂载,还是指定路径挂载

    -v 容器内地址     		# 是匿名挂载
    -v 卷名:容器内地址		# 是具名挂载
    -v /宿主机路径:/容器内地址	# 是指定路径挂载
    

补充:

通过-v容器内路径:ro/rw改变读写权限
ro readonly		只读
rw readwrite	可读可写

一旦这个了设置了容器权限,容器对我们挂载出来的内容就有限定了!
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx:rw nginx

只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!

DockerFile里写Volumes配置

Dockerfile就是用来构建docker镜像的构建文件!命令脚本!通过脚本可以生成镜像

创建一个写dockerfile的目录
mkdir docker-volume

cd !$

编写dockerfile
vim dockerfile1

FROM centos

VOLUME ["volume01","volume02"]

CMD echo "hello world"
CMD /bin/bash

通过dockerfile创建镜像
-f 是指定脚本文件
-t 是生成镜像 后面跟镜像名字
最后的 . 是之当前目录的意思 或者写绝对路径也可以如 ./home/docker-volume

docker build -f dockerfile1 -t maomao_centos:1.0 .

Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 300e315adb2f
Step 2/4 : VOLUME ["volume01","volume02"]
 ---> Running in 04ae767b3fc3
Removing intermediate container 04ae767b3fc3
 ---> 90600bc216f4
Step 3/4 : CMD echo "hello world"
 ---> Running in 2488826ba14a
Removing intermediate container 2488826ba14a
 ---> 261164acfcf7
Step 4/4 : CMD /bin/bash
 ---> Running in 2df546baf492
Removing intermediate container 2df546baf492
 ---> f54c4d94f07b
Successfully built f54c4d94f07b
Successfully tagged maomao_centos:1.0
  1. 基础镜像 From centos
  2. 通过volumes挂载
  3. 执行内部命令
  4. 进入当前的/bin/bash
查看构建的镜像
docker images

REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
maomao_centos         1.0       f54c4d94f07b   3 minutes ago   209MB

开启容器
docker run -it --name niu f54c4d94f07b /bin/bash

ls -l
drwxr-xr-x   2 root root   6 Apr 23 03:55 volume01
drwxr-xr-x   2 root root   6 Apr 23 03:55 volume02

这两个目录就是我们生成镜像时自动挂载的,数据卷目录
这个卷和容器外部一定有一个同步的目录
并且dockerfile里面写的挂载是一个匿名挂载

cd volume01

在挂载点写一个文件
vim container.py

#! /usr/bin/python3
i = 0
num = int(input('high:'))
j = num
while i < num:
    i += 1
    j -= 1
    print(j * ' ' + (2*i-1)*'*')

在外部查看容器信息
docker inspect 7b12b042fbd4

"Mounts": [
            {
     
                "Type": "volume",
                "Name": "ccf9df5be200fb23d40c3e7d02ff7d7c77cfe52d82c8925b426465a018237ad0",
                "Source": "/var/lib/docker/volumes/ccf9df5be200fb23d40c3e7d02ff7d7c77cfe52d82c8925b426465a018237ad0/_data",
                "Destination": "volume02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
     
                "Type": "volume",
                "Name": "cf59ff76f95694ce2a8fc571048cee5373dc76759ce534f2be6e94a5cb42690c",
                "Source": "/var/lib/docker/volumes/cf59ff76f95694ce2a8fc571048cee5373dc76759ce534f2be6e94a5cb42690c/_data",
                "Destination": "volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

显示了挂载位置

cd /var/lib/docker/volumes/cf59ff76f95694ce2a8fc571048cee5373dc76759ce534f2be6e94a5cb42690c/_data

[root@docker _data]# ls
container.py
[root@docker _data]# python3 container.py 
high:5
    *
   ***
  *****
 *******
*********

多个数据卷容器挂载

实验一:
创建两个容器 子容器挂载到父容器上面 查看数据是否同步

启动父容器
docker run -it --name docker01 maomao_centos:1.0 /bin/bash

启动子容器 挂载到父容器
docker run -it --name docker02 --volumes-from docker01 maomao_centos:1.0 /bin/bash

在父容器的volume01里面创建文件
[root@8b03c7d68afd /]# cd volume01/
[root@8b03c7d68afd volume01]# ls
[root@8b03c7d68afd volume01]# touch docker01

在子容器的volume01里会同步文件
[root@ca2db151b708 /]# cd volume01/

docker01创建的内容同步到docker2上
[root@ca2db151b708 volume01]# ls
docker01

实验二:
创建第三个容器挂载到第二个容器上

创建docker03挂载到docker02上
docker run -it --name docker03 --volumes-from docker02 maomao_centos:1.0 /bin/bash

[root@424d9d12c37e /]# cd volume01/
[root@424d9d12c37e volume01]# ls
docker01
[root@424d9d12c37e volume01]# touch docker03

[root@ca2db151b708 volume01]# ls
docker01  docker03

将docker01删除
docker rm -f docker01

docker02和docker03数据依然存在

实验三:
使用具名挂载 然后实现两个容器的数据同步

docker run -it -P --name nginx01 -v nginx:/etc/nginx nginx /bin/bash

查看具名挂载目录
docker inspect e1dd0b5ff9e5

cd /var/lib/docker/volumes/nginx/_data

第二个容器挂载到第一个容器上
docker run -it -P --name nginx02 --volumes-from nginx01 nginx /bin/bash

在具名挂载的目录里面修改nginx.conf配置文件
vim nginx.conf 
events {
     
    worker_connections 4096;
}

查看两个容器的配置文件
root@e1dd0b5ff9e5:/etc/nginx# cat nginx.conf 
events {
     
    worker_connections 4096;
}
两个容器配置文件都被改变 说明实现两个容器的数据同步

多个mysql实现数据共享

开启第一个mysql容器 并挂载
docker run -d -p 3310:3306 -v conf:/etc/mysql/conf.d -v mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 --name mysql01 mysql:5.7

docker exec -it mysql01 /bin/bash

开启第二个mysql容器 并挂载到第一个mysql上

docker run -d -p 3311:3307 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01  mysql:5.7
  • 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器为止
  • 一旦持久化到本地,本地的数据不会因为容器被删除而删除

你可能感兴趣的:(Docker,docker,linux,volumes)