Docker中的数据管理
Docker中的数据管理
默认一个容器内部创建的文件被存储到一个可写的容器层。这就意味着:
- 当一个容器不存在的时候,他的数据不能被持久化(一起销毁了),并且其他进程需要从容器中取出数据是困难的
- 一个容器的可写层是和正在运行容器的主机是紧耦合的,你很难移动这些数据到其他地方去
- 向一个容器的可写层写数据需要一个管理文件系统的存储驱动。这个存储驱动使用Linux内核提供的union filesysem。相较于直接向主机的文件系统交互数据的数据卷(data volumes),这种额外的抽象降低了性能
Docker有两种方式volumes, 和 bind mounts向容器主机存储文件,因此即便容器被停止了,文件依然可以被持久化。
1. 如何正确的选择挂载方式
-
Volumes 是被Docker管理的存储在主机文件系统(
/var/lib/docker/volumes/
在Linux)的一部分。非Docker进程不应该修改这部分文件系统。Volumes是在Docker中最好的数据持久方式。 - Bind mounts 可以被存储到主机文件系统的任何地方。它们可能是重要的系统文件或目录。在Docker主机上的非Docker进程或Docker容器都可以在任何时候修改它们。
2. 关于挂载类型的更多细节
-
Volumes: 被Docker创建和管理。你可以使用
docker volume create
命令明确的创建一个Volume,或者Docker会在创建一个容器或者服务期间创建一个Volume。
当你创建一个Volume,它被存储到Docker主机的一个目录里。当你挂载这个Volume到一个容器,这个目录成为被挂在到容器的目录。除了那些Volumes是被Docker管理,并且与主机的核心功能相隔离,其余和bind mounts很像。
一个给定的Volume可以同时被挂载道多个容器。当没有一个运行的容器在使用这个Volume,这个Volume对Docker来说依旧是可用的,并且不会被自动移除,你可以使用docker volume prune
移除不用的Volumes。
当你挂在一个Volume,它会是一个被命名的或匿名的。当匿名的Volume被第一次挂在到一个容器时,它们没有被指定明确的名字,因此Docker给它们分配了一个随机的名字来确保它们在Docker主机中式唯一的。除了名称不一样,命名的和匿名的Volumes使用是一致的。
Volumes也支持Volumes Drivers的使用,Volumes Drivers 允许你存储你的数据到一个远程主机或云提供商或其他可以的方式。 - bind mounts: 从Docker早期的版本就开始支持。bind mounts 和 Volume相比有些限制功能。当你使用bind mount,一个主机的文件或目录会被挂载到一个容器中。这个文件或目录被这个主机的全路径所引用。这个文件或目录不需要一开始就存在在这个Docker主机上。需要的时候再创建。bind mount是性能优异的,但是它依赖于一个被指定的可用的目录结构的主机文件系统。如果你开发一个新的Docker 应用,请考虑使用一个命名的Volume替代。你无法使用Docker CLI命令直接管理bind mounts。
Bind mounts allow access to sensitive files
One side effect of using bind mounts, for better or for worse, is that you can change the host filesystem via processes running in a container, including creating, modifying, or deleting important system files or directories. This is a powerful ability which can have security implications, including impacting non-Docker processes on the host system.、
3. Volumes
数据卷Volumes相较于bind mount是更好的数据持久化方案,Volumes相较于bind mount的几个优势:
- Volumes更容易备份和迁移
- 可以使用Docker CLI 和 Docker API管理
- 可以工作在Linux和Windows容器上
- 在多个容器间共享数据更安全
- 可以存储到远程主机,加密Volumes的内容,添加其他功能
- 可以先于容器构建
详见官网说明:Use Volumes
3.1 举例演示
选-v
还是选--mount
一开始,-v
或 --volume
参数用于单容器,而--mount
参数用于集群服务。然而,从Docker 17.06 版本开始,你可以使用 --mount
用于单容器。
新手应该尝试使用 --mount,它比 --volume语法更简单
...
VOLUME /var/lib/mysql
...
3.2 验证删除容器Volume依然存在
当我们新建docker run -d --name mysql01 -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.6
一个mysql容器时,会自动创建随机但唯一的Volume 65125ede...
[aaa@qq.com docker]# docker run -d --name mysql01 -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.6
Unable to find image 'mysql:5.6' locally
...
Digest: sha256:60c27b50ca72d81d92a743a965a82f124a4e123c7d374a021887286408878d60
Status: Downloaded newer image for mysql:5.6
c3a5d78c0c732b63bf062ff6cef7120cb0e86d1f424a03df7d61eb518439cc84
[aaa@qq.com docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3a5d78c0c73 mysql:5.6 "docker-entrypoint.s…" 42 seconds ago Up 39 seconds 0.0.0.0:3306->3306/tcp mysql01
[aaa@qq.com docker]# docker volume ls
DRIVER VOLUME NAME
local 65125ede1e3c6fee4cc29803c5f82c400c801ef69cc7dd0dc18f3692b6d0899c
查看一下mysql容器信息 docker inspect mysql01
会发现有一个名称是
"Name": "65125ede..."
[aaa@qq.com docker]# docker inspect mysql01
[
{
...
"Mounts": [
{
"Type": "volume",
"Name": "65125ede1e3c6fee4cc29803c5f82c400c801ef69cc7dd0dc18f3692b6d0899c",
"Source": "/var/lib/docker/volumes/65125ede1e3c6fee4cc29803c5f82c400c801ef69cc7dd0dc18f3692b6d0899c/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
...
]
删除这个容器实例docker rm -f mysql01
,容器的Volume还依然存在
[aaa@qq.com docker]# docker rm -f mysql01
mysql01
[aaa@qq.com docker]# docker volume ls
DRIVER VOLUME NAME
local 65125ede1e3c6fee4cc29803c5f82c400c801ef69cc7dd0dc18f3692b6d0899c
[aaa@qq.com docker]#
3.3 验证容器共享Volume
先创建一个未指定端口的mysql01(上面mysql01的已被删除)docker run -d --name mysql01 -v mysql:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.6
[aaa@qq.com docker]# docker run -d --name mysql01 -v mysql:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.6
2149914dbbaa0092a9437ba1a91e7944828ddb61fd76d553b031e95d01aaebe0
展示volume docker volume ls
[aaa@qq.com docker]# docker volume ls
DRIVER VOLUME NAME
local mysql
进入mysql01创建一个docker数据库docker exec -it mysql01 /bin/bash
[aaa@qq.com docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2149914dbbaa mysql:5.6 "docker-entrypoint.s…" 22 seconds ago Up 21 seconds 3306/tcp mysql01
[aaa@qq.com docker]# docker exec -it mysql01 /bin/bash
aaa@qq.com:/# mysql -uroot
...
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)
mysql> create database docker;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| docker |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
mysql> exit
Bye
aaa@qq.com:/# exit
exit
删除mysql01但是不影响Volume mysqldocker rm -f 2149914dbbaa
[aaa@qq.com docker]# docker rm -f 2149914dbbaa
2149914dbbaa
[aaa@qq.com docker]# docker volume ls
DRIVER VOLUME NAME
local mysql
创建mysql02,同时使用Volume mysqldocker run -d --name mysql02 -v mysql:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.6
[aaa@qq.com docker]# docker run -d --name mysql02 -v mysql:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.6
54f4f0d5ec70ed69d49598e99d43a511212e7e603e57f1a57e1f5f230174ed9c
[aaa@qq.com docker]# docker ps
进入mysql02,查看数据库列表发现docker数据已存在docker exec -it mysql02 /bin/bash
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
54f4f0d5ec70 mysql:5.6 "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 3306/tcp mysql02
[aaa@qq.com docker]# docker exec -it mysql02 /bin/bash
aaa@qq.com:/# mysql -uroot
...
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| docker |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
mysql> exit
Bye
aaa@qq.com:/# exit
exit
[aaa@qq.com docker]#
4. bind mount
bind mount 源于早期的Docker版本。bind mount 相较于 volumes功能有限。当你使用bind mount时,一个主机的文件或目录被挂载到一个容器中。这个文件或目录被主机的全路径或相对路径所引用。相较之下,当你创建一个Volume,一个新的目录会被创建到这个主机的Docker存储目录中,并且Docker管理这些目录。需要的时候再创建。bind mount是性能优异的,但是它依赖于一个被指定的可用的目录结构的主机文件系统。如果你开发一个新的Docker 应用,请考虑使用一个命名的Volume替代。你无法使用Docker CLI命令直接管理bind mounts。
启动一个nginx,把主机的目录/usr/local/nginx挂载到容器的/usr/share/nginx/htmldocker run -d --name mynginx -p 80:80 -v /usr/local/nginx:/usr/share/nginx/html nginx:latest
[aaa@qq.com nginx]# docker run -d --name mynginx -p 80:80 -v /usr/local/nginx:/usr/share/nginx/html nginx:latest
28bf0fc82e89da5f49281386ad3ed2e369b377e4c5dd8494a91474a124eaa84b
[aaa@qq.com nginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28bf0fc82e89 nginx:latest "nginx -g 'daemon of…" 6 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp mynginx
[aaa@qq.com nginx]#
我们知道默认的nginx的首页是
现在我们在/usr/local/nginx下创建一个index.html
<!doctype html>
<html><head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to my docker nginx!</h1>
</body>
</html>
访问nginx首页
在修改一下index.html
<!doctype html>
<html><head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to my docker nginx!</h1>
<h1>Welcome to my docker nginx!</h1>
<h1>Welcome to my docker nginx!</h1>
</body>
</html>
在访问首页
进入到nginx容器中
[aaa@qq.com nginx]# docker exec -it mynginx /bin/bash
aaa@qq.com:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
aaa@qq.com:/# cd /usr/share/nginx/html/
aaa@qq.com:/usr/share/nginx/html# ls
index.html
aaa@qq.com:/usr/share/nginx/html# touch myfile.txt
aaa@qq.com:/usr/share/nginx/html# ls
index.html myfile.txt
this is container addr/share/nginx/html# echo "this is container add" > myfile.tx
aaa@qq.com:/usr/share/nginx/html# cat myfile.txt
this is container add
aaa@qq.com:/usr/share/nginx/html# exit
exit
进入/usr/local/nginx查看,容器内部做的修改容器外是可见的
[aaa@qq.com nginx]# ll
total 8
-rwxr--r-- 1 root root 340 May 26 10:13 index.html
-rw-r--r-- 1 root root 22 May 26 10:16 myfile.txt
[aaa@qq.com nginx]# less myfile.txt
[aaa@qq.com nginx]# cat myfile.txt
this is container add
[aaa@qq.com nginx]#
上一篇: 使用简洁的jQuery方法实现隔行换色功能_jquery
下一篇: php 表单中的input交付