说明

  • 关于容器数据卷,这做一下简单说明
    容器层是数据是临时的,当我们删除了容器的话,对应的容器层数据是会被一起删除掉。
    所以这样的默认机制是不安全的,比如某个容器运行了一段时间,里面已经挺多数据了,但不小心将容器删除了,那么里面的数据也会被跟着删除。 所以我们需要将容器的数据同步到主机上,这样的容器数据才是安全的。【下面 会说步骤的】

  • 数据同步到主机上就是在创建的时候加一个参数: -v file
    然后容器存储在file里面的文件就会被保留在主机上了==【注,仅仅是-v 后面的file文件中的数据会被同步到主机上,其他数据随着容器被删除而消失】==,保留到主机上的目录有2种方式,一种是默认生成的目录,一种是自定义目录,见下面。

主机默认生成存储目录

说明

  • 当我们创建容器的时候 -v 指定一个容器中的目录后,同时在本地会响应的生成一个随机ID的文件用来临时存储这个文件。
  • 注,容器存储id不是固定的,即使使用同样的参数创建容器,每次创建容器都会生成不同的存储ID。
  • 创建参数说明:-v file【这个file是容器中的存储文件夹,是文件夹!】

查看容器默认生成的存储ID

  • 命令:docker inspect NAMES |egrep -B 1 volume【docker ps查看names】
    如:下面中Name后面跟的就是默认生成的存储id了
