- 默认情况下,在运行中的容器里创建的文件会被保存在一个可写的容器层
- 如果这个容器被删除,数据也会随之丢失(停止容器时不会丢失数据)
- 可写的容器层和特定的容器进行绑定,即这些数据无法方便的与其他容器共享
针对数据持久化的问题,Docker主要提供了两种方式:
- Data Volume:由Docker管理,是持久化数据最佳方式
- Bind Mount:由用户指定储存的数据挂载在系统什么位置
1. Data Volume
- 创建一个Dockerfile文件和my-cron文件,这个镜像的作用是执行计划任务(这里是每隔一分钟输出时间到一个文件里),具体过程可以参考Docker Blog:
Dockerfile_Volume:
FROM alpine:latest RUN apk update RUN apk --no-cache add curl ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \ SUPERCRONIC=supercronic-linux-amd64 \ SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e RUN curl -fsSLO "$SUPERCRONIC_URL" \ && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ && chmod +x "$SUPERCRONIC" \ && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \ && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic COPY my-cron /app/my-cron WORKDIR /app # RUN cron job CMD ["/usr/local/bin/supercronic", "/app/my-cron"]my-cron:
*/1 * * * * date >> /app/test.txt
- 创建镜像:
docker image build -f Dockerfile_Volume -t my-cron .- 创建容器:
docker container run -d my-cron- 进入交互式shell:
docker container exec -it 379 sh完成上述操作后进入到容器内部后,会查看到my-cron文件和output.txt文件,每隔一分钟去查看output.txt会出现新的时间戳。
问题1:如果将容器删除后,output.txt文件也就被删除了,该如何持久化储存在磁盘上?
- 修改Dockerfile文件,在其中添加VOLUME命令:
Dockerfile_Volume_New:
FROM alpine:latest RUN apk update RUN apk --no-cache add curl ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \ SUPERCRONIC=supercronic-linux-amd64 \ SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e RUN curl -fsSLO "$SUPERCRONIC_URL" \ && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ && chmod +x "$SUPERCRONIC" \ && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \ && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic COPY my-cron /app/my-cron WORKDIR /app VOLUME ["/app"] # RUN cron job CMD ["/usr/local/bin/supercronic", "/app/my-cron"]
VOLUME ["/app"]:/app表示VOLUME需要持久化的容器目录
- 重新构建镜像和容器
- 查看已经存在的VOLUME的NAME:执行
docker volume ls会出现VOLUME NAME- 查看VOLUME详细的信息:执行
docker volume inspect (完整的VOLUME NAME),会出现该VOLUME详细的信息,其中Mountpoint就是该VOLUME储存文件(即容器/app目录下的文件)的位置,此时便可以查看该位置下被持久化储存的文件(在Windows系统下是无法直接根据这个路径进行查看文件,需要到docker engine中查看),这个文件同样每隔一分钟会出现新的时间戳
问题2:此时使用该镜像再次创建新的容器,就会出现一个新的VOLUME(VOLUME NAME每次是随机的),导致数据储存的位置不一样了,但是我们的目的是尽管创建了新容器,还是要使用相同VOLUME的数据(即可以继续使用原来output.txt中的数据),要实现这个要求该如何操作?
- 创建新容器的时候指定VOLUME的名字:执行
docker container run -d -v cron-data:/app my-cron。其中,cron-data为自定义的VOLUME名字,/app与dockerfile文件中VOLUME ["/app"]的含义一致(不在dockerfile文件中写命令,直接指定-v也可)。这样再次创建新容器时执行相同的命令,就可以使用相同的VOLUMEtips:
docker volume prune -f:删除所有的volume(删除volume前要删除所属容器)
2. Bind Mount
在使用Data Volume时,每次执行如
docker container run -d -v cron-data:/app my-cron命令时,相当于使用cron-data这个Volume给你指定的储存路径,这样会导致之前提到的Windows系统下无法直接查看储存的文件的情况。如果能直接指定本地用于储存文件的路径就会方便很多,此时就要使用Bind Mount:
docker container run -d -v $(pwd):/app my-cron:将原来的命令中指定的Volumecron-data改为当前路径$(pwd)(Linux下为圆括号,Windows下为大括号)即可,此时再使用docker volume ls不会出现新的Volume,并且在本机当前目录下会出现output.txt文件。假如当前本机中没有gcc的编译环境,要使用container去完成某个C文件的编译和执行该如何操作?
- 在本地的当前目录创建需要执行的hello.c文件
- 创建一个
gcc:9.4的镜像- 执行
docker container run --it -v $(pwd):/root gcc:9.4进入到容器中- 此时在容器root目录下会出现hello.c文件,执行
gcc -o hello hello.c和./hello即可完成- 在本地的当前目录也会出现编译好的hello文件
3. 多个机器之间的容器共享数据
之前的内容我们是将本地的目录和容器中的目录进行挂载,所以在查看VOLUME详细信息时会看到
Driver:'local':
此时要实现两台主机容器间的数据共享该如何操作?
假设有两台主机,信息如下:
hostname ip ssh username ssh password docker-host1 192.168.200.10 vagrant vagrant docker-host2 192.168.200.11 vagrant vagrant
在两台主机上都安装一个plugin
vieux/sshfs:执行docker plugin install --grant-all-permissions vieux/sshfs在docker-host1中创建volume:
docker volume create --driver vieux/sshfs \ -o sshcmd=vagrant@192.168.200.12:/home/vagrant \ -o password=vagrant \ sshvolume 其中,
vagrant@192.168.200.12:/home/vagrant表示指定目标主机储存的目录,sshvolume为创建的VOLUME NAME。此时查看该VOLUME的详细信息时会发现Mountpoint发生了改变,下图中表示将docker-host2的/home/vagrant挂载到了docker-host1的Mountpoint:
- 创建容器挂载Volume:执行
docker container run -it -v sshvolume:/app busybox sh,即实现挂载sshvolume到使用busybox镜像创建的容器的/app目录,然后进入容器的shell,在/app目录创建一个test.txt文件。此时在docker-host1、docker-host2都会出现test.txt文件
4. 参考
https://dockertips.readthedocs.io/en/latest/docker-volume.html
https://dockertips.readthedocs.io/en/latest/docker-blog/docker-cron.html
https://docs.docker.com/storage/volumes/#share-data-among-machines
本文介绍了Docker中数据持久化的两种方法:DataVolume和BindMount。通过实例演示如何使用这两种方法来解决容器内数据的持久化问题,并进一步讨论了如何在多台主机之间共享容器数据。




5902

被折叠的 条评论
为什么被折叠?



