什么是容器数据卷

为了实现数据持久化,使容器之间可以共享数据。可以将容器内的目录,挂载到宿主机上或其他容器内,实现同步和共享的操作。即使将容器删除,挂载到本地的数据卷也不会丢失。

docker的理念回顾

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

数据如果都在容器中,那么我们容器一旦删除,数据就会丢失 需求:数据可以持久化

MySQL,容器删了,删库跑路 需求:MySQL数据可以存储在本地

容器之间可以有一个数据共享的技术,Docker容器中产生的数据同步到本地

这就是卷技术,目录的挂载将我们容器内的目录挂载到Linux上面

容器的持久化和同步操作,容器间也是可以做数据共享的

使用数据卷

一、匿名挂载

1、即不指定挂载到主机上的路径,只指定容器内部需要挂载的目录。

  1. -v 容器内路径
  2. docker run -d -P --name 容器名称 -v 容器内路径 镜像名称
  3. docker run -d -P --name nginx01 -v /etc/nginx nginx
  4. kpsmile@kpsmile-machine:~$ docker run -d -P --name nginx01 -v /etc/nginx nginx
  5. 3fb5a0afb25f658e1a2f2b7cd22cc52b0fa45822e2707aea018e3b4e8d387249
  6. kpsmile@kpsmile-machine:~$ docker inspect 3fb5a0afb25f658e1a2f2b7cd22cc52b0fa45822e2707aea018e3b4e8d387249
  7. ...
  8. "Mounts": [
  9. {
  10. "Type": "volume",
  11. "Name": "ab1706dfd8a7352003d7198f1e353092264ac24d20b933f48cbe6adca29e89db",
  12. "Source": "/var/lib/docker/volumes/ab1706dfd8a7352003d7198f1e353092264ac24d20b933f48cbe6adca29e89db/_data",
  13. "Destination": "/etc/nginx",
  14. "Driver": "local",
  15. "Mode": "",
  16. "RW": true,
  17. "Propagation": ""
  18. }
  19. ],
  20. ...
  21. # 挂载位置在ab1706dfd8a7352003d7198f1e353092264ac24d20b933f48cbe6adca29e89db这个卷下

二、具名挂载

1、给挂载位置添加名字,即具名挂载。

  1. -v 卷名:容器内路径
  2. docker run -d -P --name 容器名称 -v 卷名:容器内路径 镜像名称
  3. 例如:docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
  4. kpsmile@kpsmile-machine:~$ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
  5. a24fc2e277ed8691d659adace64f4c010c726f8e62b7146a806a9ea5f32d7dd5
  6. kpsmile@kpsmile-machine:~$ docker inspect a24fc2e277ed8691d659adace64f4c010c726f8e62b7146a806a9ea5f32d7dd5
  7. ...
  8. "Mounts": [
  9. {
  10. "Type": "volume",
  11. "Name": "juming-nginx",
  12. "Source": "/var/lib/docker/volumes/juming-nginx/_data",
  13. "Destination": "/etc/nginx",
  14. "Driver": "local",
  15. "Mode": "z",
  16. "RW": true,
  17. "Propagation": ""
  18. }
  19. ]
  20. ...

三、指定挂载

docker run -it -v 宿主机目录:dockers容器内目录 imageId

容器内操作文件

容器内

  1. kpsmile@kpsmile-machine:~$ docker run -it --name ubuntu-test -v /home/kpsmile/test:/home ubuntu
  2. root@8e7564da3550:/# echo "test docker run -v" > /home/a.text

宿主机

  1. kpsmile@kpsmile-machine:~/test$ pwd
  2. /home/kpsmile/test
  3. kpsmile@kpsmile-machine:~/test$ cat a.text
  4. test docker run -v

宿主机操作文件

宿主机

  1. # kpsmile用户权限不够,所以换了root用户
  2. root@kpsmile-machine:/home/kpsmile/test# echo "host echo" >> a.text

容器内

  1. root@8e7564da3550:/# cat /home/a.text
  2. test docker run -v
  3. host echo

四、具名挂载、匿名挂载和指定路径挂载的区别

1、

  1. -v 容器内部路径 #匿名挂载
  2. -v 卷名:容器内部路径 #具名挂载
  3. -v /宿主机路径:容器内部路径 #指定路径挂载

2、数据卷挂载还可以赋予权限

  1. #通过-v容器内路径,ro rw改变读写权限 默认是rw权限,即可读可写。
  2. ro read only #只读
  3. rw read write #可读可写
  4. #一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了
  5. $ docker run -d -P --name nginx02 -v jumping-nginx:/etc/nginx:ro nginx
  6. $ docker run -d -P --name nginx02 -v jumping-nginx:/etc/nginx:rw nginx
  7. #ro 即创建的这个卷是只读权限(read only),即容器内部职能读取,不能修改,必须通过宿主机来进行修改。

Docker挂载主机目录访问如果出现cannot open directory .: Permission denied

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

如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,

在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用—privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即

使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。