[root@ccx volumes]# docker inspect d1 | egrep -B 1 volume
            {
                "Type": "volume",
                "Name": "da83526212497c34ed7eddcb803d192f80dab0812bf20957b961a605faf6dd3d",
                "Source": "/var/lib/docker/volumes/da83526212497c34ed7eddcb803d192f80dab0812bf20957b961a605faf6dd3d/_data",
[root@ccx volumes]# 

主机上查看默认路径

  • 需要先知道上面查询到的某容器生成的存储id
  • 主机默认存储路径:/var/lib/docker/volumes/ID/_data/ 【ID就是上面查询到的ID】
  • 其实这个/var/lib/docker/volumes/路径中的id内容是可以通过命令查看的
    命令是:docker volume list这里面显示的内容和上面路径中的内容一样
[root@ccx ~]# cd /var/lib/docker/volumes/
[root@ccx volumes]# ls
1a357f1b653a6425db41e623941831617ef8cc8d6346141bf54456da6c9e7e0a
3e3709b327a2221a40db1da5632c4323e493fa4cfed9d1619a0aab4434340520
7d514798b27d6d29e626592e51d5c31c68f1b3332a4e6a4fac3dd8f6e5af8a10
854e6f5d053ebe6b759baf488a9a2656d2528954b58b4b295e292ad20853227c
bfd01afaff30e2040931a49fa46b7b118448e92f52bae935162dcff9fe973a7c
da83526212497c34ed7eddcb803d192f80dab0812bf20957b961a605faf6dd3d
metadata.db
[root@ccx volumes]# docker volume list
DRIVER              VOLUME NAME
local               1a357f1b653a6425db41e623941831617ef8cc8d6346141bf54456da6c9e7e0a
local               3e3709b327a2221a40db1da5632c4323e493fa4cfed9d1619a0aab4434340520
local               7d514798b27d6d29e626592e51d5c31c68f1b3332a4e6a4fac3dd8f6e5af8a10
local               854e6f5d053ebe6b759baf488a9a2656d2528954b58b4b295e292ad20853227c
local               bfd01afaff30e2040931a49fa46b7b118448e92f52bae935162dcff9fe973a7c
local               da83526212497c34ed7eddcb803d192f80dab0812bf20957b961a605faf6dd3d
[root@ccx volumes]# 

创建测试

  • 如:我现在新建一个容器的时候,指定一个容器中存储目录 /ccx ,在里面随便写几个文件测试
[root@ccx ~]# docker run -dit --restart=always --name=d1 -v /ccx hub.c.163.com/library/centos
cf0548fc5a3e0808c70f0c41b2e9360f8bb8a034749f622320901ce639a5fc65
[root@ccx ~]# docker attach d1
[root@cf0548fc5a3e /]# touch /ccx/111.txt
[root@cf0548fc5a3e /]# touch /ccx/222.txt
[root@cf0548fc5a3e /]# ls /ccx
111.txt  222.txt
[root@cf0548fc5a3e /]# 
  • 然后我们到主机看下默认的存储文件
    可以看到在容器中创建的文件这儿已经能看到了
[root@ccx _data]# pwd
/var/lib/docker/volumes/da83526212497c34ed7eddcb803d192f80dab0812bf20957b961a605faf6dd3d/_data
[root@ccx _data]# ls
111.txt  222.txt
[root@ccx _data]# 
  • 当我们删除了容器,这个id里面的文件依然是存在的
[root@ccx _data]# pwd
/var/lib/docker/volumes/da83526212497c34ed7eddcb803d192f80dab0812bf20957b961a605faf6dd3d/_data
[root@ccx _data]# ls
111.txt  222.txt
[root@ccx _data]# docker ps
CONTAINER ID        IMAGE                          COMMAND             CREATED             STATUS              PORTS               NAMES
cf0548fc5a3e        hub.c.163.com/library/centos   "/bin/bash"         10 minutes ago      Up 11 seconds                           d1
[root@ccx _data]# docker rm d1 -f
d1
[root@ccx _data]# pwd
/var/lib/docker/volumes/da83526212497c34ed7eddcb803d192f80dab0812bf20957b961a605faf6dd3d/_data
[root@ccx _data]# ls
111.txt  222.txt
[root@ccx _data]#

主机指定存储目录

特别说明【重要】

  • 服务器的selinux一定要修改配置文件,改为disabled模式并重启服务器。
    如果不修改的话,会出现下面两种问题。 如果不想关闭selinux,可以使用下面创建数据卷的方式,那个对selinux没有限制。
[root@ccx ~]# cat /etc/selinux/config |grep SELINUX=
# SELINUX= can take one of these three values:
SELINUX=disabled
[root@ccx ~]# 
  • 如果selinux没有设置为disabled模式,可能会出现下面2种问题:

  • 1、创建容器以后,在容器中写入文件权限错误

[root@ccx ~]# docker run -it --name=d1 --rm -v /date:/ccx:rw hub.c.163.com/library/centos
[root@fdd812c31dc8 /]# touch /ccx/1    
touch: cannot touch '/ccx/1': Permission denied
[root@fdd812c31dc8 /]# 
  • 2、如果事先在主机目录上创建一个文件夹并写入文件,那么创建容器后会出现查看目录报 权限错误
[root@ccx ~]# mkdir /date
[root@ccx ~]# touch /date/hero.txt
[root@ccx ~]# touch /date/superhero.txt
[root@ccx ~]# docker run -it --restart=always --name=c1 -v /date:/ccx hub.c.163.com/library/centos
[root@f7c89ba1174f /]# cd /ccx
[root@f7c89ba1174f ccx]# ls
ls: cannot open directory .: Permission denied
[root@f7c89ba1174f ccx]# ls
ls: cannot open directory .: Permission denied
[root@f7c89ba1174f ccx]# exit
exit

说明

  • 就是创建容器的时候指定一个主机目录用来存储容器中的文件目录
  • 创建参数说明:-v 主机文件:容器文件:rw【权限默认是rw,可以不写,但如果想指定为ro,就需要加上去了】【这个文件是容文件夹,是文件夹!】
  • 这种指定就相当于mount挂载【下面展示的信息是我已经创建好容器的内容】
    可以查看的,d1是容器的NAMES
[root@ccx ~]# docker inspect d1 | egrep -A 4 Mounts
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/date",
                "Destination": "/ccx",
[root@ccx ~]# 

创建测试

  • 如:我现在新建一个容器的时候,指定一个容器中存储目录 /ccx 并让其存储在本地的/date目录中】,在里面随便写几个文件测试
    • 我先在主机上创建一个/date并随便写入几个文件【这个文件可以不用手动创建,创建容器的时候会自动创建
    • 然后我去容器中查看目录,能看到我在主机上创建的文件
    • 然后我再容器中创建几个文件,可以在主机上的这个目录看到这些文件
[root@ccx ~]# mkdir /date
[root@ccx ~]# touch /date/hero.txt /date/superhero.txt
[root@ccx ~]# docker run -it --restart=always --name=d1 -v /date:/ccx:rw hub.c.163.com/library/centos
[root@305175003c1d /]# cd /ccx
[root@305175003c1d ccx]# ls
hero.txt  superhero.txt
[root@305175003c1d ccx]# touch test.txt
[root@305175003c1d ccx]# exit
exit
[root@ccx ~]# cd /date
[root@ccx date]# ls
hero.txt  superhero.txt  test.txt
[root@ccx date]# 

创建数据卷并挂载到容器

这种和指定存储目录比起来,可能会更专业点吧。

创建一个数据卷

  • 命令:docker volume create 自定义卷名称
  • 查看卷:docker volume list
  • 如下:我创建了一个v1的数据卷
[root@ccx ~]# docker volume create v1
v1
[root@ccx ~]# 
[root@ccx ~]# docker volume list |  tail -n 2
local               da83526212497c34ed7eddcb803d192f80dab0812bf20957b961a605faf6dd3d
local               v1
[root@ccx ~]# 

查看数据卷的默认路径

  • 这个默认路径与默认卷处于同一目录,只是这个v1不会改变,原理其实和我们指定存储目录一样,只是路径变了而已。
  • 如下v1卷的默认路径为:Mountpoint项
[root@ccx ~]# docker volume inspect v1
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/v1/_data",
        "Name": "v1",
        "Options": {},
        "Scope": "local"
    }
]
[root@ccx ~]#

