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 的反向代理設定正常取得資料。

相關連結


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

查看所有标签

猜你喜欢:

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

Web Data Mining

Web Data Mining

Bing Liu / Springer / 2006-12-28 / USD 59.95

Web mining aims to discover useful information and knowledge from the Web hyperlink structure, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is n......一起来看看 《Web Data Mining》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具