惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Palo Alto Networks Blog
Martin Fowler
Martin Fowler
T
Threatpost
D
Docker
S
Schneier on Security
M
MIT News - Artificial intelligence
G
Google Developers Blog
L
LINUX DO - 热门话题
J
Java Code Geeks
月光博客
月光博客
博客园 - 三生石上(FineUI控件)
IT之家
IT之家
博客园 - Franky
C
Cyber Attacks, Cyber Crime and Cyber Security
K
Kaspersky official blog
Google DeepMind News
Google DeepMind News
N
News and Events Feed by Topic
V
Vulnerabilities – Threatpost
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
人人都是产品经理
人人都是产品经理
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
爱范儿
爱范儿
阮一峰的网络日志
阮一峰的网络日志
U
Unit 42
C
CERT Recently Published Vulnerability Notes
The GitHub Blog
The GitHub Blog
Simon Willison's Weblog
Simon Willison's Weblog
NISL@THU
NISL@THU
MongoDB | Blog
MongoDB | Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
H
Heimdal Security Blog
Recorded Future
Recorded Future
云风的 BLOG
云风的 BLOG
SecWiki News
SecWiki News
P
Privacy International News Feed
P
Proofpoint News Feed
O
OpenAI News
B
Blog
腾讯CDC
F
Full Disclosure
Apple Machine Learning Research
Apple Machine Learning Research
T
Tor Project blog
H
Hacker News: Front Page
Project Zero
Project Zero
Hugging Face - Blog
Hugging Face - Blog
C
Cisco Blogs
S
Security Affairs

博客园 - ddrsql

从“黑盒”到“全景”:在.NET中拥抱OpenTelemetry与SigNoz的可观测工具 关于git分支堆叠 记录团队使用git合并代码丢失 记一次对老服务改造 国产麒麟(Kylin-Server-10)系统无外网环境安装docker vue3学习之axios、mockjs、nswag vue3学习之tabler组件Layout布局 vue3学习之BootstrapVueNext Framework升级到Core以及Dapper支持达梦数据库 Avalonia集成Prism与Abp Avalonia中使用EF增删改查DM数据库 Linux中使用原生Wpf之Avalonia WPF通过wine适配统信uos系统 单体仓库下通过helm优雅的将微服务部署到k8s VS使用IIS调试(非附加进程).net core、.net framework程序 k8s集群通过nginx-ingress做tcp、udp 4层网络转发 DevOps .net core Jenkins持续集成Linux、Docker、K8S swaggerui集成oauth implicit redis cluster集群web管理工具 relumin
DevOps 前端项目(angular、vue、react)打包静态资源生成一份Docker镜像支持部署不同环境
ddrsql · 2020-10-22 · via 博客园 - ddrsql

1、前言


为了尽可能地轻量化前端镜像(非node承载),将前端编译成静态资源通过nginx承载。
与后端程序不同的是,当使用静态资源方式时页面是直接加载到浏览器进行渲染,无法读取服务端机器中 env 的环境变量。
当有部署多个环境(dev、uat、pro)需求时,就无法像后端程序一样满足生成一个镜像部署不同环境。
如果你有同样的需求请往下看。

2、使用ngx_http_js_module


参考 ngx_http_js_module

njs是JavaScript语言的子集,它允许扩展nginx功能。njs的创建符合 ECMAScript 5.1 (严格模式)以及某些 ECMAScript 6 和更高版本的扩展。合规性还在不断发展

default.conf

主要关注 location /env { js_content getenv; } 部分内容,getenv 是一个 JavaScript function 函数。

server {
  listen       80;
  # listen 443;
  # ssl on;
  # ssl_certificate /etc/nginx/ssl/server.crt;
  # ssl_certificate_key /etc/nginx/ssl/server.key;

  server_name  localhost;

  #charset koi8-r;
  #access_log  /var/log/nginx/host.access.log  main;

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
    proxy_set_header    Host        $host;
    proxy_set_header    X-Real-IP   $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
  }

  location /env {
        js_content getenv;
  }

  #error_page  404              /404.html;

  # redirect server error pages to the static page /50x.html
  #
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   /usr/share/nginx/html;
  }
}

nginx.conf

主要关注 js_include env.js; 部分内容,引入js。

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

load_module modules/ngx_http_js_module.so;

events {
    worker_connections  1024;
}


http {
    js_include env.js;
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;
    include /etc/nginx/conf.d/*.conf;
}

env.js

对应 default.conf 中使用的方法。

function getenv(r) {
    var strEnv = '{"Shortsha": "'+ process.env.SHORTSHA +'","UI_ENVIRONMENT": "'+ process.env.UI_ENVIRONMENT +'"}';
    r.headersOut['Content-Type'] = "application/json; charset=utf-8";
    r.return(200, strEnv);
}
  • 效果示意

3、前端部分(以angular为例)


文件夹 /assets 中预先配置多个环境的配置文件 appconfig.dev.json 、appconfig.uat.json 、appconfig.pro.json

是不是和 .net core 中后端程序配置很像,启动配置的环境变量 "ASPNETCORE_ENVIRONMENT": "Development" 配置文件 appsettings.json、appsettings.Development.json ...

同样的道理只要在渲染生命周期比较开始的位置获上文在 nginx 中配置的 env 地址中拿到环境配置在赋值到 AppConsts.remoteServiceBaseUrl 全局变量中。

  private static getApplicationConfig(injector: Injector,httpClient: HttpClient,callback: () => void
  ) {
    //能满足ng build --|dev|uat|pro 编译时指定不同环境变量
    let envName = '';
    if (environment.production) {
      envName = 'pro';
    } else {
      envName = 'dev';
    }
    //nginx容器中环境变量
    const envUrl = window.location.protocol + '//' + window.location.host + "/env";
    httpClient.get(envUrl).subscribe(
      (result: any) => {
        envName = result.UI_ENVIRONMENT;

        callback();
      },
      error => {
        alert(`获取环境变量出错,信息:\n\n${error.message}`);
      }
    );

    //assets 文件夹存放不同环境配置文件
    const url = '/assets/appconfig.' + envName + '.json';
    httpClient.get(url).subscribe(
      (result: any) => {
        //后端服务地址
        AppConsts.remoteServiceBaseUrl = result.remoteServiceBaseUrl;

        callback();
      },
      error => {
        alert(`初始化配置出错,信息:\n\n${error.message}`);
      }
    );
  }

4、镜像、部署


Dockerfile

在 ci\cd 流水线 build 拿到产出的 /dist 静态资源打包Docker镜像。

FROM nginx:1.17.3-alpine as base
EXPOSE 80
WORKDIR /usr/share/nginx/html

COPY /_nginx/nginx.conf /etc/nginx/nginx.conf
COPY /_nginx/env.js /etc/nginx/env.js
COPY /_nginx/default.conf /etc/nginx/conf.d/default.conf

COPY /dist /usr/share/nginx/html

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

部署的yaml中配置

value 中的值均通过流水线变量获取,文中使用具体值示意。

env: 
- name: UI_ENVIRONMENT
    value: "uat"   #流水线中不同分支对应不同环境
- name: SHORTSHA
    value: "v1.0"  #源码仓库的签名

5、总结


水平有限,难免有所纰漏,欢迎批评指正。本文纯属抛转引玉,大家有更好思路欢迎留言评论。