背景
对docker的数据持久化用得比较少, 也没细究过, 今天抽空来研究一下。
docker数据持久化或者说存储,主要有两种形式:
环境
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ cat /etc/os-release
PRETTY_NAME="Deepin 20 Beta"
NAME="Deepin"
VERSION_ID="20 Beta"
VERSION="20 Beta"
ID=Deepin
HOME_URL="https://www.deepin.com/"
BUG_REPORT_URL="https://bbs.deepin.org/"
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker version
Client: Docker Engine - Community
Version: 19.03.12
API version: 1.40
Go version: go1.13.10
Git commit: 48a66213fe
Built: Mon Jun 22 15:45:50 2020
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.12
API version: 1.40 (minimum version 1.12)
Go version: go1.13.10
Git commit: 48a66213fe
Built: Mon Jun 22 15:44:21 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
bind mounts
为了演示方便, 如无特别说明, 都在/var/workspace/learn/docker
来操作
# 显示目录/文件结构
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ tree .
.
└── volume-test
└── Dockerfile
1 directory, 1 file
查看docker volume,发现目前没有volume创建
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker volume ls
DRIVER VOLUME NAME
使用不存在的相对路径
# 容器中创建了个空目录
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker run --rm -it -v some-dir:/some-dir alpine sh
/ # ls some-dir/
# 宿主机上创建了个 docker volume
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ ls
volume-test
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker volume ls
DRIVER VOLUME NAME
local some-dir
使用存在的相对路径
# 容器中创建了个空目录
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker run --rm -it -v volume-test:/volume-test alpine sh
/ # ls volume-test/
/ #
# 宿主机上创建了个 docker volume
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker volume ls
DRIVER VOLUME NAME
local some-dir
local volume-test
- 小结: -v使用相对目录, 总是会创建docker volume.
在做下边的实验前, 先删除下现有的volume: docker volume rm $(docker volume ls -q)
使用不存在的绝对路径
# 容器内自动创建
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker run --rm -it -v `pwd`/some-dir:/somedir alpine sh
/ # cd some-dir/
/some-dir # touch a
# 宿主机上目录文件与容器内同步
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ ls some-dir/a
some-dir/a
使用存在的绝对路径
# 容器内自动映出到宿主机上的目录文件结构
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker run --rm -it -v `pwd`/volume-test:/volume-test alpine sh
/ # ls volume-test/
Dockerfile
/ # cd volume-test
/volume-test # echo hello > a.txt
/volume-test #
# 宿主机上的文件与容器内同步
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ cat volume-test/a.txt
hello
小结:使用绝对路径这种形式(容器内相应目录不存在时), 能实现容器内和宿主机上对应目录/文件的同步, 平时用的最多的也是这种形式, 让容器读取宿主机上的配置。
如:
docker run -p 8081:80 --name nginx-80
-v /docker_data/data/nginx/html:/usr/share/nginx/html
-v /docker_data/data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
-v /docker_data/data/nginx/conf/conf.d:/etc/nginx/conf.d
-v /docker_data/data/nginx/logs:/var/log/nginx
-d nginx
把容器内的文件映射出来
现在有一个很有意思的想法, 怎么把容器内的配置映射出来?
之所以想这样, 是因为类似nginx这类容器, 都有默认配置, 就想映出出来 然后就可以在其基础上修改了, 方便快捷。
# 显示Dockerfile内容
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ cat ./volume-test/Dockerfile
FROM alpine
LABEL target=learn
RUN mkdir -p /var/workspace && echo 'hello' > /var/workspace/a.txt
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker build -t myimage:1.0 volume-test/
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM alpine
---> a24bb4013296
Step 2/3 : LABEL target=learn
---> Using cache
---> dd29d7a61fef
Step 3/3 : RUN mkdir -p /var/workspace && echo 'hello' > /var/workspace/a.txt
---> Using cache
---> e7e9c25c0383
Successfully built e7e9c25c0383
Successfully tagged myimage:1.0
# 先看看容器内有没有我们创建的文件
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker run --rm myimage:1.0 cat /var/workspace/a.txt
hello
上面基于alpine创建了镜像myapp:1.0, 并且创建了文件 /var/workspace/a.txt, 以此来演示如何将容器内的文件挂载出来 。
# 先看看宿主机的上的目录(无workspace目录)
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ ls
some-dir volume-test
# 容器内, 发现a.txt没有了
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker run --rm -it -v `pwd`/workspace:/var/workspace myimage:1.0 sh
/ # ls /var/workspace/
/ #
# 再看宿主机上, 发现多了个空目录workspace
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ ls workspace/
gerrylon@gerrylon-PC:/var/workspace/learn/docker$
以上面的实验为基础, 在宿主机workspace下创建个b.txt, 再看看:
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ cat workspace/b.txt
world
# 发现容器内的文件以宿主机上的为准
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker run --rm -it -v `pwd`/workspace:/var/workspace myimage:1.0 sh
/ # cat var/workspace/b.txt
world
也就是说这种这种方式不能把容器内的文件映射出来, 实验的效果显示:是以宿主机上的目录为准来设置容器目录的。
如果有哪位同学知道怎么把容器内的文件映射出来, 请指教。
volumes
# 使用相对路径的形式,会创建一个docker volume
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker run --rm -it -v myworkspace:/var/workspace myimage:1.0 sh
/ # cat var/workspace/a.txt
hello
/ # echo workd >> /var/workspace/a.txt
/ #
# 查看volume详情
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ docker volume inspect myworkspace
[
{
"CreatedAt": "2020-07-11T13:33:18+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/myworkspace/_data",
"Name": "myworkspace",
"Options": null,
"Scope": "local"
}
]
# 看看文件同步情况
gerrylon@gerrylon-PC:/var/workspace/learn/docker$ sudo cat /var/lib/docker/volumes/myworkspace/_data/a.txt
hello
workd
可以看出, 使用volume这种形式, 挂载的内容会放到
/var/lib/docker/volumes/$volume_name/_data
, 而且会实现文件同步
官方推荐使用volume: https://docs.docker.com/storage/volumes/
Volumes are the preferred mechanism for persisting data generated by and used by Docker containers. While bind mounts are dependent on the directory structure of the host machine, volumes are completely managed by Docker. Volumes have several advantages over bind mounts:
Volumes are easier to back up or migrate than bind mounts.
You can manage volumes using Docker CLI commands or the Docker API.
Volumes work on both Linux and Windows containers.
Volumes can be more safely shared among multiple containers.
Volume drivers let you store volumes on remote hosts or cloud providers, to encrypt the contents of volumes, or to add other functionality.
New volumes can have their content pre-populated by a container.
总结
- -v path:/some-dir 会创建名为path的volume
- -v /path:/some-dir 会创建目录(如果不存在的话)/path
- -v /path:/some-dir 会将/path(如果存在的话)及其下的文件映射到容器内
- 推荐使用docker volume来做容器的存储和共享数据
(完)