如何在 docker-compose 中执行多条命令?
command 字段用 sh -c "cmd1 && cmd2 && cmd3" 串多条命令,YAML 用 > 折叠多行书写;更规范的做法是把初始化逻辑放 entrypoint 脚本。本文给出写法与注意事项。
写法:在 command 里用 shell 串联——command: > sh -c "命令1 && 命令2 && 命令3"(> 是 YAML 折叠语法,多行会拼成一行)。&& 表示前一条成功才执行下一条;无论成败都执行用 ;。
基本写法
services:
app:
build: .
command: >
sh -c "python manage.py migrate &&
python manage.py collectstatic --noinput &&
python manage.py runserver 0.0.0.0:8000"
典型场景:启动前先做数据库迁移、收集静态文件,再起服务。
更规范的做法:entrypoint 脚本
命令多了之后 command 会越来越难读,推荐抽成脚本:
#!/bin/sh
set -e
python manage.py migrate
python manage.py collectstatic --noinput
exec gunicorn -w 4 app.wsgi:application
services:
app:
entrypoint: ["/app/entrypoint.sh"]
好处:set -e 出错即停、exec 让主进程成为 PID 1(能收到停止信号)、脚本可独立测试、逻辑可版本管理。
注意事项
- 最后一条命令要以前台运行:主进程退出 = 容器退出。不要在末尾加
&或 daemonize。 &&与;的区别:迁移失败就不该起服务,用&&。- 多命令里只有最后的主进程收到信号:前面都是一次性命令没问题;若需要同时跑多个长期进程,该拆成多个服务(sidecar)或用 supervisord。
- 依赖顺序:迁移需要数据库先就绪,配
depends_on+ 健康检查,或在脚本里做等待重试。
观测云对照
启动阶段日志别丢。 迁移、初始化这些启动期输出是排障关键信息,DataKit 采集容器 stdout 后完整留存,服务起不来时直接查启动阶段日志定位卡在哪一步。
常见问题(FAQ)
Q:YAML 里 > 和 | 有什么区别?
A:> 折叠(换行变空格,适合拼成一条命令);| 保留换行。写多行命令用 >。
Q:command 和 entrypoint 都写会怎样?
A:command 整体作为参数传给 entrypoint,组合执行。
Q:能在 command 里写 shell 变量和判断吗?
A:可以,走 sh -c 就是完整 shell 语法,但复杂了就该进 entrypoint 脚本。