卷的继承

  1. docker run -it --privileged=true -v /home/kpsmile/testExtend:/tmp --name u1 ubuntu
  2. docker run -it --privileged=true --volumes-from a8e05fd5907e --name u2 ubuntu
  3. # u1
  4. kpsmile@kpsmile-PC:~$ docker run -it --privileged=true -v /home/kpsmile/testExtend:/tmp --name u1 ubuntu
  5. root@a8e05fd5907e:/# ls /tmp
  6. a.txt
  7. root@a8e05fd5907e:/# cat /tmp/a.txt
  8. # u2
  9. kpsmile@kpsmile-PC:~$ docker run -it --privileged=true --volumes-from a8e05fd5907e --name u2 ubuntu
  10. root@a833d6b8c2de:/# ls /tmp
  11. a.txt
  12. root@a833d6b8c2de:/# cat /tmp/a.txt
  13. # 宿主机
  14. kpsmile@kpsmile-PC:~/testExtend$ pwd
  15. /home/kpsmile/testExtend
  16. kpsmile@kpsmile-PC:~/testExtend$ ls
  17. a.txt
  18. kpsmile@kpsmile-PC:~/testExtend$ cat a.txt

u1写入

  1. # u1
  2. root@a8e05fd5907e:/# echo "u1 wirte" >> /tmp/a.txt
  3. root@a8e05fd5907e:/# cat /tmp/a.txt
  4. u1 wirte
  5. # u2
  6. root@a833d6b8c2de:/# cat /tmp/a.txt
  7. u1 wirte
  8. # 宿主机
  9. kpsmile@kpsmile-PC:~/testExtend$ cat a.txt
  10. u1 wirte

u2写入

  1. # u2
  2. root@a833d6b8c2de:/# echo "u2 wirte" >> /tmp/a.txt
  3. root@a833d6b8c2de:/# cat /tmp/a.txt
  4. u1 wirte
  5. u2 wirte
  6. # u1
  7. root@a8e05fd5907e:/# cat /tmp/a.txt
  8. u1 wirte
  9. u2 wirte
  10. # 宿主机
  11. kpsmile@kpsmile-PC:~/testExtend$ cat a.txt
  12. u1 wirte
  13. u2 wirte

宿主机写入

  1. # 宿主机
  2. kpsmile@kpsmile-PC:~/testExtend$ echo "host wirte" >> a.txt
  3. kpsmile@kpsmile-PC:~/testExtend$ cat a.txt
  4. u1 wirte
  5. u2 wirte
  6. host wirte
  7. # u1
  8. root@a8e05fd5907e:/# cat /tmp/a.txt
  9. u1 wirte
  10. u2 wirte
  11. host wirte
  12. # u2
  13. root@a833d6b8c2de:/# cat /tmp/a.txt
  14. u1 wirte
  15. u2 wirte
  16. host wirte

安装MySQL

  1. docker run -d -p 3306:3306 --privileged=true -v /home/kpsmile/mysql/log:/var/log/mysql -v /home/kpsmile/mysql/data:/var/lib/mysql -v /home/kpsmile/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7

此时进入容器内部

  1. kpsmile@kpsmile-machine:~/mysql$ docker exec -it c7be37c4ab1a bash

运行MySQL

  1. root@c7be37c4ab1a:/# mysql -uroot -p
  2. mysql> SHOW VARIABLES LIKE 'character%' ;
  3. +--------------------------+----------------------------+
  4. | Variable_name | Value |
  5. +--------------------------+----------------------------+
  6. | character_set_client | latin1 |
  7. | character_set_connection | latin1 |
  8. | character_set_database | latin1 |
  9. | character_set_filesystem | binary |
  10. | character_set_results | latin1 |
  11. | character_set_server | latin1 |
  12. | character_set_system | utf8 |
  13. | character_sets_dir | /usr/share/mysql/charsets/ |
  14. +--------------------------+----------------------------+
  15. 8 rows in set (0.00 sec)

CTRL+q+p回到宿主机

编写my.cnf

  1. kpsmile@kpsmile-machine:~/mysql$ sudo vim conf/my.cnf
  2. [client]
  3. default_character_set=utf8
  4. [mysqld]
  5. collation_server = utf8_general_ci
  6. character_set_server = utf8

重启MySQL

  1. kpsmile@kpsmile-machine:~/mysql$ docker restart c7be37c4ab1a
  2. c7be37c4ab1a
  3. kpsmile@kpsmile-machine:~/mysql$ docker exec -it c7be37c4ab1a bash
  4. root@c7be37c4ab1a:/# mysql -uroot -p
  5. mysql> SHOW VARIABLES LIKE 'character%' ;
  6. +--------------------------+----------------------------+
  7. | Variable_name | Value |
  8. +--------------------------+----------------------------+
  9. | character_set_client | utf8 |
  10. | character_set_connection | utf8 |
  11. | character_set_database | utf8 |
  12. | character_set_filesystem | binary |
  13. | character_set_results | utf8 |
  14. | character_set_server | utf8 |
  15. | character_set_system | utf8 |
  16. | character_sets_dir | /usr/share/mysql/charsets/ |
  17. +--------------------------+----------------------------+
  18. 8 rows in set (0.00 sec)