Angular 結合 nginx 反向代理的 Docker 容器化封裝技巧

栏目: 编程语言 · AngularJS · 发布时间: 6年前

内容简介:在微服務架構下,部署 Angular 應用程式與後端 Web API 應該切割成兩個不同的微服務。但具體的實現方式,通常會透過容器化技術來達成,實作上相對容易許多。像我們公司的特定專案,就是透過 Kubernetes 叢集化技術來實現這個目的。這篇文章,我將分享如何將 Angular 這類 SPA 框架,如何透過 nginx 反向代理與 Docker 容器化技術,徹底做到微服務化。將前後端分離的結果,可以幫助我們簡化 CI/CD 流程,同時降低系統之間的耦合性。在整個實作的過程中,我會以 Angular

在微服務架構下,部署 Angular 應用程式與後端 Web API 應該切割成兩個不同的微服務。但具體的實現方式,通常會透過容器化技術來達成,實作上相對容易許多。像我們公司的特定專案,就是透過 Kubernetes 叢集化技術來實現這個目的。這篇文章,我將分享如何將 Angular 這類 SPA 框架,如何透過 nginx 反向代理與 Docker 容器化技術,徹底做到微服務化。將前後端分離的結果,可以幫助我們簡化 CI/CD 流程,同時降低系統之間的耦合性。

在整個實作的過程中,我會以 Angular 6 當作範例,並透過 Angular CLI 建立專案,最後透過 Docker 進行容器化封裝。

安裝 Angular CLI 工具

npm i -g @angular/cli

建立 Angular 專案範本

ng new demo1

設定 ng serve 專用的 proxy 代理伺服器

這裡我打算用網路上的一個 Dog API 當作我們的後端 Web API 服務。我將會使用 https://dog.ceo/api/breeds/image/random 當作我們主要實作用的 API,所以我在開發環境下,就可以透過建立 proxy.config.json 設定檔,來做到開發環境的 API 反向代理功能。

{
  "/api": {
    "target": "https://dog.ceo",
    "changeOrigin": true,
    "secure": false
  }
}

接著我們修改 package.json 檔案,將 "start" 腳本設定修改為 "ng serve --proxy-config proxy.config.json" ,並執行 npm start 啟動 Angular 開發伺服器 (Angular Live Development Server)。

npm start

啟動之後,你可以嘗試連到 http://localhost:4200/api/breeds/image/random 看是否能得到遠端 API 執行的結果:

{"status":"success","message":"https:\/\/images.dog.ceo\/breeds\/papillon\/n02086910_7405.jpg"}

修改 Angular 應用程式,呼叫 API 顯示照片

編輯 src\app\app.module.ts 並匯入 HttpClientModule 模組:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from "@angular/common/http";

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

編輯 src\app\app.component.ts 並實作 API 呼叫程式:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'demo1';
  imgUrl = '/assets/Spinner-1s-200px.svg';

  constructor(private httpClient: HttpClient) {}

  ngOnInit(): void {
    this.load_image();
  }

  load_image() {
    this.httpClient.get('/api/breeds/image/random').subscribe((v: any) => {
      this.imgUrl = v.message;
    });
  }
}

編輯 src\app\app.component.html 並顯示圖片在畫面上:

<div style="text-align:center">
  <h1>
    Welcome to {{ title }}!
  </h1>
  <img width="300" [src]="imgUrl" (click)="load_image()">
</div>

建立 nginx 站台設定檔

我的 nginx.site.template 檔案內容如下,其中的 ${BACKEND_URI} 將會透過「環境變數」自動替換成後端 Web API 的 URI 位址。

另外,由於 dog.ceo 這個域名的 DNS 實在太慢了,這會導致 nginx 會一直出現 502 Bad Gateway 的錯誤。所以我才特別加上一條 resolver 8.8.8.8 valid=30s ipv6=off; 設定。這條設定在使用 docker-compose 或 Kubernetes 部署的時候可以放心移除。

