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

如何让docker-compose在多阶段构建时等待子模块构建完成再构建主应用

问题:Docker Compose首次构建主应用时,因子模块镜像未生成报错

项目结构

my-app/
├─ my-submodule/
│  ├─ .git
│  ├─ Dockerfile
│  ├─ ...
├─ .git/
├─ .gitmodules
├─ docker-compose.yml
├─ Dockerfile
├─ .dockerignore
├─ ...

需求与当前配置

my-app包含子模块my-submodule,需先编译子模块再构建主应用。采用多阶段构建:

子模块Dockerfile

FROM ubuntu AS my-submodule
WORKDIR /my-submodule
COPY . 
# 子模块编译逻辑...

主应用Dockerfile

FROM my-submodule AS my-app
WORKDIR /my-app
COPY . .
# 主应用构建逻辑...

docker-compose.yml

version: "3.9"

services:
  my-submodule:
    image: my-submodule
    build:
      context: ./my-submodule
      target: my-submodule
  my-app:
    build:
      context: .
      dockerfile: Dockerfile
      target: my-app
    image: my-app
    depends_on:
      - my-submodule

.dockerignore已忽略my-submodule目录,避免主应用构建时重复复制子模块内容。

报错信息

首次运行docker-compose build时出现以下错误:

=> ERROR [my-app internal] load metadata for docker.io/library/my-submodule:latest 0.4s
...
failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to create LLB definition: pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed

再次运行构建正常,因为my-submodule镜像已存在本地。

问题原因

depends_on指令仅控制容器启动顺序,对docker-compose build的镜像构建顺序没有约束。首次构建时,Compose会并行尝试构建所有服务的镜像,主应用构建时本地还没有my-submodule镜像,就会尝试从Docker Hub拉取,导致拉取失败报错。

解决方案

方案1:显式指定构建顺序

每次构建时手动指定先构建子模块,再构建主应用:

docker-compose build my-submodule my-app

缺点:需要手动指定顺序,无法自动固化到配置中。

方案2:使用构建阶段的依赖(推荐)

在Compose文件的my-app服务的build配置中添加depends_on,明确指定依赖子模块的构建任务。该特性支持Compose文件版本3.7及以上:

version: "3.9"

services:
  my-submodule:
    image: my-submodule
    build:
      context: ./my-submodule
      target: my-submodule
  my-app:
    build:
      context: .
      dockerfile: Dockerfile
      target: my-app
      # 新增:指定构建依赖
      depends_on:
        - my-submodule
    image: my-app
    # 容器启动依赖可保留(若需要)
    depends_on:
      - my-submodule

这样docker-compose build会先完成my-submodule的镜像构建,再开始构建my-app。

方案3:合并到单个Dockerfile

将子模块的构建逻辑整合到主应用的Dockerfile中,无需依赖外部镜像:

# 第一阶段:构建子模块
FROM ubuntu AS my-submodule
WORKDIR /my-submodule
# 复制子模块代码(上下文为主目录,路径为./my-submodule)
COPY ./my-submodule .
# 子模块编译逻辑...

# 第二阶段:构建主应用
FROM my-submodule AS my-app
WORKDIR /my-app
COPY . .
# 主应用构建逻辑...

此时可以移除Compose文件中的my-submodule服务,简化配置:

version: "3.9"

services:
  my-app:
    build:
      context: .
      dockerfile: Dockerfile
      target: my-app
    image: my-app

缺点:若子模块内容频繁变动,每次主应用构建都会重新触发子模块构建,可能影响构建效率。


内容的提问来源于stack exchange,提问作者Simon Tran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:55:18