Docker 数据管理简介
Docker容器提供了几种挂载方式,用于将主机上的数据卷与容器内的路径进行关联。以下是几种常见的挂载方式:
- 绑定挂载(Bind Mount):绑定挂载是将主机上的目录或文件直接挂载到容器内的指定路径。这种方式可以实现主机与容器之间的数据共享,任何一方对数据的更改都会在另一方中反映出来。
- 卷挂载(Volume Mount):卷挂载是将Docker创建的卷(Volume)挂载到容器内的指定路径。卷是Docker管理的一种持久化存储,可以独立于容器进行管理和共享。使用卷挂载可以方便地在不同容器之间共享数据,同时也可以保证数据的持久性。
- 临时文件系统(Tmpfs):临时文件系统是将主机上的临时文件系统挂载到容器内的指定路径。这种方式适用于需要在容器内进行临时性存储的场景,容器停止后,临时文件系统中的数据会被清除。
这些挂载方式可以根据实际需求选择和配置,以满足容器与主机之间数据共享和持久化存储的需求。
数据卷(Data Volume)
数据卷的使用,类似于 Linux 下对目录或文件进行 mount
数据卷(Data Volume)是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
- 数据卷可以在容器之间共享和重用
- 对数据卷的修改会立马生效
- 对数据卷的更新,不会影响镜像
- 卷会一直存在,直到没有容器使用
建立一个数据卷
在用 docker run 命令的时候,使用 -v 标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。
创建一个容器
[root@test ~]# docker run -d -P --name web -v /webapp-data training/webapp python app.py
7bdad53401c47568b01257e36d9f063a941885879dbe041f1bcfb72cf7b7e5e7
[root@test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7bdad53401c4 training/webapp "python app.py" 5 seconds ago Up 4 seconds 0.0.0.0:32769->5000/tcp, :::32769->5000/tcp web
看下容器内部是否生成/webapp-data目录
[root@test ~]# docker exec -it web /bin/bash
root@7bdad53401c4:/opt/webapp# cd /webapp-data
root@7bdad53401c4:/webapp-data# ls
root@7bdad53401c4:/webapp-data# ll
total 0
drwxr-xr-x 2 root root 6 Jul 13 07:46 ./
drwxr-xr-x 1 root root 25 Jul 13 07:46 ../
挂在一个主机目录当做容器数据卷
使用 -v 标记也可以指定挂载一个本地主机的目录到容器中去
[root@test ~]# docker rm -f web
web
[root@test ~]# docker run -d --name web -v /opt/webapp-data5:/opt/webapp2 training/webapp
bbc86563b417f36098982de02dbbaa06aebfab09caff8758d863c5c1e08a5515
[root@test ~]# docker exec -it web /bin/bash
root@bbc86563b417:/opt/webapp# cd ..
root@bbc86563b417:/opt# ls
webapp webapp2
root@bbc86563b417:/opt# cd webapp2
root@bbc86563b417:/opt/webapp2# mkdir test
root@bbc86563b417:/opt/webapp2# exit
exit
[root@test webapp-data5]# ls
test
上面的命令加载主机的 /opt/webapp-data5 目录到容器的 /opt/webapp2 目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,如果目录不存在 Docker 会自动为你创建它
我们删除容器,看主机上数据是否会被删除
[root@test webapp-data5]# docker rm -f web
web
[root@test webapp-data5]# ls
test
挂在一个本地主机文件作为数据卷
-v 标记也可以从主机挂载单个文件到容器中
[root@test ~]# docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash
root@79eca07938db:/# ll | grep .bash_history
-rw------- 1 root root 19549 Feb 19 10:28 .bash_history
root@79eca07938db:/# exit
exit
这样就可以记录在容器输入过的命令了。
*注意:如果直接挂载一个文件,很多文件编辑工具,包括 vi
或者 sed --in-place
,可能会造成文件 inode 的改变,从 Docker 1.1 .0起,这会导致报错误信息。所以最简单的办法就直接挂载文件的父目录。
数据卷容器(Data Volume Container)
上面讲述的是主机和容器之间共享数据,那么如何你有一些持续更新的数据需要在容器之间共享,最好的方法就是创建数据卷容器
数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的
[root@test webapp-data5]# docker run -d -v /dbdata --name dbdata training/postgres
9b45a8a658434d43a73857ab3d3f98bfaaeb8b9bc4b15a20bcfbba74ff6b3439
[root@test webapp-data5]# docker run -d --volumes-from dbdata --name db1 training/postgres
19d14c2fdb62b0b30e33e9fa5f95813ae949cdba450f3b942a152cbf03ad9b45
[root@test webapp-data5]# docker run -d --volumes-from dbdata --name db2 training/postgres
6fad6aa97b03adf3a613e5109792c0c1d35f0d076ea9a097d3f645d54139eec9
[root@test webapp-data5]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6fad6aa97b03 training/postgres "su postgres -c '/us…" 5 seconds ago Up 4 seconds 5432/tcp db2
19d14c2fdb62 training/postgres "su postgres -c '/us…" 12 seconds ago Up 12 seconds 5432/tcp db1
9b45a8a65843 training/postgres "su postgres -c '/us…" 19 seconds ago Up 19 seconds 5432/tcp dbdata
-volumes-from
可以多次使用来 mount 多个conatainer里的多个volumes。
这个操作是链式的, 我们在db1 中通过 --volumes-from mount
进来的 volume可以继续被其他container使用
[root@test webapp-data5]# docker run -d --name db3 --volumes-from db1 training/postgres
3f2d71eecb6cd747ce694ecaa4bab58a22360886002837ea65f2659cd61119d6
[root@test webapp-data5]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3f2d71eecb6c training/postgres "su postgres -c '/us…" 7 seconds ago Up 5 seconds 5432/tcp db3
6fad6aa97b03 training/postgres "su postgres -c '/us…" 2 minutes ago Up 2 minutes 5432/tcp db2
19d14c2fdb62 training/postgres "su postgres -c '/us…" 2 minutes ago Up 2 minutes 5432/tcp db1
9b45a8a65843 training/postgres "su postgres -c '/us…" 2 minutes ago Up 2 minutes 5432/tcp dbdata
使用 --volumes-from 参数所挂载数据卷的容器自己并不需要保持在运行状态。
如果删除了挂载的容器(包括 dbdata、db1 和 db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时使用
docker rm -v
命令来指定同时删除关联的容器。 这可以让用户在容器之间升级和移动数据卷。
数据备份、恢复、迁移数据卷
利用数据卷对其中的数据进行进行备份、恢复和迁移
备份
首先使用 --volumes-from
标记来创建一个加载 dbdata 容器卷的容器,并从本地主机挂载当前到容器的 /backup 目录。命令如下:
[root@test ~]# docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
tar: Removing leading `/' from member names
/dbdata/
[root@test ~]# ll | grep backup.tar
-rw-r--r-- 1 root root 10240 Feb 20 12:39 backup.tar
容器启动后,使用了 tar 命令来将 dbdata 卷备份为本地的 /backup/backup.tar
恢复
如果要恢复数据到一个容器
首先创建一个带有数据卷的容器 dbdata2
[root@test ~]# docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
然后创建另一个容器,挂载 dbdata2 的容器,并使用 untar 解压备份文件到挂载的容器卷中。
[root@test ~]# docker run --volumes-from dbdata2 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar
dbdata/