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

Docker Compose创建React容器但无法启动的问题及解决

更新 - 已解决(2024年7月21日)

我已完成调试,成功配置前端Dockerfile和compose.yaml,只需执行docker compose up --build即可运行Spring-React应用,调试期间搭配使用docker compose down --rmi all命令,未修改后端Spring的Dockerfile。

更新后的compose.yaml

services:
  backend:
    build: backend-spring
    restart: always
    ports:
      - 8080:8080

  frontend:
    build:
      context: frontend-react
    stdin_open: true
    tty: true
    ports:
      - 3000:3000
    depends_on:
      - backend

更新后的前端Dockerfile

ARG NODE_VERSION=20.13.1

################################################################################
# 所有阶段均使用Node镜像作为基础镜像
FROM node:${NODE_VERSION}-alpine as base

# 为所有构建阶段设置工作目录
WORKDIR /app


################################################################################
# 创建安装生产依赖的阶段
FROM base as deps

# 将下载依赖作为单独步骤,利用Docker缓存机制加速构建
# 使用缓存挂载到/root/.npm,加快后续构建速度
# 使用绑定挂载package.json和package-lock.json,避免将它们复制到当前层
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev

################################################################################
# 创建构建应用的阶段
FROM deps as build

# 构建前下载额外的开发依赖,部分项目需要安装"devDependencies"才能完成构建。如果不需要可移除此步骤
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci
# 复制package.json,以便执行包管理器命令
COPY package*.json .

RUN npm install

# 复制剩余的源码文件到镜像中
COPY . .

# 执行构建脚本
RUN npm run build --omit=dev

################################################################################
# 创建运行应用的阶段,仅包含最小运行时依赖,从构建阶段复制必要文件
FROM base as final

# 默认使用生产环境Node环境
ENV NODE_ENV production

# 复制package.json,以便执行包管理器命令
COPY package.json .

# 从deps阶段复制生产依赖,从build阶段复制构建完成的应用到镜像中
COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/build ./build
COPY --from=build /app/public ./public
COPY --from=build /app/src ./src

# 安装`serve`用于运行应用
RUN npm install -g serve

# 使用非root用户运行应用
USER node

# 暴露应用监听的端口
EXPOSE 3000
# 运行应用 # 在npm start(调试)和serve(生产)之间切换
#CMD [ "npm", "start" ]
CMD ["serve", "-s", "build"]

原始问题

我是Docker新手,尝试用单个compose.yaml部署Spring-React应用,通过docker init和相关资料分别为后端(Spring)和前端(React)创建了Dockerfile。

.
├── backend-spring
│   ├── ...
│   ├── Dockerfile
├── frontend-react
│   ├── ...
│   └── Dockerfile
├── ...
└── compose.yaml

我想先让应用在本地运行,再部署到AWS。

在根目录执行docker compose up -d后,提示后端和前端容器均已创建,但执行docker container ls时仅显示Spring后端容器,导致无法通过localhost访问React应用。

为何frontend-react容器未出现在docker container ls结果中?

我怀疑是前端Dockerfile的问题,已尝试调整RUN/CMD命令但无效。

手动在目录执行serve -s build或npm start时React应用可正常运行,希望仅通过docker compose up -d命令就能同时启动前后端,且已确认Spring后端API可通过localhost访问。

感谢您的帮助。


原始compose.yaml

services:
  backend:
    build: backend-spring
    restart: always
    ports:
      - 8080:8080

  frontend:
    build:
      context: frontend-react
#      target: development # 指定多阶段Dockerfile中要构建的阶段。由于backend-spring的Dockerfile是单阶段,因此注释掉
    stdin_open: true
    tty: true
    ports:
      - 3000:3000
    volumes:
      - /frontend-react/src
      - /frontend-react/node_modules
    depends_on:
      - backend

原始前端Dockerfile

# syntax=docker/dockerfile:1

# Dockerfile参考指南

ARG NODE_VERSION=20.13.1

################################################################################
# 所有阶段均使用Node镜像作为基础镜像
FROM node:${NODE_VERSION}-alpine as base

