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

在Kubernetes与Docker部署Angular应用时,如何安全管理环境变量?

问题解决方案

一、解决编译时配置局限:Docker与Kubernetes动态注入环境变量

Docker环境实现

  1. 改造前端构建逻辑,用运行时环境变量替代编译时硬编码
    修改environment.prod.ts,改为读取全局环境变量:

    export const environment = {
      production: true,
      firebase: {
        apiKey: window.env?.firebaseApiKey || "",
        authDomain: window.env?.firebaseAuthDomain || "",
        databaseURL: window.env?.firebaseDatabaseURL || "",
        projectId: window.env?.firebaseProjectId || "",
        storageBucket: window.env?.firebaseStorageBucket || "",
        messagingSenderId: window.env?.firebaseMessagingSenderId || "",
        appId: window.env?.firebaseAppId || "",
        measurementId: window.env?.firebaseMeasurementId || ""
      },
      apiServerUrl: window.env?.apiServerUrl || ""
    };
    

    在项目assets目录下创建env.template.js作为环境变量模板:

    window.env = {
      apiServerUrl: "${API_SERVER_URL}",
      firebaseApiKey: "${FIREBASE_API_KEY}",
      firebaseAuthDomain: "${FIREBASE_AUTH_DOMAIN}",
      firebaseDatabaseURL: "${FIREBASE_DATABASE_URL}",
      firebaseProjectId: "${FIREBASE_PROJECT_ID}",
      firebaseStorageBucket: "${FIREBASE_STORAGE_BUCKET}",
      firebaseMessagingSenderId: "${FIREBASE_MESSAGING_SENDER_ID}",
      firebaseAppId: "${FIREBASE_APP_ID}",
      firebaseMeasurementId: "${FIREBASE_MEASUREMENT_ID}"
    };
    

    确保angular.json中包含该模板文件,构建时会打包到dist目录。

  2. 编写Dockerfile与启动脚本
    使用多阶段构建减小镜像体积:

    # 构建阶段
    FROM node:18-alpine as builder
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN ng build --configuration production
    
    # 运行阶段
    FROM nginx:alpine
    COPY --from=builder /app/dist /usr/share/nginx/html
    COPY entrypoint.sh /entrypoint.sh
    RUN chmod +x /entrypoint.sh
    ENTRYPOINT ["/entrypoint.sh"]
    CMD ["nginx", "-g", "daemon off;"]
    

    编写entrypoint.sh脚本,容器启动时替换模板中的环境变量:

    #!/bin/sh
    # 替换环境变量模板中的占位符
    envsubst '${API_SERVER_URL} ${FIREBASE_API_KEY} ${FIREBASE_AUTH_DOMAIN} ${FIREBASE_DATABASE_URL} ${FIREBASE_PROJECT_ID} ${FIREBASE_STORAGE_BUCKET} ${FIREBASE_MESSAGING_SENDER_ID} ${FIREBASE_APP_ID} ${FIREBASE_MEASUREMENT_ID}' \
      < /usr/share/nginx/html/assets/env.template.js \
      > /usr/share/nginx/html/assets/env.js
    # 执行原启动命令
    exec "$@"
    

    启动容器时直接传入环境变量:

    docker run -d \
      -e API_SERVER_URL="https://prod-api.example.com" \
      -e FIREBASE_API_KEY="your-firebase-key" \
      -p 80:80 \
      your-frontend-image:latest
    

Kubernetes环境实现

用ConfigMap存储非敏感配置,Secret存储敏感信息,在Deployment中注入容器:

  1. 创建ConfigMap存储非敏感配置

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: frontend-config
    data:
      API_SERVER_URL: "https://prod-api.example.com"
      FIREBASE_AUTH_DOMAIN: "your-project.firebaseapp.com"
      FIREBASE_DATABASE_URL: "https://your-project.firebaseio.com"
      FIREBASE_PROJECT_ID: "your-project-id"
      FIREBASE_STORAGE_BUCKET: "your-project.appspot.com"
      FIREBASE_MESSAGING_SENDER_ID: "123456789"
      FIREBASE_APP_ID: "1:123456789:web:abc123"
      FIREBASE_MEASUREMENT_ID: "G-ABC123"
    
  2. 创建Secret存储敏感的Firebase API Key
    先将密钥转为Base64编码:echo -n "your-firebase-api-key" | base64,再编写Secret配置:

    apiVersion: v1
    kind: Secret
    metadata:
      name: frontend-secrets
    type: Opaque
    data:
      FIREBASE_API_KEY: <base64编码后的密钥>
    
  3. 在Deployment中注入环境变量

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: frontend
      template:
        metadata:
          labels:
            app: frontend
        spec:
          containers:
          - name: frontend
            image: your-frontend-image:latest
            env:
              # 从ConfigMap读取非敏感配置
              - name: API_SERVER_URL
                valueFrom:
                  configMapKeyRef:
                    name: frontend-config
                    key: API_SERVER_URL
              - name: FIREBASE_AUTH_DOMAIN
                valueFrom:
                  configMapKeyRef:
                    name: frontend-config
                    key: FIREBASE_AUTH_DOMAIN
              # 其他ConfigMap配置项同理
              # 从Secret读取敏感配置
              - name: FIREBASE_API_KEY
                valueFrom:
                  secretKeyRef:
                    name: frontend-secrets
                    key: FIREBASE_API_KEY
            ports:
            - containerPort: 80
    

    Kubernetes会自动将配置注入容器,启动时通过entrypoint.sh替换到前端文件中,无需重新构建镜像。

二、前端敏感信息安全管理

核心认知

前端代码运行在用户浏览器中,任何直接暴露在前端的信息都可被用户通过开发者工具获取,因此绝不能将真正的敏感密钥(如服务端私钥、数据库密码)放到前端。

针对Firebase的优化

Firebase的apiKey是设计为可公开的:它仅用于标识你的Firebase项目,不具备直接访问敏感资源的权限。真正的访问控制依赖于Firebase的安全规则(数据库、存储规则)和用户身份验证。只要配置好规则,限制只有认证用户才能访问资源,apiKey暴露不会带来风险。

通用敏感信息保护方案

  • 后端代理转发:所有需要敏感密钥的请求,都通过自有后端服务代理。比如前端调用你的后端API,后端再使用密钥调用Firebase Admin SDK或其他第三方服务,敏感密钥仅存在于后端服务器。
  • 避免前端存储敏感数据:不要将用户令牌、密钥等存储在localStorage/sessionStorage中,优先使用HttpOnly Cookie存储认证信息,防止XSS攻击窃取。
  • 构建时清理敏感信息:确保构建过程中不会将敏感信息硬编码到产物中,所有动态配置都通过运行时环境变量注入,敏感内容仅通过Secret管理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 08:03:14