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

使用GitHub Actions部署GKE时Express容器持续崩溃求助

问题:CI构建的Express容器在GKE中持续崩溃,手动部署正常

我通过GitHub Actions将包含Vue、Express和MongoDB的三容器Pod部署到GKE,手动执行以下命令部署完全正常:

kubectl apply -f deployment-sit.yaml
kubectl apply -f vue-service-sit.yaml
kubectl apply -f express-service-sit.yaml
kubectl apply -f mongodb-service-sit.yaml
kubectl apply -f sit-ingress.yaml

但CI流水线使用相同的docker-compose文件和Dockerfile构建镜像后,Express容器持续崩溃,仅能看到以下错误信息:

stream closed EOF for default/seg-dashboard-sit-6c9d6d5798-lscd5 (seg-dashboard-sit-express)

以及:

Warning  BackOff 3m30s (x24 over 8m26s)  kubelet Back-off restarting failed container seg-dashboard-sit-express in pod seg-dashboard-sit-6c9d6d5798-lscd5_default(7042eb1d-c7bc-455f-bfc5-4159733aa00e)

已确认问题出在构建阶段(CI构建的镜像本地运行也异常),尝试过配置GCP IAM权限、检查环境变量、校验健康检查路径、调整livenessProbe,均未解决。


相关配置文件

Express docker-compose.yaml

version: '3.8'
services:
  api:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: seg-dashboard-vue
    env_file:
      - ./.env.production
    environment:
      - NODE_ENV=production
      - HOSTNAME=0.0.0.0
      - BASE_URL=/seg-dashboard/api
      - OPSGENIE_APIKEY=4075da9d-07b2-4db3-9388-2a1b7c851c78
      - OPSGENIE_APIURL=https://api.opsgenie.com/v2
    image: asia-east1-docker.pkg.dev/visitor-access-system/tools/seg-dashboard-express:latest
    platform: linux/amd64

Express Dockerfile

FROM node:lts-jod AS build
LABEL maintainer="jackylai327@gmail.com" version="1.0"
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 11200
ENV NODE_ENV=production
ENV HOSTNAME=0.0.0.0
ENV BASE_URL=/seg-dashboard/api
ENV OPSGENIE_APIKEY=4075da9d-07b2-4db3-9388-2a1b7c851c78
ENV OPSGENIE_APIURL=https://api.opsgenie.com/v2
CMD ["npm", "start"]

CI流水线配置

name: SEG Dashboard CI/CD Pipeline

on:
  push:
    branches:
      # - main
      - develop

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Set up Node.js
      uses: actions/setup-node@v4
      with:
        node-version: '21'

    - name: Install Docker Compose
      run: |
        sudo apt-get update
        sudo apt-get install -y docker-compose

    - name: Build Docker images
      run: |
        docker-compose -f vue-app/docker-compose.yaml build --no-cache
        docker-compose -f express-app/docker-compose.yaml build --no-cache

    - name: Log in to Google Container Registry
      uses: google-github-actions/auth@v2
      with:
        credentials_json: ${{ secrets.GCP_SA_KEY }}

    - name: Configure Docker to use the gcloud command-line tool as a credential helper
      run: gcloud auth configure-docker asia-east1-docker.pkg.dev

    - name: Push Docker images to Google Container Registry
      run: |
        docker push asia-east1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/tools/seg-dashboard-vue:latest
        docker push asia-east1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/tools/seg-dashboard-express:latest

  deploy:
    needs: build
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Log in to Google Container Registry
      uses: google-github-actions/auth@v2
      with:
        credentials_json: ${{ secrets.GCP_SA_KEY }}

    - name: Set up gcloud Cloud SDK environment
      uses: google-github-actions/setup-gcloud@v2.1.2
      with:
        project_id: ${{ secrets.GCP_PROJECT_ID }}
        install_components: 'kubectl,gke-gcloud-auth-plugin'

    - name: Configure gcloud and kubectl
      run: |
        gcloud container clusters get-credentials ${{ secrets.GKE_CLUSTER_NAME }} --zone ${{ secrets.GKE_CLUSTER_LOCATION }} --project ${{ secrets.GCP_PROJECT_ID }}
        gcloud config set project ${{ secrets.GCP_PROJECT_ID }}
        kubectl config current-context

    - name: Deploy to Kubernetes
      run: |
        kubectl apply -f deployment-sit.yaml
        kubectl apply -f vue-service-sit.yaml
        kubectl apply -f express-service-sit.yaml
        kubectl apply -f mongodb-service-sit.yaml
        kubectl apply -f sit-ingress.yaml
        kubectl rollout restart deployment seg-dashboard-sit

排查步骤
  • 本地复现CI构建流程:在本地机器上完全模拟CI的构建步骤(使用Node 21,执行docker-compose build --no-cache),然后运行构建出的镜像,手动启动服务查看详细错误:
    docker run -it asia-east1-docker.pkg.dev/visitor-access-system/tools/seg-dashboard-express:latest bash
    # 进入容器后执行
    npm start
    
  • 核对Node版本差异:CI构建步骤用的是Node 21,但Dockerfile基础镜像是node:lts-jod(对应Node 20.x),版本不一致可能导致依赖安装异常。可以让CI的Node版本和Dockerfile保持一致,或在Dockerfile中明确指定与CI匹配的Node版本。
  • 验证.env.production文件存在性:检查CI环境中是否存在.env.production文件,如果该文件未提交到仓库,容器会缺少必要环境变量。可以在CI构建步骤中添加文件检查命令,或在Dockerfile中增加验证:
    # 在Dockerfile的COPY步骤后添加
    RUN ls -la .env.production || echo ".env.production file missing"
    
  • 检查构建上下文路径:确认CI中构建Express镜像时,docker-compose -f express-app/docker-compose.yaml build的上下文是否正确,package.json、源码文件是否在指定路径下,避免COPY命令遗漏关键文件。
  • 获取GKE容器完整日志:查看崩溃容器的上一次启动日志,通常能找到具体失败原因:
    kubectl logs <pod-name> -c seg-dashboard-sit-express --previous
    
  • 优化Dockerfile多阶段构建:当前Dockerfile未区分开发依赖和生产依赖,建议使用多阶段构建减少镜像体积并避免依赖冲突:
    FROM node:lts-jod AS builder
    WORKDIR /app
    COPY package*.json ./
    RUN npm install
    COPY . .
    # 如果有构建步骤(比如编译TypeScript),添加对应命令
    # RUN npm run build
    
    FROM node:lts-jod AS production
    WORKDIR /app
    COPY --from=builder /app/package*.json ./
    RUN npm ci --only=production
    COPY --from=builder /app ./ # 或仅复制生产需要的文件(如dist目录)
    EXPOSE 11200
    ENV NODE_ENV=production
    ENV HOSTNAME=0.0.0.0
    ENV BASE_URL=/seg-dashboard/api
    ENV OPSGENIE_APIKEY=4075da9d-07b2-4db3-9388-2a1b7c851c78
    ENV OPSGENIE_APIURL=https://api.opsgenie.com/v2
    CMD ["npm", "start"]
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 01:40:03