命名容器在不同 docker-compose 文件之间共享

Named container shared between different docker-compose files

我见过一些类似的问题,但我自己找不到解决方案。

我有 2 个 docker-compose 文件,我创建了一个命名卷,我目前正在这样使用它:

app:
    ...
    volumes:
      - volume_static:/path/to/container
    ...
...
volumes:
  ...
  volume_static:
    external:
      name: static
  ...
...

在构建过程中,脚本会向该卷添加一些新文件,但是随后,第二个 docker-compose(以完全相同的方式安装卷)无法访问新数据,我需要重新启动它才能正常工作。

这是正确的方法吗?

我只需要从一个 docker-compose 将一些新文件推送到卷中,然后直接在第二个 docker-compose 上看到它们(是的,我知道,docker ,但是说指定 compose 可以更好地了解我的问题)而无需重新启动和构建服务

这可能吗?

谢谢!

Docker 认为命名卷用于保存用户数据,以及其他不属于正常容器生命周期的内容。

如果您使用空卷启动容器,只有在第一次 运行 时,Docker 才会将图像中的内容加载到卷中。 Docker 对此没有更新机制:由于该卷可能包含用户数据,Docker 不能冒用更新映像中的内容覆盖文件来破坏它的风险。

此处最好的方法是完全避免共享文件。如果文件类似于后端应用程序的静态资产,您可以使用后端应用程序的图像名称和标签 (COPY --from=my/backend ...),将这些文件从后端图像 COPY --from 转换为代理图像。这完全避免了对音量的需要。

如果您确实必须在卷中共享文件,那么提供文件的容器需要负责在启动时自行复制文件。入口点脚本是执行此操作最简单的地方;当容器启动时(卷存在并已安装)但在 运行 启动主容器进程之前,它会为您提供 运行 的挂钩。

#!/bin/sh
set -e

# Populate (or update) the shared static tree
cp -r ./app/assets /static

# Now run the image CMD
exec "$@"

将此脚本设为 Docker 文件中的 ENTRYPOINT;它必须使用 JSON-array 语法。您可以保持 CMD 不变。如果您将解释器和文件名拆分为单独的 ENTRYPOINTCMD,您可以将它们组合成一个 CMD 行(无论如何都应该这样做)。

...
ENTRYPOINT ["entrypoint.sh"]
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

在构建生命周期方面,图像是在没有任何周围的 Compose 生态系统的情况下构建的;他们不知道网络环境、卷、环境变量、绑定安装等;因此,当您重建映像时,您构建了一个新的更改后的映像,但根本不修改卷。第一次 运行 整个文件时,由于指定的卷是空的,因此它填充了卷中的内容,但这只会在第一次 运行 时发生。

重建图像和重新启动容器在 Docker 中非常常见,我不会试图避免这种情况。 (如果需要更改设置,re-运行ning docker-compose up -d 将删除并重新创建现有容器,这是非常常规的事情。)