Docker 12 容器数据卷

由来

Docker 是将应用和环境打包成一个镜像。

这样,数据就不应该在容器中,否则容器删除,数据就会丢失,有着非常大的风险。

为此,容器和主机之间需要有一个数据共享技术,使得在 Docker 容器中产生的数据能够同步到本地。

这就是容器数据卷技术。其本质上是一个目录挂载,将容器内的目录挂载到主机上。

使用

命令方式

语法

docker run -v 主机目录:容器目录

示例

  1. 查看主机 /home 目录。
[root@sail ~]# ls /home
admin  f2  f3  sail  test.java
  1. 以交互模式启动 centos 镜像。
[root@sail ~]# docker run -it -v /home/ceshi:/home centos /bin/bash
[root@ec95646b1a4c /]# 
  1. 新开一个窗口查看容器详情。

Docker 12 容器数据卷

可以看到,Mounts 下的 Source 即为设置的主机目录、Destination 即为设置的容器目录,他们已经绑定在了一起。

  1. 在主机中查看 /home
[root@sail /]# cd /home
[root@sail home]# ls
admin  ceshi  f2  f3  sail  test.java

可以看到,主机上的 /home 下已经有了 ceshi 目录。说明容器一经启动,就会在主机生成对应的挂载目录。

  1. 在容器中的 /home 下新建一个文件。
[root@ec95646b1a4c /]# cd /home
[root@ec95646b1a4c home]# ls
[root@ec95646b1a4c home]# touch test.java
[root@ec95646b1a4c home]# ls
test.java
  1. 查看主机的 ceshi 目录。
[root@sail home]# cd ceshi
[root@sail ceshi]# ls
test.java

可以发现,此时主机中的 ceshi 目录下也有了这个文件。

由此实现了容器到主机的数据同步。

  1. 关闭容器。
[root@ec95646b1a4c home]# exit
exit
  1. 修改主机中 /home/ceshi/test.java 文件的内容。
[root@sail ceshi]# vim test.java
# 此处编辑文件过程省略
[root@sail ceshi]# cat test.java
hello sail
  1. 重启容器。
[root@sail ~]# docker start ec95646b1a4c
ec95646b1a4c
[root@sail ~]# docker ps
CONTAINER ID   IMAGE          COMMAND             CREATED          STATUS         PORTS                    NAMES
ec95646b1a4c   centos         "/bin/bash"         19 minutes ago   Up 5 seconds                            charming_cartwright
  1. 查看 /home 下的文件。
[root@sail ~]# docker exec -it ec95646b1a4c /bin/bash
[root@ec95646b1a4c /]# cd /home
[root@ec95646b1a4c home]# ls
test.java
[root@ec95646b1a4c home]# cat test.java
hello sail

可以看到,此时容器中的文件也更改了。

由此实现了主机到容器的数据同步。

由此可见,数据卷技术实现的是双向同步。

权限设置

在使用命令方式设置卷时,还可以指定权限,以此保证数据安全。

参数

  • ro(readonly):只读。
  • rw(readwrite):可读可写。

示例

  1. 以数据卷只读权限启动镜像。
[root@sail mysql]# docker run -it -v /home/sail:/home:ro centos /bin/bash
  1. 新建文件测试。
[root@02ef70c94920 home]# touch test.java
touch: cannot touch 'test.java': Read-only file system

可以看出,容器内部该目录是没有写入权限的。

  1. 以数据卷可读可写的权限启动镜像。
[root@sail mysql]# docker run -it -v /home/sail:/home:rw centos /bin/bash
[root@48678e08f868 /]# cd /home
[root@48678e08f868 home]# touch test.java
[root@48678e08f868 home]# ls
apache-tomcat-9.0.55.tar.gz  jdk-8u301-linux-x64.rpm  test.java
  1. 新建文件测试。
[root@sail mysql]# docker run -it -v /home/sail:/home:rw centos /bin/bash
[root@48678e08f868 /]# cd /home
[root@48678e08f868 home]# touch test.java
[root@48678e08f868 home]# ls
apache-tomcat-9.0.55.tar.gz  jdk-8u301-linux-x64.rpm  test.java

