AWS ECS 构建 Ant Design Pro 前端 SPA 工程容器镜像

AWS Ant Design Docker About 2,814 words

Dockerfile

# ---------- build stage ----------
FROM public.ecr.aws/docker/library/node:22.20.0-alpine AS build

# umi max build 比较吃内存,CodeBuild small 规格容易 OOM
ENV NODE_OPTIONS="--max-old-space-size=4096"

WORKDIR /app

# 先只拷依赖清单,利用层缓存
COPY package.json package-lock.json .npmrc ./
RUN npm ci --no-audit --no-fund --ignore-scripts

COPY . .
RUN npm run build

# ---------- runtime stage ----------
FROM public.ecr.aws/docker/library/nginx:stable-alpine

# 去掉默认站点配置
RUN rm -f /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/app.conf

# 产物放到 /now 子目录,和 URL 路径对应
COPY --from=build /app/dist /usr/share/nginx/html/myapp

EXPOSE 80

HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD wget -q -O /dev/null http://127.0.0.1/health || exit 1

CMD ["nginx", "-g", "daemon off;"]

nginx.conf 配置

server {
    listen 80;
    server_name _;

    # 隐藏 nginx 版本号(响应头和错误页里都不再显示版本)
    server_tokens off;
    # 在 ALB 后面时,重定向用相对路径,避免跳到 http://xxx:80/
    absolute_redirect off;

    root /usr/share/nginx/html;
    index index.html;

    # ALB / ECS 健康检查
    location = /health {
        access_log off;
        default_type text/plain;
        return 200 "ok";
    }

    location = /myapp {
        return 301 /myapp/;
    }

    # index.html 不缓存
    location = /myapp/index.html {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # 运行环境标识:容器启动时生成,内容随环境变化,必须每次都取最新的(精确匹配优先于下面的 js 正则)
    location = /myapp/env-config.js {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # 带 hash 的 js/css:长缓存
    location ~* ^/myapp/.+\.(js|css)$ {
        access_log off;
        add_header Cache-Control "public, max-age=31536000, immutable";
        try_files $uri =404;
    }

    # 图片/字体(public 目录下的文件没有 hash,不设 immutable)
    location ~* ^/myapp/.+\.(png|jpg|jpeg|gif|svg|ico|woff2?|ttf)$ {
        access_log off;
        add_header Cache-Control "public, max-age=604800";
        try_files $uri =404;
    }

    # SPA history 路由回退
    location /myapp/ {
        try_files $uri $uri/ /myapp/index.html;
    }

    # 其他路径一律 404
    location / {
        return 404;
    }

    gzip on;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/javascript application/json image/svg+xml;
}

config.ts

/**
 * 部署路径:ALB 上 /myapp/* 转发到本前端容器(nginx.conf 里的 location /myapp/ 与此一致)。
 * 注意:不要用 path.join 拼 headScripts 的路径——Windows 下会拼出反斜杠(\myapp\scripts\loading.js)。
 */
const PUBLIC_PATH = '/myapp/';

export default defineConfig({
  hash: true,
  base: PUBLIC_PATH,
  publicPath: PUBLIC_PATH,
  outputPath: process.env.NODE_ENV === 'production' ? 'dist' : 'dist-dev',
  devtool: process.env.NODE_ENV === 'development' ? 'cheap-module-source-map' : false,
  favicons: ['/myapp/favicon.ico'],
  ...
})
Views: 7 · Posted: 2026-11-02

———         Thanks for Reading         ———

Give me a Star, Thanks:)

https://github.com/fendoudebb/LiteNote

扫描下方二维码关注公众号和小程序↓↓↓

扫描下方二维码关注公众号和小程序↓↓↓
Prev Post
Today In History
Browsing Refresh