1、Docker数据管理
如果正在运行中的容器如果生成了新的数据或者修改了现有的一个已经存在的文件内容,那么新产生的数据就会被复制到读写层进行持久化保存,这个读写层的话也就是容器的工作目录,这就是写时复制(COW)copy on write的机制。
1.1、Docker默认的数据存储类型
在没有设置数据卷或其他数据存储方式时,Docker是无法对容器中新产生的数据进行持久化保存。暂时保存在读写层的数据也会随着容器的删除而被删除,这样的话对于MySQL这类要求数据能做到持久化保存的容器是极为不利的。
1.2、Docker数据持久化存储的类型
Docker要使数据持久化保存的话,现在Docker的数据存储类型有数据卷、文件挂载和数据卷容器这三种类型。
1.2.1、数据卷
数据卷实际上就是宿主机上的文件或目录,可以被直接挂载到容器中,容器中产生的新数据也都会直接保存到宿主机的挂载目录中,从而实现容器数据的持久化保存。
数据卷的特点:
- 数据卷是宿主机的目录或者文件,可以在多个容器之间共同使用;
- 在宿主机上对数据卷中的数据做出更改后,所有使用该数据卷的容器了也会立即更新;
- 数据卷的数据可以持久保存,即使删除使用该数据卷的容器也不会受到影响;
- 在容器里写入的数据不会影响到镜像本身。
适合数据卷的服务类型:
在生产环境中,我们是需要针对不同的类型服务来使用不同类型的数据存储做出相应的规划,从而保证服务的可扩展性、稳定性和数据的安全性。
不是所有的服务都是要使用到数据卷的,就例如下面这图一样,从左边到右边是无存储到有存储的需求,总下面到上面是从无http请求的状态到有http请求状态,根据实际要求来确定服务是否需要使用数据卷。
数据卷的使用场景:
- 日志输出
- 静态web文件
- 应用的配置文件
- 多容器之间的目录或文件共享
1.2.2、文件挂载
文件挂载的话一般用于一些配置文件和一些很少改动的文件场景,比如nginx配置文件、tomcat配置文件等等一些其它服务的配置文件,这种类型比较少用。
1.2.3、数据卷容器
数据卷容器的功能时可以让数据在多个docker容器之间共享,即可以让B容器访问A容器的内容,也可以让C容器访问A容器的内容。
2、MySQL容器的数据持久保存
2.1、下载MySQL镜像
root@node1:~# docker images REPOSITORY TAG IMAGE ID CREATED SIZE root@node1:~# docker pull mysql:5.7.39 5.7.39: Pulling from library/mysql 66fb34780033: Pull complete ef4ccd63cdb4: Pull complete d6f28a94c51f: Pull complete 7feea2a503b5: Pull complete 71dd5852ecd9: Pull complete 2ff5c3b24fd5: Pull complete 88a546386a61: Pull complete 65b18297cf83: Pull complete d64f23335fb8: Pull complete 6ba4171261fa: Pull complete 96dcc6c8de93: Pull complete Digest: sha256:b3a86578a582617214477d91e47e850f9e18df0b5d1644fb2d96d91a340b8972 Status: Downloaded newer image for mysql:5.7.39 docker.io/library/mysql:5.7.39 root@node1:~# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7.39 3147495b3a5c 8 days ago 431MB
2.2、未设置数据存储的MySQL容器
#使用刚刚下载的镜像启动一个容器,并设置root用户的登陆密码
root@node1:~# docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD="wm@521314" --name mysql-nodatadisk mysql:5.7.39
20e52715841c820658528fd4a960fc11399e0300cbb8903cb319ae66d206cd70
#使用客户端测试
root@node2:~# apt -y install mysql-client #安装mysql客户端
root@node2:~# mysql -uroot -p"wm@521314" -h 10.0.0.100
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.39 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database zg;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| zg |
+--------------------+
5 rows in set (0.00 sec)
#当删除并启动新的容器时
root@node1:~# docker rm -f 20e52715841c
20e52715841c
root@node1:~# docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD="wm@521314" --name mysql-nodatadisk mysql:5.7.39
615b31343cb631b208dc1dc94e95e40b369a09e54677364f6caaac2be0f8fd96
这时会发现重新创建后的容器是没有刚刚创建的数据库的,容器之间是分离的
root@node2:~# mysql -uroot -p"wm@521314" -h10.0.0.100
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.39 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql>
2.3、设置MySQL的数据持久保存
2.3.1、数据持久保存数据的原理
可以在宿主机上使用docker inspect 容器name/容器ID来查看刚刚创建的MySQL容器的相关信息,数据主要是在LowerDir、MergedDir、UpperDir和WorkDir这几个目录中。
root@node1:~# docker inspect mysql-nodatadisk | grep -E "LowerDir|MergedDir|UpperDir|WorkDir"
"LowerDir": "/var/lib/docker/overlay2/611031be59b9e45ea0798db055c61bd6eb86febd30996c5e15093b2329816040-init/diff:/var/lib/docker/overlay2/aa1d02f9d4fce68268e13783ede37f54577d06b72ec21d777285402a48330dff/diff:/var/lib/docker/overlay2/5afa170f977d7db4b5e256f7d252a49ff86757e5737f5e0d6951a4284d7fabd4/diff:/var/lib/docker/overlay2/a26b4fde1ffca9fd9351f641ed9a1d394170f35610a82887a8363deb5ae6b5e3/diff:/var/lib/docker/overlay2/80efbab75da2389f9156a632f949fb0d0897f865b3fc93224462b6ed99ade5d6/diff:/var/lib/docker/overlay2/17df76ad20fab09cde957c2e83c44bafb94c79ee95b266deff8bcf923b3fb199/diff:/var/lib/docker/overlay2/2afd02feedfff72c722f2bd225d949a94e7739c5112e0cd23e780b7a714adc0e/diff:/var/lib/docker/overlay2/f446411cba727d527a8b0da16d95ba418cf01352beb46b99e56a40a575e5c687/diff:/var/lib/docker/overlay2/792b32bae9ed637f65eedef65e44c643fcd2d2e776717db5497de1d471758a93/diff:/var/lib/docker/overlay2/31ca30a45f3764c6e96dfee6933cc851f52d211f2abe7a8ced845e90ab584dd1/diff:/var/lib/docker/overlay2/6e54f3e3cfa836c1270b45244a226fed31068863b4be29e0ed755286449890a7/diff:/var/lib/docker/overlay2/3e45abad9fa2f4a0c227c7a7cad5cdee75f07973ce4e56f671c1841a202e82c3/diff",
"MergedDir": "/var/lib/docker/overlay2/611031be59b9e45ea0798db055c61bd6eb86febd30996c5e15093b2329816040/merged",
"UpperDir": "/var/lib/docker/overlay2/611031be59b9e45ea0798db055c61bd6eb86febd30996c5e15093b2329816040/diff",
"WorkDir": "/var/lib/docker/overlay2/611031be59b9e45ea0798db055c61bd6eb86febd30996c5e15093b2329816040/work"
这四个目录简介:
LowerDir:这个目录是容器所使用的镜像,是只读的;
MergedDir:这个目录指的是容器的最上层,这是可以进行读写的操作的;
UpperDir:这个目录是容器的文件系统,使用Union FS将LowerDir和UpperDir合并给容器使用
WorkDir:这个目录是容器在宿主机上的工作目录
当我们没有设置数据存储的时候,删除容器的话也就是说/var/lib/docker/overlay2/目录下创建的容器可写层也会跟随这容器删除而删除;如果使用了数据存储的话,可以将容器后面产生的数据保存到数据卷中,即使容器删了,数据卷也还是在的,这样的话就可以在创建一个容器指定这个数据卷就好了,这样数据也就不会丢了,从而使得数据得到了持久保存。
2.3.2、创建数据卷来保存容器的数据
注意: 启动MySQL容器时是要设置root的登陆密码的,没有设置的话容器是启动不了的。
#在宿主机上创建一个目录来做数据卷,并创建一个MySQL容器使用这个数据卷
root@node1:~# docker rm -f `docker ps -aq` #删除正在运行或停止的容器,这里就一个我刚刚创建的一个测试容器
615b31343cb6
root@node1:~# mkdir -p /data/mysql-data
root@node1:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7.39 3147495b3a5c 8 days ago 431MB
root@node1:~# docker run -d -p 3306:3306 -v /data/mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD="wm@521314" --name mysql-datadisk mysql:5.7.39 #-v选项就是指定要使用的数据卷
c007b3fad34ab42072a44529a1f18778d9e1a717d2f9c0d70f070540f4fdaea4
root@node1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c007b3fad34a mysql:5.7.39 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:3306->3306/tcp, 33060/tcp mysql-datadisk
#在客户端上创建一个测试数据库
root@node2:~# mysql -uroot -p"wm@521314" -h10.0.0.100
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.39 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database zg;
Query OK, 1 row affected (0.01 sec)
这时/data/mysql-data这个目录下是会多一个zg的目录的
root@node1:~# ll /data/mysql-data/
total 188488
drwxr-xr-x 6 wm root 4096 Aug 4 18:50 ./
drwxr-xr-x 3 root root 4096 Aug 4 18:40 ../
-rw-r----- 1 wm wm 56 Aug 4 18:46 auto.cnf
-rw------- 1 wm wm 1680 Aug 4 18:46 ca-key.pem
-rw-r--r-- 1 wm wm 1112 Aug 4 18:46 ca.pem
-rw-r--r-- 1 wm wm 1112 Aug 4 18:46 client-cert.pem
-rw------- 1 wm wm 1680 Aug 4 18:46 client-key.pem
-rw-r----- 1 wm wm 1318 Aug 4 18:46 ib_buffer_pool
-rw-r----- 1 wm wm 79691776 Aug 4 18:46 ibdata1
-rw-r----- 1 wm wm 50331648 Aug 4 18:46 ib_logfile0
-rw-r----- 1 wm wm 50331648 Aug 4 18:46 ib_logfile1
-rw-r----- 1 wm wm 12582912 Aug 4 18:46 ibtmp1
drwxr-x--- 2 wm wm 4096 Aug 4 18:46 mysql/
lrwxrwxrwx 1 wm wm 27 Aug 4 18:46 mysql.sock -> /var/run/mysqld/mysqld.sock
drwxr-x--- 2 wm wm 4096 Aug 4 18:46 performance_schema/
-rw------- 1 wm wm 1676 Aug 4 18:46 private_key.pem
-rw-r--r-- 1 wm wm 452 Aug 4 18:46 public_key.pem
-rw-r--r-- 1 wm wm 1112 Aug 4 18:46 server-cert.pem
-rw------- 1 wm wm 1676 Aug 4 18:46 server-key.pem
drwxr-x--- 2 wm wm 12288 Aug 4 18:46 sys/
drwxr-x--- 2 wm wm 4096 Aug 4 18:50 zg/
2.3.3、删除刚刚创建的容器并重新启动一个新的容器
#在宿主机上删除刚刚创建挂载数据卷的容器,在查看/data/mysql-data目录,之前创建的zg数据库的目录还是会存在的。
root@node1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c007b3fad34a mysql:5.7.39 "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:3306->3306/tcp, 33060/tcp mysql-datadisk
root@node1:~# docker rm -f mysql-datadisk
mysql-datadisk
root@node1:~# ll /data/mysql-data/
total 188488
drwxr-xr-x 6 wm root 4096 Aug 4 18:50 ./
drwxr-xr-x 3 root root 4096 Aug 4 18:40 ../
-rw-r----- 1 wm wm 56 Aug 4 18:46 auto.cnf
-rw------- 1 wm wm 1680 Aug 4 18:46 ca-key.pem
-rw-r--r-- 1 wm wm 1112 Aug 4 18:46 ca.pem
-rw-r--r-- 1 wm wm 1112 Aug 4 18:46 client-cert.pem
-rw------- 1 wm wm 1680 Aug 4 18:46 client-key.pem
-rw-r----- 1 wm wm 1318 Aug 4 18:46 ib_buffer_pool
-rw-r----- 1 wm wm 79691776 Aug 4 18:46 ibdata1
-rw-r----- 1 wm wm 50331648 Aug 4 18:46 ib_logfile0
-rw-r----- 1 wm wm 50331648 Aug 4 18:46 ib_logfile1
-rw-r----- 1 wm wm 12582912 Aug 4 18:46 ibtmp1
drwxr-x--- 2 wm wm 4096 Aug 4 18:46 mysql/
lrwxrwxrwx 1 wm wm 27 Aug 4 18:46 mysql.sock -> /var/run/mysqld/mysqld.sock
drwxr-x--- 2 wm wm 4096 Aug 4 18:46 performance_schema/
-rw------- 1 wm wm 1676 Aug 4 18:46 private_key.pem
-rw-r--r-- 1 wm wm 452 Aug 4 18:46 public_key.pem
-rw-r--r-- 1 wm wm 1112 Aug 4 18:46 server-cert.pem
-rw------- 1 wm wm 1676 Aug 4 18:46 server-key.pem
drwxr-x--- 2 wm wm 12288 Aug 4 18:46 sys/
drwxr-x--- 2 wm wm 4096 Aug 4 18:50 zg/
#在使用/data/mysql-data目录作为数据卷在重新启动一个新的数据库容器,创建完后再使用mysql客户端服务器登陆上查看数据是否存在
root@node1:~# docker run -d -p 3306:3306 -v /data/mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD="wm@521314" --name mysql1-datadisk mysql:5.7.39
178aa3d722b76631236006b25118706e4d8f34105a36475158c61da4346b8238
root@node1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
178aa3d722b7 mysql:5.7.39 "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp mysql1-datadisk
root@node2:~# mysql -uroot -p"wm@521314" -h10.0.0.100
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.39 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| zg |
+--------------------+
5 rows in set (0.00 sec)
mysql>
从上面的测试发现,使用了数据存储创建的容器,即使删除了容器数据也是会存在的,这样的话就实现了容器的数据持久保存。