# 为所有构建阶段设置工作目录
WORKDIR /usr/src/app


################################################################################
# 创建安装生产依赖的阶段
FROM base as deps

# 将下载依赖作为单独步骤,利用Docker缓存机制加速构建
# 使用缓存挂载到/root/.npm,加快后续构建速度
# 使用绑定挂载package.json和package-lock.json,避免将它们复制到当前层
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev

################################################################################
# 创建构建应用的阶段
FROM deps as build

# 构建前下载额外的开发依赖,部分项目需要安装"devDependencies"才能完成构建。如果不需要可移除此步骤
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci

# 复制剩余的源码文件到镜像中
COPY . .
# 安装`serve`用于运行应用
RUN npm install -g serve
# 执行构建脚本
RUN npm run build --omit=dev

################################################################################
# 创建运行应用的阶段,仅包含最小运行时依赖,从构建阶段复制必要文件
FROM base as final

# 默认使用生产环境Node环境
ENV NODE_ENV production

# 使用非root用户运行应用
USER node

# 复制package.json,以便执行包管理器命令
COPY package.json .

# 从deps阶段复制生产依赖,从build阶段复制构建完成的应用到镜像中
COPY --from=deps /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/build ./build


# 暴露应用监听的端口
EXPOSE 3000
# 运行应用 # 在npm start(调试)和serve(生产)之间切换
CMD [ "npm", "start" ]
#CMD serve -s build # 无效
#RUN serve -s build # 无效

后端Dockerfile

# syntax=docker/dockerfile:1

# Dockerfile参考指南

################################################################################

# 创建解析和下载依赖的阶段
FROM eclipse-temurin:17-jdk-jammy as deps

WORKDIR /build

# 复制具有执行权限的mvnw包装器
COPY --chmod=0755 mvnw mvnw
COPY .mvn/ .mvn/

# 将下载依赖作为单独步骤,利用Docker缓存机制加速构建
# 使用缓存挂载到/root/.m2,避免后续构建重复下载依赖包
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
    --mount=type=cache,target=/root/.m2 ./mvnw dependency:go-offline -DskipTests

################################################################################

# 基于已下载依赖的阶段创建构建应用的阶段
# 此Dockerfile针对输出uber jar的Java应用优化,uber jar包含JVM运行所需的所有依赖。如果你的应用不输出uber jar,而是依赖Tomcat等应用服务器,则需要更新此阶段的包文件名,并将"final"阶段的基础镜像替换为对应的应用服务器镜像
FROM deps as package

WORKDIR /build

COPY ./src src/
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
    --mount=type=cache,target=/root/.m2 \
    ./mvnw package -DskipTests && \
    mv target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar target/app.jar

################################################################################

# 创建将应用提取到单独层的阶段
# 利用Spring Boot的层工具和Docker缓存,将打包后的应用提取到单独层,以便复制到最终阶段
FROM package as extract

WORKDIR /build

RUN java -Djarmode=layertools -jar target/app.jar extract --destination target/extracted

################################################################################

# 创建运行应用的阶段,仅包含最小运行时依赖,通常使用与安装或构建阶段不同的基础镜像,并从安装阶段复制必要文件
#
# 以下示例使用eclipse-temurin的JRE镜像作为运行应用的基础。
# 指定"17-jre-jammy"标签时,构建Dockerfile会使用该标签的最新版本。
# 如果需要可重复性,建议使用特定的摘要SHA
FROM eclipse-temurin:17-jre-jammy AS final

# 创建非特权用户用于运行应用
ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    appuser
USER appuser

# 从"package"阶段复制可执行文件
COPY --from=extract build/target/extracted/dependencies/ ./
COPY --from=extract build/target/extracted/spring-boot-loader/ ./
COPY --from=extract build/target/extracted/snapshot-dependencies/ ./
COPY --from=extract build/target/extracted/application/ ./

EXPOSE 8080

ENTRYPOINT [ "java", "org.springframework.boot.loader.launch.JarLauncher" ]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 14:20:53