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

M1 Mac使用Docker Buildx构建Google Cloud Run镜像挂起求助

问题:Docker Buildx构建linux/amd64镜像时进程卡住,本地构建正常

正在将MEAN栈前端发布到Google Container Registry(GCR),使用Docker Buildx构建linux/amd64架构镜像时,构建进程始终无法完成(已等待数小时)。本地直接执行npm run build-prod仅需几秒即可完成。

构建与部署命令

构建命令:

docker buildx build --platform linux/amd64 -t gcr.io/project_id/:latest -f Dockerfile.frontend . --push

部署命令:

gcloud run deploy (removed) 
--image gcr.io/project_id/:latest 
--platform managed 
--region europe-west1 
--allow-unauthenticated

相关配置文件

package.json

{
  "name": "frontend",
  "version": "0.0.1",
  "license": "",
  "scripts": {
    "build-dev": "ng build --configuration=development,localized",
    "build-prod": "ng build --configuration=production,localized --verbose"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "16.2.12",
    "@angular/cdk": "16.2.12",
    "@angular/common": "16.2.12",
    "@angular/compiler": "16.2.12",
    "@angular/core": "16.2.12",
    "@angular/forms": "16.2.12",
    "@angular/localize": "^16.2.3",
    "@angular/platform-browser": "16.2.12",
    "@angular/platform-browser-dynamic": "16.2.12",
    "@angular/router": "16.2.12",
    "@fullcalendar/core": "^6.1.8",
    "@fullcalendar/daygrid": "^6.1.8",
    "@fullcalendar/interaction": "^6.1.8",
    "@fullcalendar/timegrid": "^6.1.8",
    "@google-cloud/translate": "^8.0.1",
    "@googlemaps/js-api-loader": "^1.16.2",
    "@halftome/szamlazz-client": "^1.1.0",
    "@swc-node/register": "^1.6.7",
    "@swc/core": "^1.3.88",
    "axios": "^1.5.0",
    "chart.js": "^4.4.0",
    "file-saver": "^2.0.5",
    "html2canvas": "^1.4.1",
    "jspdf": "^2.5.1",
    "authpal-client": "^1.4.3",
    "jszip": "^3.10.1",
    "luxon": "^3.4.3",
    "primeflex": "^3.3.1",
    "primeicons": "^6.0.1",
    "primeng": "16.3.1",
    "prismjs": "^1.29.0",
    "rxjs": "~7.8.1",
    "tslib": "^2.3.0",
    "sass": "^1.69.4",
    "web-animations-js": "^2.3.2",
    "xlsx": "^0.18.5",
    "zone.js": "^0.13.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~16.2.0",
    "@angular-devkit/core": "~16.2.0",
    "@angular-devkit/schematics": "~16.2.0",
    "@angular/cli": "~16.2.0",
    "@angular/compiler-cli": "~16.2.0",
    "@angular/language-service": "~16.2.0",
    "@schematics/angular": "~16.2.0",
    "@types/google.maps": "^3.54.0",
    "@types/luxon": "^3.3.2",
    "typescript": "~5.1.3",
    "@types/file-saver": "^2.0.5",
    "@angular/localize": "^16.2.0"
  }
}

Dockerfile.frontend

# ---- Base Node ----
FROM node:alpine as base
# Set working directory
WORKDIR /usr/src/app
# Copy package.json and package-lock.json (or yarn.lock)
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy application source code
COPY . .
# Build the application
RUN npm run build-prod

# ---- Nginx ----
FROM nginx:alpine as runner
# Copy nginx configuration from base stage
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Copy built application files from base stage
COPY --from=base /usr/src/app/dist /usr/share/nginx/html/
# Expose port
EXPOSE 80
# Run the application
CMD ["nginx", "-g", "daemon off;"]

nginx.conf

map $http_accept_language $accept_language {
    ~*^hu hu;
    ~*^en en;

    default en;
}

