如何在Makefile中通过单次docker-compose调用避免重复启动PHP镜像执行多条命令
可行实现方案
你之前尝试的管道写法为什么不对
管道的核心作用是将前一个命令的输出作为后一个命令的输入传递,根本不是实现同容器内多命令顺序执行的手段。按照你写的逻辑,只有第一行
$(PHP) php composer config ...是真正在容器内执行的,后面接管道的所有php、curl命令,实际上都是在宿主机本地直接运行的,既没有进容器,也完全达不到预期的执行效果。
正确的实现思路
只需要把所有原本要在PHP容器内执行的命令,拼接成一段完整的shell脚本,作为单次docker-compose run的启动参数传入,就能保证仅启动一次容器、跑完所有命令后自动清理。
具体改造点:
- 用容器内的
sh -c作为最终的执行入口,把所有要跑的命令用&&连接,保证任意一步执行失败时直接中断后续流程 - Makefile中通过行尾反斜杠实现长命令的换行,避免单条命令过长难以阅读
改造完成后的Makefile示例
COMPOSE=docker-compose PHP=$(COMPOSE) run --rm -u `id -u`:`id -g` -T php .SILENT: .PHONY: help install-dependencies: $(PHP) sh -c ' \ php composer config --global disable-tls true && \ php composer config --global secure-http false && \ curl -sS https://getcomposer.org/installer > composer-setup.php && \ php composer-setup.php && \ php -r "unlink('"'"'composer-setup.php'"'"');" && \ php composer.phar install --ignore-platform-reqs \ '
额外说明
- 上述写法全程只会触发1次PHP容器的启动流程,不会反复初始化容器,执行效率会比原来逐行调用的方式提升非常明显
- 用
&&串联命令的错误处理逻辑,和你原来逐行写Makefile命令的行为完全一致:只要任意一步执行失败,整个流程就会直接中断,不会继续执行后续步骤 - 如果你觉得命令里的单引号转义太繁琐,也可以把这段容器内的执行逻辑单独写到一个shell脚本里,通过docker-compose的卷挂载映射到容器内执行;对于当前场景下的几行简单命令,直接用
sh -c拼接是最轻量化的方案,不需要额外新增文件。
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

