Dockerfile 中的 运行 和 docker-compose.yml 文件中的命令之间的区别
The difference between RUN in a Dockerfile and command in a docker-compose.yml file
这个问题一直困扰着我,因为我想遵循最佳实践,如果不知道每个命令的用途,我可能会犯架构错误。那么,谁能向我解释一下何时在 Dockerfile
中使用 RUN
命令与在 docker-compose.yml
文件中使用 command
指令?
据我了解,Dockerfile
应该包含构建映像的说明,因此通过逻辑命令(例如迁移数据库)应该在此处。 docker-compose.yml
文件包含构建环境的说明。不过,我感到困惑的是为什么似乎有选项可以在两个文件中放置 运行 命令的说明。
Dockerfile
是关于如何构建新的 image 的收据,例如docker build
,而 docker-compose
用于编排启动(多个)容器。
Dockerfile
中的 RUN
指令在映像的构建阶段执行,其结果将提交给映像。 docker-compose.yml
中的 command
属性对应于 CMD
directive in a Dockerfile
and to the optional command parameter of docker run
并指定在 启动 基于给定图像的新容器时要执行的命令。
另请参阅:
假设您想将申请的副本发送给同事。他们不需要整个源代码树,因为他们只是想 运行 应用程序。您可以想象 运行 使用一些命令来构建和安装应用程序,创建结果的 tar 文件,然后将该 tar 文件发送给它们。那些“构建和安装”命令应该是 Dockerfile RUN
命令。
I'm confused about [...] why there seem to be options to put instructions for running commands in both [Dockerfile and docker-compose.yml
].
举一个非常典型的例子,假设您有一个 Python Django 应用程序,它也恰好能够 运行 使用 Celery 框架在后台执行一些任务。主 Web 服务器和后台工作程序都具有完全相同的源代码;这只是启动容器时 运行ning 什么命令的问题。
在这种情况下,您的 Dockerfile 会声明一些有用的默认值 CMD
,对 运行 Django 应用程序说:
FROM python:3.10
...
CMD ./manage.py runserver 0.0.0.0:8000
在您的 docker-compose.yml
文件中,您可以 运行 此图像 两次 ,但对于第二个,您将覆盖 command:
.
version: '3.8'
services:
app:
build: .
ports: ['8000:8000']
# using the default Dockerfile CMD
worker:
build: .
command: celery -A proj worker
特别是如果您的应用程序只需要一个命令 运行,最好在 Dockerfile 中声明它。我猜 90% 以上的案例不需要 Compose command:
。没有理由在 Compose 文件中重复相同的命令。
我会避免在 CMD
或 command:
中编写扩展的 multi-line 命令。相反,编写一个 shell 脚本来完成您需要做的所有事情,COPY
将脚本放入图像中,并将该脚本设置为您的 CMD
。 (还有一种模式我喜欢使用 ENTRYPOINT
来完成设置任务并以 exec "$@"
到 运行 结束 CMD
。)
... a Dockerfile should contain [...] commands which for instance migrate a database ...
这实际上行不通。记住我假设的tar问题:如果构建指令的一部分 运行 数据库迁移,然后您只将文件系统的 tar 文件发送给您的同事,他们的数据库不会有 运行 迁移。出于几个原因,如果您的数据库也在容器中,图像构建序列将无法联系数据库(如果它根本 运行ning)。
例如, 中有更多关于此主题的讨论。请注意,那里的答案有 multi-line Compose command:
;如上所述,我可能会把它写成一个脚本,并让脚本成为图像的 CMD
。
这个问题一直困扰着我,因为我想遵循最佳实践,如果不知道每个命令的用途,我可能会犯架构错误。那么,谁能向我解释一下何时在 Dockerfile
中使用 RUN
命令与在 docker-compose.yml
文件中使用 command
指令?
据我了解,Dockerfile
应该包含构建映像的说明,因此通过逻辑命令(例如迁移数据库)应该在此处。 docker-compose.yml
文件包含构建环境的说明。不过,我感到困惑的是为什么似乎有选项可以在两个文件中放置 运行 命令的说明。
Dockerfile
是关于如何构建新的 image 的收据,例如docker build
,而 docker-compose
用于编排启动(多个)容器。
Dockerfile
中的 RUN
指令在映像的构建阶段执行,其结果将提交给映像。 docker-compose.yml
中的 command
属性对应于 CMD
directive in a Dockerfile
and to the optional command parameter of docker run
并指定在 启动 基于给定图像的新容器时要执行的命令。
另请参阅:
假设您想将申请的副本发送给同事。他们不需要整个源代码树,因为他们只是想 运行 应用程序。您可以想象 运行 使用一些命令来构建和安装应用程序,创建结果的 tar 文件,然后将该 tar 文件发送给它们。那些“构建和安装”命令应该是 Dockerfile RUN
命令。
I'm confused about [...] why there seem to be options to put instructions for running commands in both [Dockerfile and
docker-compose.yml
].
举一个非常典型的例子,假设您有一个 Python Django 应用程序,它也恰好能够 运行 使用 Celery 框架在后台执行一些任务。主 Web 服务器和后台工作程序都具有完全相同的源代码;这只是启动容器时 运行ning 什么命令的问题。
在这种情况下,您的 Dockerfile 会声明一些有用的默认值 CMD
,对 运行 Django 应用程序说:
FROM python:3.10
...
CMD ./manage.py runserver 0.0.0.0:8000
在您的 docker-compose.yml
文件中,您可以 运行 此图像 两次 ,但对于第二个,您将覆盖 command:
.
version: '3.8'
services:
app:
build: .
ports: ['8000:8000']
# using the default Dockerfile CMD
worker:
build: .
command: celery -A proj worker
特别是如果您的应用程序只需要一个命令 运行,最好在 Dockerfile 中声明它。我猜 90% 以上的案例不需要 Compose command:
。没有理由在 Compose 文件中重复相同的命令。
我会避免在 CMD
或 command:
中编写扩展的 multi-line 命令。相反,编写一个 shell 脚本来完成您需要做的所有事情,COPY
将脚本放入图像中,并将该脚本设置为您的 CMD
。 (还有一种模式我喜欢使用 ENTRYPOINT
来完成设置任务并以 exec "$@"
到 运行 结束 CMD
。)
... a Dockerfile should contain [...] commands which for instance migrate a database ...
这实际上行不通。记住我假设的tar问题:如果构建指令的一部分 运行 数据库迁移,然后您只将文件系统的 tar 文件发送给您的同事,他们的数据库不会有 运行 迁移。出于几个原因,如果您的数据库也在容器中,图像构建序列将无法联系数据库(如果它根本 运行ning)。
例如,command:
;如上所述,我可能会把它写成一个脚本,并让脚本成为图像的 CMD
。