命名容器在不同 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
不变。如果您将解释器和文件名拆分为单独的 ENTRYPOINT
和 CMD
,您可以将它们组合成一个 CMD
行(无论如何都应该这样做)。
...
ENTRYPOINT ["entrypoint.sh"]
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
在构建生命周期方面,图像是在没有任何周围的 Compose 生态系统的情况下构建的;他们不知道网络环境、卷、环境变量、绑定安装等等;因此,当您重建映像时,您构建了一个新的更改后的映像,但根本不修改卷。第一次 运行 整个文件时,由于指定的卷是空的,因此它填充了卷中的内容,但这只会在第一次 运行 时发生。
重建图像和重新启动容器在 Docker 中非常常见,我不会试图避免这种情况。 (如果需要更改设置,re-运行ning docker-compose up -d
将删除并重新创建现有容器,这是非常常规的事情。)
我见过一些类似的问题,但我自己找不到解决方案。
我有 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
不变。如果您将解释器和文件名拆分为单独的 ENTRYPOINT
和 CMD
,您可以将它们组合成一个 CMD
行(无论如何都应该这样做)。
...
ENTRYPOINT ["entrypoint.sh"]
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
在构建生命周期方面,图像是在没有任何周围的 Compose 生态系统的情况下构建的;他们不知道网络环境、卷、环境变量、绑定安装等等;因此,当您重建映像时,您构建了一个新的更改后的映像,但根本不修改卷。第一次 运行 整个文件时,由于指定的卷是空的,因此它填充了卷中的内容,但这只会在第一次 运行 时发生。
重建图像和重新启动容器在 Docker 中非常常见,我不会试图避免这种情况。 (如果需要更改设置,re-运行ning docker-compose up -d
将删除并重新创建现有容器,这是非常常规的事情。)