说明
Docker中镜像存储在只读层,当通过镜像创建容器相当于启动了一个新的进程, 在容器中是可读写的,默认情况下,容器内创建的文件都会存在容器的写入层.当容器删除.数据不会持久化, 即使用相同的镜像创建容器也是无法获取到之前的数据.
为了使数据能够保存并且可以与其他容器共享数据.目前Docker提供了Volumes
, Bind Mounts
,tmpfs Mounts
三种方式.
Volume
volume的数据是永久保存,容器是可以读写volume中的数据,但volume中的数据不会随着容器删除而删除.容器使用volume增加数据,并不会增加容器的大小.
创建和管理数据卷
创建数据卷
docker volume create my-vol
查看数据卷
docker volume ls
数据卷详情
docker volume inspect
[
{
"CreatedAt": "2021-10-08T06:51:38Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
删除数据卷
docker volume rm my-vol
删除全部未使用的数据卷
docker volume prune
启动容器使用数据卷
创建数据卷
docker volume create my-sql
启动容器指定数据卷
数据卷读写权限
docker run -d -p 3366:3306 \
--name database-sql \
--mount source=vol-data-sql,target=/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
mysql
数据卷只读权限
docker run -d -p 3366:3306 \
--name database-sql \
--mount source=vol-data-sql,destination=/var/lib/mysql,readonly \
-e MYSQL_ROOT_PASSWORD=root \
mysql
数据卷读写权限
docker run -d -p 3366:3306 \
--name database-sql \
-v vol-data-sql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
mysql
数据卷只读权限
docker run -d -p 3366:3306 \
--name database-sql \
-v vol-data-sql:/var/lib/mysql:ro \
-e MYSQL_ROOT_PASSWORD=root \
mysql
清理容器与数据卷
容器停止与关闭
docker container stop database-sql
docker container rm database-sql
删除数据卷
docker volume rm vol-data-sql
数据共享
多个机器访问相同的资源可以通过给应用程序增加逻辑,将数据存储在远程,另一种方式将数据写入NFS等外部存储系统的驱动程序创建卷.
卷驱动程序允许您从应用程序逻辑中抽象底层存储系统.如果服务使用具有NFS驱动程序的卷,则可以更新服务以使用其他驱动程序,如过在云中存储数据,而无需更改应用程序逻辑.
使用Volume驱动
当创建volume使用docker volume create vol-name
,或者启动容器选择没有创建的volume的时候,可以指定volume驱动.
说明
机器 | 备注 |
---|---|
192.168.128.125 | 安装docker以及sshfs插件, 创建远程数据卷 |
192.168.128.126 | 安装docker以及sshfs插件, 创建远程数据卷 |
vieux/sshfs驱动
安装插件
docker plugin install --grant-all-permissions vieux/sshfs
Linux下报错
Error response from daemon: rpc error: code = 2 desc = shim error: docker-runc not installed on system
解决方式
cd /usr/libexec/docker/
ln -s docker-runc-current docker-runc
使用驱动创建数据卷
-o nonempty -o allow_other 设置普通用户访问共享文件夹, 创建volume生成共享目录权限设置成777.在启动容器后文件的权限,所属组用户都发生变化. 会造成无权限操作目录.
docker volume create --driver vieux/sshfs \
-o sshcmd=root@192.168.128.125:/data/redis \
-o password=root \
-o nonempty \
-o allow_other \
volume-ssh-redis
启动容器指定驱动卷
# redis的rdb文件存储在/data下.
docker container run -it -d -p 6379:6379 \
--name database-redis \
--mount src=volume-ssh-redis,type=volume,target=/data \
redis
验证
进入125机器查看挂载目录文件(未设置缓存此时/data/redis 应为空)进入125机器的容器(如未设置缓存, 容器内的/data目录也应为空)
# 进入容器
docker container exec -it database-redis sh
# 验证容器内目录
cd /data && ls
# 进入容器的redis, 设置缓存
redis-cli
127.0.0.1:6379> set test hello
127.0.0.1:6379> set user gy
127.0.0.1:6379> exit
# 验证容器目录
cd /data && ls
dump.rdb
exit
# 退出容器进入125宿主机验证挂载目录
cd /data/redis && ls -l
总用量 4
-rw-r--r-- 1 polkitd root 118 10月 9 04:41 dump.rdb
# 进入126容器
docker container exec -it database-redis sh
# 查看redis数据目录
cd /data && ls
dump.rdb
# 进入redis
redis-cli
127.0.0.1:6379> keys *
1) "test"
2) "user"
127.0.0.1:6379> get test
"hello"
127.0.0.1:6379> exit
备份还原
备份
拉取镜像
docker pull centos:7
启动并进入容器
docker container run -d -it -v /data/log --name hello centos:7
docker container exec -it hello sh
mkdir -p /data/log && cd "$_"
echo "hello Emiya" >> hello.txt && echo "今日星期一啦" >> file.log
exit
删除容器备份数据卷到宿主机指定目录
- 创建临时容器
- 通过
--volumes-from
创建hello容器. 数据卷复制hello容器的数据卷 - 此时hello2容器与hello1容器的/data/log目录数据相同
- 通过
-v
将hello2容器的/back目录挂载到宿主机的/back目录.达到数据共享 - 容器hello2启动后,将/data目录压缩至/backup/file.tar.
- 此时宿主机的/backup目录下多出file.tar
- 容器hello2运行结束,通过--rm销毁容器.
docker container run --rm --name hello2 \
--volumes-from hello \
-v /backup:/backup centos:7 \
tar cf /backup/file.tar /data
宿主机目录
[root@pxc126 backup]# ls
file.tar
[root@pxc126 backup]# tar -xvf file.tar
data/
data/log/
data/log/hello.txt
data/log/file.log
[root@pxc126 backup]# ls
data file.tar
[root@pxc126 backup]# cd data/
[root@pxc126 data]# ls
log
[root@pxc126 data]# cd log/
[root@pxc126 log]# ls
file.log hello.txt
还原
修改数据
docker container exec -it hello sh
sh-4.2# cd /data/log/
sh-4.2# echo "hello Emiya2" >> hello.txt && echo "今日星期二啦" >> file.log
sh-4.2# cat file.log
今日星期一啦
今日星期二啦
还原备份
- 启动新的临时容器,数据卷复制hello容器的数据卷.
- 挂载/backup目录到宿主机/backup目录. 共享数据压缩包
- 此时临时容器数据file.log有2条记录.
- 临时容器删除/data/log下所有文件, 解压/backup/file.tar到/data/log. 脱衣2层
- 恢复成原始数据
- 删除数据卷
docker container run --rm \
--volumes-from hello \
-v /backup/:/backup \
centos:7 \
bash -c "cd /data/log && rm -rf ./* && tar xvf /backup/file.tar --strip 2"
还原到新容器中
docker container run -d -it -v /data/log --name bye centos:7
docker container run --rm \
--volumes-from bye \
-v /backup/:/backup \
centos:7 \
bash -c "cd /data/log && rm -rf ./* && tar xvf /backup/file.tar --strip 2"
Bind Mount
使用绑定挂载,宿主机的文件目录装入到容器中.使用的文件路径为宿主机的相对路径.绑定挂载依赖特定的主机文件系统.无法通过命令管理.
挂载启动容器
docker container run -itd --name local-redis \
--mount type=bind,source=/data/docker-mount/redis,target=/data \
redis
docker container run -itd --name local-redis \
--v /data/docker-mount/redis:/data \
redis
查看容器详情
docker container inspect local-redis
- Type: 绑定挂载类型
- Source: 来源目录
- Destination: 目的目录
- RW: 读写权限
"Mounts": [
{
"Type": "bind",
"Source": "/data/docker-mount/redis",
"Destination": "/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
只读挂载
docker container run -itd --name local-redis \
--mount type=bind,source=/data/docker-mount/redis,target=/data,readonly \
redis
docker container run -itd --name local-redis \
--v /data/docker-mount/redis:/data:ro \
redis
不错不错(。•ˇ‸ˇ•。)