可以看出,容器内部该目录写入是没有问题的。

前面我们没有指定权限也可以写入,由此可见,数据卷默认是具有读写权限的。

具名挂载

示例

  1. 启动镜像时只定义主机卷名称,不指定挂载目录。
[root@sail mysql]# docker run -it -v my-centos:/home centos /bin/bash
[root@3cf74e9e6973 /]#
  1. 查看目前挂载的卷。
# 使用 Ctrl + P + Q 不退出容器的情况下回到主机目录。
[root@sail mysql]# docker volume ls
DRIVER    VOLUME NAME
local     my-centos
  1. 查看卷的详情。
[root@sail mysql]# docker volume inspect my-centos
[
    {
        "CreatedAt": "2021-12-20T16:55:35+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/my-centos/_data",
        "Name": "my-centos",
        "Options": null,
        "Scope": "local"
    }
]

可以看出,卷挂载在 /var/lib/docker/volumes/卷名/_data 目录下。

在没有指定主机挂载目录的情况下,会默认挂载到该目录。

由于指定了卷名,所以这种方式称为具名挂载。

匿名挂载

示例

  1. 启动镜像时只指定容器目录。
[root@sail mysql]# docker run -it -v /home centos /bin/bash
  1. 查看目前挂载的卷。
[root@sail mysql]# docker volume ls
DRIVER    VOLUME NAME
local     159830cf55550c9a39e845c1d96aa04cc762005bc0c64d15d5066834b47df940
  1. 查看卷的详情。
[root@sail mysql]# docker volume inspect 159830cf55550c9a39e845c1d96aa04cc762005bc0c64d15d5066834b47df940
[
    {
        "CreatedAt": "2021-12-20T17:05:23+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/159830cf55550c9a39e845c1d96aa04cc762005bc0c64d15d5066834b47df940/_data",
        "Name": "159830cf55550c9a39e845c1d96aa04cc762005bc0c64d15d5066834b47df940",
        "Options": null,
        "Scope": "local"
    }
]

可以看出,卷也是挂载在 /var/lib/docker/volumes/xxx/_data 目录下。

在没有指定主机挂载目录的情况下,会默认挂载到该目录。

由于没有指定卷名,所以这种方式称为匿名挂载。

由此可见,只有指定主机目录的情况下会挂载到指定目录,否则都会挂载到默认目录。

实战

mysql数据同步

数据库中的数据极为重要,必须同步到主机,否则将会有非常大的数据丢失风险。

这里以 mysql 镜像为例演示数据同步的过程。

  1. 启动 mysql 镜像。
[root@sail ~]# 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
Unable to find image 'mysql:5.7' locally
5.7: Pulling from library/mysql
ffbb094f4f9e: Pull complete 
df186527fc46: Pull complete 
fa362a6aa7bd: Pull complete 
5af7cb1a200e: Pull complete 
949da226cc6d: Pull complete 
bce007079ee9: Pull complete 
eab9f076e5a3: Pull complete 
c7b24c3f27af: Pull complete 
6fc26ff6705a: Pull complete 
bec5cdb5e7f7: Pull complete 
6c1cb25f7525: Pull complete 
Digest: sha256:d1cc87a3bd5dc07defc837bc9084f748a130606ff41923f46dec1986e0dc828d
Status: Downloaded newer image for mysql:5.7
a016e564d977550e475474556cfd033fb1c731002381bc9f9544c63fccb7f60c

其中 -e 为环境配置。安装启动 mysql 需要配置密码。

  1. 使用docker inspect查看挂载情况。

Docker 12 容器数据卷

可以看见,已经生成了两个目录的挂载。

  1. 查看主机同步的目录。
[root@sail ~]# cd /home
[root@sail home]# ls
admin  ceshi  f2  f3  mysql  sail  test.java
[root@sail home]# cd mysql
[root@sail mysql]# ls
conf  data

可以看到,主机已经同步了容器挂载的目录。

  1. 使用数据库管理工具连接测试(这里使用 IDEA 自带的数据库工具)。

Docker 12 容器数据卷

至此,mysql 数据同步完成。

上一篇:inline-block元素没有对齐的解决方案及总结


下一篇:动态设计模式