Docker数据持久化

Docker/容器
488
0
0
2022-07-29
标签   Docker

Docker数据持久化

容器删除掉后,里边的数据也会跟着删除。数据的保存和重复可用这是最基本的要求,也就是常说的数据持久化。在写Dockerfile的时候可以用VOLUME命令,指定数据持久化

VOLUME命令设置持久化

当知道了容器中的数据不能持久化后,可以在编写Dockerfile时用VOLUME命令设置持久化的目录。

dockerfile

FROM ubuntu:21.04
VOLUME ["/app"]
RUN apt-get update && \
    apt-get install vim -y 

然后构建镜像 docker image build -t volume-test:1

[root@iZwz9257qzx65bg8c3p88gZ docker-test]# docker image ls -a
REPOSITORY                     TAG       IMAGE ID       CREATED          SIZE
volume-test                    1         0526a62af1d2   16 seconds ago   180MB
....

并使用该镜像启动一个容器,参数为以命令行模式进入该容器

docker container run -it -p 3999:3999 0526a62af1d2 sh

[root@iZwz9257qzx65bg8c3p88gZ docker-test]# docker container run -it -p 3999:3999 0526a62af1d2 sh
# ls
app  bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
# echo hello > app/hello.txt
# cd app
# ls
hello.txt
# cat hello.txt
hello
# exit
[root@iZwz9257qzx65bg8c3p88gZ docker-test]# 

上面的操作分别是

  • 进入容器,可以看到根目录下有app文件夹(通过VOLUME ["/app"]指定的与宿主机共享数据的目录)
  • 然后进入app目录写入了一个helloapp下的hello.txt文件,然后退出容器的命令行