最後,有個 proxy_ssl_server_name 設定也很重要。當你的後端 Web API 使用 SNI SSL 的時候,如果不設定為 on 就一定會掛掉。(很雷)

server {
    listen 80;
    root  /usr/share/nginx/html;

    # The dog.ceo domain is very slow that will lead nginx resolver not working.
    resolver 8.8.8.8 valid=30s ipv6=off;

    location ~/api(.*)$ {

        proxy_pass ${BACKEND_URI}/api$1;

        # if BACKEND_URI is using TLS/SSL with SNI, this is important!
        proxy_ssl_server_name on;

        proxy_redirect off;
        proxy_set_header Host $proxy_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;
    }
}

建立 Dockerfile 與 .dockerignore 檔案

請將以下兩個檔案建立在 Angular 專案根目錄下。

.dockerignore

注意: node_modules 一定要排除。

node_modules
npm-debug.log
Dockerfile*
docker-compose*
.dockerignore
.git
.gitignore
README.md
LICENSE
.vscode

Dockerfile

我使用了 multi stage 的建置技巧,先透過 node:10 建置 Angular 應用程式,然後再將建置過的 Angular 應用程式複製到透過 nginx:1.15.2-alpine 建立的容器中,最後再透過 nginx.site.template 置換成 /etc/nginx/conf.d/default.conf 站台設定檔。

這邊最重要技巧是 envsubst 的使用方式,透過這個工具,可以輕易的將設定檔範本中特定變數 ( $VARNAME , ${VARNAME} ),替換成目前的「環境變數」。不過執行的時候,要特別加上你想替換的變數有哪些 ( ${BACKEND_URI} ),否則執行的過程會將所有範本中的 $VARNAME 全部移除。

最後一段的 nginx -g 'daemon off;' 是因為 nginx 預設執行時,會跑在 daemon 模式,將這個模式關閉,就可以讓 nginx 跑在前景,讓 Docker Engine 監視這個程序,如果 nginx 意外被關閉的話,Container 就會自動停止!

FROM node:10 AS node-builder
WORKDIR /src
COPY . .
RUN npm install
RUN npm run build -- --prod --output-path dist

FROM nginx:1.15.2-alpine
COPY --from=node-builder /src/dist /usr/share/nginx/html
COPY nginx.site.template /etc/nginx/conf.d/
CMD envsubst '${BACKEND_URI}' < /etc/nginx/conf.d/nginx.site.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'

建置 Docker 映像檔

docker build -t myapp:ng6-nginx .

執行 Docker 容器

請注意:執行 docker run 的時候,一定要加入 -e 參數,帶入 BACKEND_URI 環境變數,並設定 SCHEME://HOSTNAME:PORT 進去,這樣才能成功執行 nginx 反向代理功能。部署到 Kubernetes 的時候,也要記得綁定環境變數才行!

其中 myapp:ng6-nginx 只是一個 ImageName:Tag 而已,你可以任意修改。

docker run -d -p 8088:80 -e BACKEND_URI=https://dog.ceo myapp:ng6-nginx

連到 http://localhost:8088/ 就可以看到 Angular 應用程式成功執行,並且成功呼叫後端 API 顯示狗狗圖片。

連到 http://localhost:8088/api/breeds/image/random 就可以看到後端 API 可以透過 nginx 的反向代理設定正常取得資料。

相關連結


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

有的放矢

有的放矢

Nathan Furr、Paul Ahlstrom / 七印部落 / 华中科技大学出版社 / 2014-4-20 / 38.00元

创业需要大笔资金吗?自信的人适合创业吗?好点子究竟来自哪里?《有的放矢:NISI创业指南》的两位作者拥有多年创业与投资经验,收集了大量的一手案例和资料,提出有的放矢创业流程,帮助创业者规避创业风险,提高创业成功率。一起来看看 《有的放矢》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器