You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器中服务执行script.sh后自动停止的问题求助

问题原因与解决方法

核心原因

  1. 容器生命周期绑定主进程:Docker容器的存活完全依赖启动时的主进程状态。你的script.sh执行完exit 0后,主进程直接终止,容器随即停止。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 04:22:38