Docker容器中服务执行script.sh后自动停止的问题求助
问题原因与解决方法
核心原因
- 容器生命周期绑定主进程:Docker容器的存活完全依赖启动时的主进程状态。你的
script.sh执行完exit 0后,主进程直接终止,容器随即停止。 - CMD指令的执行逻辑:
CMD是容器启动阶段触发的命令,而非镜像构建阶段的RUN指令。因此每次重启服务,都会重新执行初始化脚本,执行完成后再次触发容器停止。
解决方法
根据使用场景,选择对应方案:
方案1:初始化仅执行一次(生产环境推荐)
将初始化操作与容器长期运行的服务解耦,确保容器启动后持续运行web服务。
方式A:修改脚本,最后启动web服务
先调整Dockerfile指令顺序(WORKDIR必须在CMD之前,否则脚本执行时工作目录不正确):
COPY script.sh /sh/script.sh RUN chmod +x /sh/script.sh WORKDIR /var/www CMD /sh/script.sh
再修改script.sh,移除exit 0,最后启动Drupal依赖的web服务(根据你的环境替换为Apache或PHP-FPM命令):
#!/usr/bin/env bash # 顺序执行初始化操作,无需后台运行 php ./web/vendor/bin/drush cim -y php ./web/vendor/bin/drush cr # 启动前台运行的web服务,作为容器主进程 apache2-foreground
方式B:使用初始化容器(适合依赖外部服务的场景)
如果初始化需要等待数据库等外部服务就绪,用docker-compose的初始化容器单独执行初始化,主容器仅负责运行web服务:
services: app: build: docker command: apache2-foreground # 直接启动web服务 depends_on: - init init: build: docker command: /sh/script.sh depends_on: - db # 替换为你的数据库服务名 volumes: - ./web:/var/www/web # 共享代码目录,确保初始化配置生效
初始化容器执行完脚本后会自动停止,但主app容器会持续运行。
方案2:每次启动都执行初始化(开发环境适用)
如果开发时需要每次启动都刷新配置,修改脚本让最后启动的web服务成为容器主进程:
#!/usr/bin/env bash # 执行初始化操作 php ./web/vendor/bin/drush cim -y php ./web/vendor/bin/drush cr # 用exec让web服务替换当前脚本进程,绑定容器生命周期 exec php-fpm # 替换为你实际使用的web服务命令
exec命令会让web服务进程接管脚本的进程ID,确保容器不会因为脚本执行完成而停止。
内容的提问来源于stack exchange,提问作者Haamome
相关产品推荐
相关产品推荐