然后我们需要验证这个文件是不是也同步到了我们的宿主机器上,这样才能保证完成容器数据的持久化`

docker volume相关命令

[root@iZwz9257qzx65bg8c3p88gZ _data]# docker volume 

Usage:  docker volume COMMAND

Manage volumes

Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
  ls          List volumes
  prune       Remove all unused local volumes
  rm          Remove one or more volumes

Run 'docker volume COMMAND --help' for more information on a command.

首先 ls查询所有的volume

[root@iZwz9257qzx65bg8c3p88gZ _data]# docker volume ls
DRIVER    VOLUME NAME
local     0bdf00aab64d926f21a6f90342e391d84a4c6ec14b67fe249f8c96ac4e59d91b
local     0ea958861d42b680f60053c59c5384a44069d53e7229f47118ffd64399b46926
local     01b1566780ad5af79b7228f10741b14cc38246e784f3fa5669fe7888a94bfb09
local     3cea763fa6e484560cc489b2aa9f794d370f0f34809a0a4fdd2e513a9c474a74
local     5d599f822fd7cf3f217423af17d483f14deecde3f0adaab300b5c777b3e77636
local     5f61686f8e896c94fb4e1ad2f518e9fb4e4160be75c5358be430919f7a1f5130
local     6b3f0fc9738e3402273e21b605629e6d5dfbf34c37747df4818fa5cd2b1e6059
local     7ae7a3c826c0bdf9a3f893266fedb5c6356d7067cb54bef2ca8506194483b635
local     8ad42e37588d4bb6386f4c18e8c887ffd3a20d7ec4a4742947d01b6f7514331b
local     8b24b542f0d75f7073c47e555d155c7719cd5d65c09b5b03b2a3f87dab4ba513
local     98e980c61c1b6fac75f899303f959f9ff8f788fdb6094edba8349d2dd950ce34
local     824de8cf2066827829e7ff90efc66073607956d8ad6c33e9d3811f8ba2cbc3e0
local     9759e4fb808c4674d384785b6bc746122d0284cafb2c94623d900c7f3508931e
local     40334acb4196bae68de3232bacb4dad775cc63b9cb96f4d9940c99acc3a491ce
local     c69dc1de5d77b32eae6ccb7654921bbd63a07c4cf39b7b86ed818e79b211d480
local     d5c0e014d7499a3a08642700f8ca8208f2d32a2d06fded94a621a82ccbf3cfe5
local     e38488f4bd0dc6f910bee270bd1e1bd5ac9816d6f2e581f9406e7feab444cc45

然后找到我们刚刚创建的那个(这里我是一个一个找的…下面可以知道如何给volume命名~)

[root@iZwz9257qzx65bg8c3p88gZ _data]# docker volume inspect 8ad42e37588d4bb6386f4c18e8c887ffd3a20d7ec4a4742947d01b6f7514331b
[
    {
        "CreatedAt": "2021-11-28T16:06:46+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/8ad42e37588d4bb6386f4c18e8c887ffd3a20d7ec4a4742947d01b6f7514331b/_data",
        "Name": "8ad42e37588d4bb6386f4c18e8c887ffd3a20d7ec4a4742947d01b6f7514331b",
        "Options": null,
        "Scope": "local"
    }
]

Mountpoint对应的路径就是宿主机持久化数据的路径

[root@iZwz9257qzx65bg8c3p88gZ _data]# cd /var/lib/docker/volumes/8ad42e37588d4bb6386f4c18e8c887ffd3a20d7ec4a4742947d01b6f7514331b/_data
[root@iZwz9257qzx65bg8c3p88gZ _data]# ls
hello.txt
[root@iZwz9257qzx65bg8c3p88gZ _data]# cat hello.txt 
hello

经过验证发现数据的确从容器同步到了宿主机,完成了容器数据的持久化~

设置启动容器volume的名字

和上面不同的地方在于我们使用镜像启动容器的时候使用-v命令
docker container run -d -v VolumeName:DockerfileVOLUMEPath image

我们这里的命令就变成了

docker container run -it -p 3999:3999 -v my-data:/app 0526a62af1d2 sh

[root@iZwz9257qzx65bg8c3p88gZ _data]#  docker container run -it -p 3999:3999 -v my-data:/app  0526a62af1d2 sh
# ls
app  bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
# cd app
# ls
# echo "hello my data" > hello.txt
# ls
hello.txt
# cat hello.txt
hello my data
# exit

重复文件的操作

然后退出,来到宿主机,查看宿主机dockervolume

[root@iZwz9257qzx65bg8c3p88gZ _data]# docker volume ls
DRIVER    VOLUME NAME
local     0bdf00aab64d926f21a6f90342e391d84a4c6ec14b67fe249f8c96ac4e59d91b
local     0ea958861d42b680f60053c59c5384a44069d53e7229f47118ffd64399b46926
local     01b1566780ad5af79b7228f10741b14cc38246e784f3fa5669fe7888a94bfb09
local     3cea763fa6e484560cc489b2aa9f794d370f0f34809a0a4fdd2e513a9c474a74
local     5d599f822fd7cf3f217423af17d483f14deecde3f0adaab300b5c777b3e77636
local     5f61686f8e896c94fb4e1ad2f518e9fb4e4160be75c5358be430919f7a1f5130
local     6b3f0fc9738e3402273e21b605629e6d5dfbf34c37747df4818fa5cd2b1e6059
local     7ae7a3c826c0bdf9a3f893266fedb5c6356d7067cb54bef2ca8506194483b635
local     8ad42e37588d4bb6386f4c18e8c887ffd3a20d7ec4a4742947d01b6f7514331b
local     8b24b542f0d75f7073c47e555d155c7719cd5d65c09b5b03b2a3f87dab4ba513
local     98e980c61c1b6fac75f899303f959f9ff8f788fdb6094edba8349d2dd950ce34
local     824de8cf2066827829e7ff90efc66073607956d8ad6c33e9d3811f8ba2cbc3e0
local     9759e4fb808c4674d384785b6bc746122d0284cafb2c94623d900c7f3508931e
local     40334acb4196bae68de3232bacb4dad775cc63b9cb96f4d9940c99acc3a491ce
local     c69dc1de5d77b32eae6ccb7654921bbd63a07c4cf39b7b86ed818e79b211d480
local     d5c0e014d7499a3a08642700f8ca8208f2d32a2d06fded94a621a82ccbf3cfe5
local     e9b25fe9c662b3d06d2914878b3d1ec498532fa8bf936de61ec1b6076d0fa360
local     e38488f4bd0dc6f910bee270bd1e1bd5ac9816d6f2e581f9406e7feab444cc45
local     my-data

这个时候,你就可以发现其中一条volume是我们自定义的名称,查看详细的信息也的确是我们刚刚生成的

[root@iZwz9257qzx65bg8c3p88gZ _data]# docker volume inspect my-data
[
    {
        "CreatedAt": "2021-11-28T16:24:42+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/my-data/_data",
        "Name": "my-data",
        "Options": null,
        "Scope": "local"
    }
]

验证数据是否同步到了宿主机✅

[root@iZwz9257qzx65bg8c3p88gZ _data]# cd /var/lib/docker/volumes/my-data/_data
[root@iZwz9257qzx65bg8c3p88gZ _data]# ls
hello.txt
[root@iZwz9257qzx65bg8c3p88gZ _data]# cat hello.txt 
hello my data

新容器使用宿主机的数据

已经会把容器(container)中的数据和文件,保存在操作系统上了。现在的需求是,再创建一个容器,新容器如何用我们之前用volume保存下来的的持久化数据?

现在我们本地已经有了之前的容器同步持久化下来的数据了,那么如果我们重新起了一个容器,如果去使用这一块数据呢~其实很简单和指定volume名称的命令是一样的

[root@iZwz9257qzx65bg8c3p88gZ docker-test]# docker container run -it -p 3002:3002 -v my-data:/app --name datafromlocal volume-test sh
# ls
app  bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
# cd app
# ls
hello.txt
# cat hello.txt
hello my data
# exit

Bind Mount实现数据持久化

数据持久化除了Data Volume外,还有一种叫做Bind Mount,从中文翻译来讲,就是挂载绑定。简单讲就是把容器中持久化的数据,绑定到本机的一个自定义位置

Data Volume,在WIndows/Mac环境中很难使用,因为路径是虚拟机的路径,不容易找到(mac都不太好找到的,下图的问题还未有解决方法,mac下找不到~哈哈)

image-20211128165421450

相较于Data Volume来说 Bind Mount 设置更简单,可以和开发环境更好的融合

[root@iZwz9257qzx65bg8c3p88gZ docker-test]# docker container run -it -p 3002:3002 -v ~/docker-test:/app --name datafromlocal volume-test sh
# ls
app  bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
# cd app
# ls
dockerfile
# cat dockerfile 
FROM ubuntu:21.04
VOLUME ["/app"]
RUN apt-get update && \
    apt-get install vim -y

# ls
dockerfile
# exit
这种用法其实就是自定义了一个宿主机的目录同容器内的某个目录做绑定挂在,而不是像volume帮你管理在某个规定好的位置
[root@iZwz9257qzx65bg8c3p88gZ docker-test]# ls
dockerfile
[root@iZwz9257qzx65bg8c3p88gZ docker-test]# docker container run -it -p 3002:3002 -v ~/docker-test:/app --name datafromlocal volume-test sh
# cd app
# ls
dockerfile
# vim newFile.txt
# exit
[root@iZwz9257qzx65bg8c3p88gZ docker-test]# ls
dockerfile  newFile.txt

完成了宿主机和容器的数据共享持久化!

  • 容器内创建了一个newFile.txt
  • 退出容器回到宿主机通过ls命令,发现已经从容器中同步过来,完成了容器数据的持久化