创建容器时指定数据卷

  • 这个和主机指定存储目录挂载的方式是一样的,只是主机路径变成之前创建的卷名了而已。
  • 如:我讲主机的v1卷挂在到容器中的/ccx目录,并在里面创建一个文件,然后回到主机上查看这个卷的内容,发现同步的。
[root@ccx ~]# docker run -it --restart=always --name=d1 -v v1:/ccx hub.c.163.com/library/centos
[root@2c7ff6e87a94 /]# touch /ccx/hero.txt
[root@2c7ff6e87a94 /]# exit
exit
[root@ccx ~]# ls /var/lib/docker/volumes/v1/_data/
hero.txt
[root@ccx ~]# 

指定主机目录的特别使用场景

  • 上面中:主机指定存储目录和创建数据卷并挂载到容器方法均一样

  • 容器之间数据同步 【也就这一个使用方式比较特殊罢了】
    比如将多个容器的数据目录均使用同一个数据卷,那么容器间看到的数据都是一样的。

- 将数据写入到主机目录后,容器中的这个目录内容会同步变化,这个需要了解一下。

  • 数据持久化

mysql数据备份特别说明

流程

  • 因为mysql的默认存放路径为:/var/lib/mysql
    所以我们只需要在创建的时候将数据卷同步到上面路径上,即可实现mysql的数据自动同步了

  • 如,我创建mysql容器的时候将本地的/date【建议手动mkdir创建好该文件】同步到容器中的/var/lib/mysql目录,这样创建的时候数据就会自动同步到本地的/date目录中了
    注:本地的目录中必须是空的,如果有内容先执行:rm -rf /date1/*

[root@ccx date]# rm -rf /date/*
[root@ccx date]# docker run -dit --restart=always --name=db -e MYSQL_ROOT_PASSWORD=passwd -v /date:/var/lib/mysql/:rw hub.c.163.com/library/mysql
8d27c14f23c60e7cee5a34ac135f3c1e09fbfca31e378d632b9fb383953f705a
[root@ccx date]# ls
auto.cnf        ibdata1      ib_logfile1  mysql               sys
ib_buffer_pool  ib_logfile0  ibtmp1       performance_schema
[root@ccx date]# 
  • 后续登陆这个容器的方法和测试见下面
    先在客户端上装 mysql,查看容器的ip,然后就可以登陆了
    如果密码是p开头,那么是不能直接-p后面跟密码的,如我密码是passwd,如果我用-ppasswd登陆就会报错,必须-p然后手动输入密码才行。
    我下面就是登陆进容器以后,创建了一个aa表再里面写如数据后退出并查看本地文件,确实aa表有出现了。
[root@ccx date]# docker inspect db | grep ipaddress -i
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.3",
                    "IPAddress": "172.17.0.3",
[root@ccx date]# cd
[root@ccx ~]# mysql -uroot -ppasswd -h 127.17.0.3
ERROR 2003 (HY000): Can't connect to MySQL server on '127.17.0.3' (111)
[root@ccx ~]# mysql -uroot -h 172.17.0.3
ERROR 1045 (28000): Access denied for user 'root'@'172.17.0.1' (using password: NO)
[root@ccx ~]# mysql -uroot -h 172.17.0.3 -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.18 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> show datebash;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'datebash' at line 1
MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

MySQL [(none)]> create database aa;
Query OK, 1 row affected (0.00 sec)

MySQL [(none)]> use aa;
Database changed
MySQL [aa]> create table aa(id int,name varchar(10));
Query OK, 0 rows affected (0.01 sec)

MySQL [aa]> insert into aa values (1,'ccx');
Query OK, 1 row affected (0.01 sec)

MySQL [aa]> show tables;
+--------------+
| Tables_in_aa |
+--------------+
| aa           |
+--------------+
1 row in set (0.00 sec)

MySQL [aa]> select * from aa;
+------+------+
| id   | name |
+------+------+
|    1 | ccx  |
+------+------+
1 row in set (0.00 sec)

MySQL [aa]> exit
Bye
[root@ccx ~]# cd /date
[root@ccx date]# ls
aa          ca.pem           ib_buffer_pool  ib_logfile1  performance_schema  server-cert.pem
auto.cnf    client-cert.pem  ibdata1         ibtmp1       private_key.pem     server-key.pem
ca-key.pem  client-key.pem   ib_logfile0     mysql        public_key.pem      sys
[root@ccx date]#
  • 如果要进入mysql容器中查看路径,需要新增一个bash进程,流程如下
    我顺便在这进入到容器中的/var/lib/mysql目录中,对比主机的/date目录,可以看到文件内容确实一模一样的。
[root@ccx aa]# docker exec -it db bash
root@8d27c14f23c6:/# cd /var/lib/mysql
root@8d27c14f23c6:/var/lib/mysql# ls
aa          ca.pem           ib_buffer_pool  ibdata1  performance_schema  server-cert.pem
auto.cnf    client-cert.pem  ib_logfile0     ibtmp1   private_key.pem     server-key.pem
ca-key.pem  client-key.pem   ib_logfile1     mysql    public_key.pem      sys
root@8d27c14f23c6:/var/lib/mysql# exit
exit
[root@ccx aa]# cd /date
[root@ccx date]# ls
aa          ca.pem           ib_buffer_pool  ib_logfile1  performance_schema  server-cert.pem
auto.cnf    client-cert.pem  ibdata1         ibtmp1       private_key.pem     server-key.pem
ca-key.pem  client-key.pem   ib_logfile0     mysql        public_key.pem      sys
[root@ccx date]# 

备份意义及使用

  • 通过上面的备份完毕以后,这么做的好处就是,如果不小心误删了该容器,可以新建一个一摸一样的容器出来,这样里面的数据都还在
    • 注:必须参数要一模一样,特别是密码,如果变动了以后,就登不上了,报错内容是:ERROR 1045 (28000): Access denied for user 'root'@'172.17.0.1' (using password: YES)
    • 这个数据库是不能共享到其他容器上面的,登陆报错和上面一样
  • 如,我删掉db这个容器,新建一个一摸一样的,可以看到之前新建的aa库还在。
[root@ccx ~]# docker rm -f db
db
[root@ccx ~]# docker run -dit --restart=always --name=db -e MYSQL_ROOT_PASSWORD=passwd -v /date:/var/lib/mysql/ hub.c.163.com/library/mysql
83817192b3ad981916fbd4a5233f6938ed39fadbe397e808ce6fe9cae2d3ef37
[root@ccx ~]# mysql -uroot -p -h 172.17.0.3 
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.18 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> show datebases;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'datebases' at line 1
MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| aa                 |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

MySQL [(none)]> 
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