docker-compose build时RUN yarn install完成后挂起如何解决
该挂起问题与yarn依赖安装逻辑本身无关,核心原因是你使用的node:14-stretch-slim基础镜像中,yarn首次执行安装时会触发postinstall脚本、可选依赖编译、网络探测等子任务,部分子任务在主安装流程结束后不会主动退出,残留的进程会持有标准输入输出句柄;而Docker构建RUN步骤的判定逻辑是等待该步骤启动的所有子进程全部退出后才会进入下一阶段,首次构建无缓存时文件系统IO压力较高,子进程回收出现阻塞就会触发永久挂起。
命中缓存时不会实际执行yarn install逻辑,没有残留进程,因此可以正常执行后续步骤。另外你compose配置里的stdin_open: true属于服务运行阶段参数,和构建阶段挂起没有关联,不需要调整。
按生效概率从高到低排序,可逐个尝试:
- 给yarn install增加无交互参数,并在安装结束后强制清理残留yarn相关进程,修改Dockerfile中对应RUN命令:
RUN yarn install --frozen-lockfile --silent --non-interactive && \ pkill -f yarn || true
*--frozen-lockfile会严格按照现有yarn.lock文件安装依赖,避免版本漂移;--silent关闭非必要日志输出减少IO占用;末尾的pkill命令会强制清理所有yarn启动的残留子进程,|| true用于避免无匹配进程时命令返回非零错误导致构建中断。
- 如果上述方案仍存在挂起问题,可临时禁用yarn的install脚本执行:
RUN yarn install --frozen-lockfile --silent --non-interactive --ignore-scripts
注意:如果你的项目存在必须执行的install阶段逻辑(比如依赖补丁注入、二进制资源拉取),不要使用该方案,优先选择上一种方案。
- 增加轻量init进程负责回收残留子进程,解决Docker默认无init进程导致的僵尸进程残留问题,修改builder阶段开头配置:
FROM node:14-stretch-slim as frontend-builder # 安装tini作为init进程自动回收残留子进程 RUN apt-get update && apt-get install -y --no-install-recommends tini && \ rm -rf /var/lib/apt/lists/* ENTRYPOINT ["/usr/bin/tini", "--"] WORKDIR /app/frontend COPY ./frontend . ENV PATH ./node_modules/.bin/:$PATH RUN yarn install --frozen-lockfile RUN yarn build
- 替换已停止维护的基础镜像:
node:14-stretch-slim已结束生命周期,内置的早期yarn 1.22版本存在已知的进程句柄泄漏问题,可替换为同大版本的维护中镜像:
FROM node:14-bullseye-slim as frontend-builder
该版本镜像内置的yarn版本已修复安装完成后子进程不退出的问题,无需额外调整参数即可正常构建。
修改配置后执行无缓存构建验证:
docker-compose build --no-cache frontend
若yarn install输出完成提示后10秒内自动进入yarn build执行步骤,即代表问题修复。
内容的提问来源于stack exchange,提问作者user19271630

