# 本文件不指定平台。目标架构由构建命令决定: # docker build --platform linux/arm64 ... # 交付构建请走 API 仓库的 scripts/build-release.sh,它统一了两个镜像的平台。 # ---------- build ---------- FROM node:20-alpine AS build WORKDIR /app # 镜像里没有 .git,husky install 会失败;HUSKY=0 让它跳过。 ENV HUSKY=0 COPY package.json package-lock.json ./ RUN npm ci COPY . . # 这里刻意没有任何 ARG:所有环境相关的配置都走运行时注入(见文件末尾的 ENV)。 # 镜像因此与具体环境无关,同一份产物可以在任何环境跑,换配置只需重启容器。 # 用 build-only 而非 build:跳过 vue-tsc 类型检查, # 避免既有类型问题阻塞交付镜像的构建。类型检查请在 CI / 本地跑。 RUN npm run build-only # ---------- runtime ---------- FROM nginx:alpine COPY --from=build /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf # nginx 官方镜像自带的 docker-entrypoint 会在启动时对 # /etc/nginx/templates/*.template 做 envsubst,输出到 NGINX_ENVSUBST_OUTPUT_DIR。 # 这里把输出目录指向静态根,于是生成 /usr/share/nginx/html/config.js, # 覆盖构建产物里那份空的占位 config.js。不需要自定义 entrypoint。 COPY config.js.template /etc/nginx/templates/config.js.template ENV NGINX_ENVSUBST_OUTPUT_DIR=/usr/share/nginx/html # 运行时可配置项。必须给默认值:envsubst 只替换"已定义"的变量, # 未定义时模板里的 ${XXX} 会被原样保留,变成一个非空的垃圾字符串, # 反而绕过了代码里的兜底逻辑。 # # AZURE_SPEECH_* 供前端 TTS(speechService.ts)使用。放在这里而非构建期 ARG, # 是为了让镜像与环境解耦 —— 但要清楚:它最终会写进浏览器可读的 /config.js, # 并不比构建期烧入更安全,只是更灵活。详见 DEPLOY.md「已知问题」。 ENV SPEAKING_API_HOST="" \ AZURE_SPEECH_KEY="" \ AZURE_SPEECH_REGION="" EXPOSE 80