Docker Compose 中执行多条命令的方法
技术背景
在使用 Docker Compose 部署应用时,有时需要在一个服务中执行多条命令,例如在启动 Django 应用时,可能需要先执行数据库迁移命令,再启动开发服务器。然而,Docker Compose 默认只能指定一个 command,因此需要找到一种方法来执行多条命令。
实现步骤
方法一:使用 bash -c
可以使用 bash -c 来执行多条命令,示例如下:
version: '3'
services:
web:
build: .
command: bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
volumes:
- .:/code
ports:
- "8000:8000"
也可以写成多行形式:
version: '3'
services:
web:
build: .
command: >
bash -c "python manage.py migrate
&& python manage.py runserver 0.0.0.0:8000"
volumes:
- .:/code
ports:
- "8000:8000"
方法二:使用 sh -c
对于大多数基于 Unix 的镜像,sh 比 bash 更常用,示例如下:
version: '3'
services:
app:
build:
context: .
command: >
sh -c "python manage.py wait_for_db &&
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
方法三:使用单独的临时容器
可以将预启动的操作(如数据库迁移)放在一个单独的临时容器中执行,示例如下:
version: '2'
services:
db:
image: postgres
web:
image: app
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db
depends_on:
- migration
migration:
build: .
image: app
command: python manage.py migrate
volumes:
- .:/code
links:
- db
depends_on:
- db
方法四:使用数组形式
version: '3.1'
services:
web:
build: .
command:
- /bin/bash
- -c
- |
python manage.py migrate
python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db
方法五:使用 entrypoint
可以创建一个启动脚本,将其作为 entrypoint 执行,示例如下:
# docker-entrypoint.sh
#!/bin/bash
python manage.py migrate
exec "$@"
version: '3'
services:
web:
build: .
entrypoint: /docker-entrypoint.sh
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db
核心代码
以下是使用 bash -c 执行多条命令的完整 docker-compose.yml 示例:
version: '3'
services:
db:
image: postgres
web:
build: .
command: bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db
最佳实践
- 选择合适的方法:根据镜像的基础系统和具体需求选择合适的方法。如果镜像中没有安装
bash,可以使用sh -c;如果需要将预启动操作和主服务分离,可以使用单独的临时容器。 - 使用脚本:将复杂的命令逻辑封装在脚本中,提高代码的可读性和可维护性。
- 处理依赖关系:使用
depends_on确保服务的启动顺序正确,对于需要等待数据库等服务就绪的情况,可以使用wait-for-it.sh等工具。
常见问题
镜像中没有安装 bash
如果镜像中没有安装 bash,可以使用 sh -c 代替,例如:
version: '3'
services:
app:
build: .
command: sh -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
depends_on 不能保证服务就绪
depends_on 只能保证服务按顺序启动,但不能保证服务已经就绪。可以使用 wait-for-it.sh 等工具来解决这个问题,示例如下:
version: '3'
services:
db:
image: postgres
web:
build: .
command: >
bash -c "./wait-for-it.sh db:5432 -- python manage.py makemigrations
&& python manage.py migrate
&& python manage.py runserver 0.0.0.0:8000"
depends_on:
- db
变量替换问题
docker-compose 在运行命令之前会尝试解析变量,如果需要 bash 处理变量,需要对美元符号进行转义,示例如下:
version: '3.1'
services:
web:
build: .
command:
- /bin/bash
- -c
- |
var=$$(echo 'foo')
echo $$var # prints foo
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db
1万+

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



