docker 通过卷持久存储

docker persistent storage via volume

阅读的所有内容都说我们可以通过 VOLUME 控件创建 docker 持久存储,例如 here and here.

但是,我的 Dockerfile 中有以下内容:

VOLUME      ["/home", "/root"]

但里面没有任何东西(我试过 touch abc,当我退出并再次进入时文件不存在)。

我看到 official usage 没有其他特殊的控制或处理,但它可以提供持久存储,即使 apt-cacher-ng 服务容器停止。

这怎么可能?我已经检查了以下内容,但仍然没有任何线索:

总之,如解释的那样here

The first mechanism will create an implicit storage sandbox for the container that requested host-based persistence. ... The key thing to understand is that the data stored in the sandbox is not available to other containers, except the one that requested it.

我怎样才能使持久存储工作?为什么我的更改每次都被擦除,而 apt-cacher-ng 服务容器即使停止并重新启动也能保持其持久存储? 我这里没看到的"other special controls or treatments"是什么?

请用简单的 Dockerfile(而不是 docker-compose.yml)进行解释。

问题在于,当使用 docker 运行 而没有针对该特定文件夹的 "mount" 选项时,VOLUME 指令会创建外部存储。换句话说,每次为该图像创建容器时,docker 都会创建一个带有随机标签的新卷,但由于您没有为这些卷命名,新容器无法重复使用现有的生成卷。

例如

FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

给定这个 Dockerfile,如果您使用以下命令简单地构建和 运行 这个 docker 图像:

echo "There are currently $(docker volume ls | wc -l) volumes"

docker build -t my_volume_test:latest .
docker run --name another_test my_volume_test:latest

echo "There are currently $(docker volume ls | wc -l) volumes"

您会看到计算机上的卷数量增加了。该容器现在使用一个卷来存储数据,但该特定卷没有名称或标签,因此它仅绑定到该特定容器。如果您删除并重新创建该容器,docker 将生成一个具有随机名称的新卷,除非您设法装载之前创建的卷。

如果你想简单点,我建议先创建卷然后挂载它。例如

docker rm -f another_test
docker volume create my-vol

docker run \
    --name another_test \
    --mount source=my-vol,target=/myvol \
    my_volume_test:latest

# alternative
docker rm -f another_test
docker run \
    --name another_test \
    -v my-vol:/myvol \
    my_volume_test:latest

在这种情况下,您可以创建和删除任意数量的容器,但它们都将使用相同的卷。

查看 VOLUME reference and Use volumes 了解更多信息。