server {
    listen 80;
    resolver 8.8.8.8;

    set $backend_name (removed);
    server_name $backend_name;

    root /usr/share/nginx/html;
    index index.html index.htm;
    client_max_body_size 32m;

    add_header Content-Security-Policy "default-src 'self'; connect-src 'self' https://maps.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://cdn.jsdelivr.net; font-src 'self' data:; script-src 'self' 'unsafe-inline' https://maps.googleapis.com https://editor.unlayer.com; frame-src 'self' https://editor.unlayer.com; frame-ancestors 'self'";
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
    add_header X-Content-Type-Options "nosniff" always;

    gzip on;
    gzip_static on;
    gzip_comp_level 4;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_min_length 1000;

    location = /favicon.ico {
        try_files /hu/favicon.ico /en/favicon.ico =404;
    }

    location ~* \.css$ {
        add_header Content-Type text/css;
    }

    location ~* \.png$ {
        add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
        expires off;
    }

    location ~ ^/(hu|en)/ {
        try_files $uri $uri/ /$1/index.html?$args;
    }

    location ~ /(hu|en)?/vendor.js {
        expires 7d;
        add_header Cache-Control "public, max-age=604800";
        add_header Last-Modified $date_gmt;
        add_header ETag $request_uri;
    }


    location /api {
        proxy_ssl_server_name on;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header Host $backend_name(removed);

        proxy_pass https://$backend_name(removed):443;

        proxy_read_timeout 300s;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

  
    location / {
        if ($request_uri = '/') {
            rewrite ^/$ /$accept_language/ permanent;
        }
        try_files $uri $uri/ /$accept_language/index.html?$args;
    }

    error_page 500 502 503 504 /50x.html;
    error_page 404 =200 /en/index.html;

    location = /50x.html {
        internal;
    }
}

angular.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",

  "projects": {
    "projectname": {
      "projectType": "application",
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",

      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        }
      },
      "i18n": {
        "sourceLocale": "en",
        "locales": {
          "hu": {
            "translation": "src/locale/source.hu.json",
            "baseHref": "hu/"
          }
        }
      },

      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "i18nMissingTranslation": "warning",
            "outputPath": "dist/projectname",
            "index": "src/index.html",
            "main": "src/main.ts",

            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "inlineStyleLanguage": "scss",
            "assets": ["src/favicon.ico", "src/assets"],
            "styles": ["src/scss/_styles.scss"]
          },
          "configurations": {
            "production": {
              "aot": true,
              "buildOptimizer": true,
              "optimization": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "5mb",
                  "maximumError": "6mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "4kb",
                  "maximumError": "8kb"
                }
              ],
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ]
            },
            "development": {
              "buildOptimizer": false,
              "optimization": false,
              "vendorChunk": true,
              "extractLicenses": false,
              "sourceMap": true,
              "namedChunks": true,
              "index": "src/index.html"
            },

            "localized": {
              "localize": ["hu", "en"]
            }
          },
          "defaultConfiguration": "production"
        },

        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",

          "configurations": {
            "production": {
              "browserTarget": "projectname:build:production"
            },
            "development": {
              "browserTarget": "projectname:build:development"
            }
          },
          "defaultConfiguration": "development"
        },

        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "projectname:build"
          }
        },

        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "inlineStyleLanguage": "scss",
            "assets": ["src/favicon.ico", "src/assets"],
            "styles": ["src/scss/_styles.scss"]
          }
        }
      }
    }
  },

  "cli": {
    "analytics": false
  }
}

tsconfig.json

{
  "compileOnSave": false,

  "compilerOptions": {
    "target": "es2022",
    "module": "esnext",
    "moduleResolution": "node",

    "lib": ["es2020", "dom"],

    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,

    "forceConsistentCasingInFileNames": true,

    "strict": true,
    "strictNullChecks": false,

    "noImplicitAny": false,
    "noImplicitOverride": true,
    "noImplicitReturns": false,

    "noPropertyAccessFromIndexSignature": false,
    "noFallthroughCasesInSwitch": true,

    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,

    "importHelpers": true
  },

  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true,
    "strictPropertyInitialization": false
  }
}

解决方案

1. 增加Buildx构建容器资源

Docker Buildx默认构建容器资源可能不足,导致Angular构建卡住,可手动指定CPU和内存配额:

docker buildx build --platform linux/amd64 --cpus 4 --memory 8g -t gcr.io/project_id/:latest -f Dockerfile.frontend . --push

2. 替换Node基础镜像

Alpine镜像使用musl libc,部分Node依赖存在兼容性问题,换用Debian系镜像:

FROM node:18-bullseye-slim as base
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build-prod

3. 查看详细构建日志

添加--progress=plain参数输出完整构建过程,定位卡住的具体步骤:

docker buildx build --platform linux/amd64 --progress=plain -t gcr.io/project_id/:latest -f Dockerfile.frontend . --push

4. 优化Dockerfile分层缓存

调整文件复制顺序,缓存依赖安装层,减少重复构建时间:

FROM node:18-bullseye-slim as base
WORKDIR /usr/src/app
# 先复制package文件,缓存依赖层
COPY package*.json ./
RUN npm ci --only=production && npm ci
# 再复制源代码
COPY . .
RUN npm run build-prod

FROM nginx:alpine as runner
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=base /usr/src/app/dist /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

5. 禁用Angular并行构建

在angular.json的production配置中添加"parallel": false,避免多线程构建在容器中死锁:

"production": {
  // 原有配置...
  "parallel": false
}

6. 改用Google Cloud Build构建

跳过本地Buildx,直接使用GCP的构建服务:

gcloud builds submit --tag gcr.io/project_id/latest --file Dockerfile.frontend .

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:37:06