Link Search Menu Expand Document

Container

Advanced

Containerization là cơ chế đóng gói dịch vụ cùng những thư viện và cấu hình cần thiết trong một container từ đó dễ dàng triển khai và chia sẻ trên nhiều môi trường khác nhau (development, server hay cloud). Việc sử dụng container giúp các kĩ sư phần mềm tập trung hơn vào phát triển logic sản phẩm, trong khi nhóm vận hàng DevOps có thể triển khai và vận hàng sản phẩm một cách thuận lợi hơn.

Có nhiều nền tảng cung cấp cơ chế xây dựng, triển khai và vận hàng containers: Docker, Kuberness, Vagrant, etc…Trong phần tiếp theo, chúng ta sẽ tìm hiểu việc sử dụng Docker để đóng gói dịch vụ RemindersManagement trong Docker Image, từ đó tạo ra Docker Container để thực thi dịch vụ này.

Nội dung

  1. Container
  2. Cài đặt Docker
  3. Docker Image
  4. Docker Compose
    1. Health Check & CloudWatch
    2. Setup Reverse Proxy
    3. Setup HTTPS NGINX

Cài đặt Docker

Tham khảo cài đặt Docker Destop

Kiểm tra hệ thống Docker:

docker info

Docker Image

Docker là công cụ cho phép xây dựng môi trường phát triển và thực thi ứng dụng chạy trong một container độc lập. Container đóng gói ứng dụng cùng những tài nguyên hoặc thư viện cần thiết. Sử dụng container cho phép những kĩ sư thiết lập môi trường làm việc nhanh gọn, không cần quan tâm đến việc cài đặt các thư viện cho môi trường làm việc.

Một container được tạo theo các bước:

  • Khai báo Dockerfile - tập hợp các chỉ thị để xây dựng Docker Image
  • Tạo Docker Image - tập hợp các files được chia thành nhiều layers
  • Khởi tạo Docker Container dựa trên Docker Image

Trong phần này, chúng ta sẽ xây dựng một Docker Image cho dịch vụ RemindersManagement.

Tạo Dockerfile trong foler RemindersManagement.API

# Define build environment and working directory
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# Copy everything else and build
COPY . .
RUN dotnet publish -c release -o out

# Define runtime environment and working directory
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1

# Copy build result and asset to folder
WORKDIR /app
COPY --from=build /app/out .

# Define environment variable
ENV DOTNET_RUNNING_IN_CONTAINER=true \
  ASPNETCORE_URLS=http://+:8000

# Define port and entry point for running docker
EXPOSE 8000
ENTRYPOINT ["dotnet", "RemindersManagement.API.dll"]

Dockerfile thực hiện hai việc chính:

  • Download image mcr.microsoft.com/dotnet/core/sdk:3.1, kết hợp lệnh dotnet restore / dotnet publish để cài đặt thư viện và biên dịch dịch vụ RemindersManagement trên Docker Container.
  • Download image mcr.microsoft.com/dotnet/core/aspnet:3.1, khai báo ENTRYPOINT cho phép thực thi container như một chương trình với main command dotnet RemindersManagement.API.dll

Trong folder RemindersManagement.API tạo Docker Image với lệnh:

docker build --tag remindersmanagement:1.0 .

Câu lệnh sử dụng tham số:

  • -t remindersmanagement:1.0: tên và version của Docker Image
  • .: vị trí của thư mục chứa Dockerfile

Output:

Sending build context to Docker daemon  180.6MB
Step 1/12 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
 ---> 9ab567a29502
Step 2/12 : WORKDIR /app
 ---> Using cache
 ---> 4413e130453d
Step 3/12 : COPY *.csproj ./
 ---> 2ae0d9c0e0d7
Step 4/12 : RUN dotnet restore
 ---> Running in 72d7aabef5da
  Determining projects to restore...
  Restored /app/RemindersManagement.API.csproj (in 39.78 sec).
Removing intermediate container 72d7aabef5da
 ---> 5a2226da309a
Step 5/12 : COPY . .
 ---> e3d34d9024d8
Step 6/12 : RUN dotnet publish -c release -o out
 ---> Running in e809355e8e1c
Microsoft (R) Build Engine version 16.7.0-preview-20360-03+188921e2f for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  Restored /app/RemindersManagement.API.csproj (in 814 ms).
  RemindersManagement.API -> /app/bin/release/netcoreapp3.1/RemindersManagement.API.dll
  RemindersManagement.API -> /app/out/
Removing intermediate container e809355e8e1c
 ---> b6f83339f334
Step 7/12 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
 ---> bdca989bc8d3
Step 8/12 : WORKDIR /app
 ---> Using cache
 ---> 729e605b63dc
Step 9/12 : COPY --from=build /app/out .
 ---> f09bf1a60e06
Step 10/12 : ENV DOTNET_RUNNING_IN_CONTAINER=true   ASPNETCORE_URLS=http://+:8000
 ---> Running in bfe989c99c9f
Removing intermediate container bfe989c99c9f
 ---> a63a0e590682
Step 11/12 : EXPOSE 8000
 ---> Running in 1a4845d9faa4
Removing intermediate container 1a4845d9faa4
 ---> 12bd9184dc49
Step 12/12 : ENTRYPOINT ["dotnet", "RemindersManagement.API.dll"]
 ---> Running in 8c727d26c18e
Removing intermediate container 8c727d26c18e
 ---> 5fa79800389e
Successfully built 5fa79800389e
Successfully tagged remindersmanagement:1.0

Bên cạnh đó, có thể dùng câu lệnh sau để xác nhận remindersmanagement đã được build thành công:

docker images

Output

REPOSITORY                              TAG                 IMAGE ID            CREATED             SIZE
remindersmanagement                     1.0                 322671312233        35 seconds ago      267MB
mcr.microsoft.com/dotnet/core/sdk       3.1-buster          65279ad76723        2 weeks ago         708MB
mcr.microsoft.com/dotnet/core/runtime   3.1-buster-slim     601add7f3c26        2 weeks ago         190MB
mcr.microsoft.com/dotnet/core/sdk       3.1                 9ab567a29502        6 weeks ago         708MB
mcr.microsoft.com/dotnet/core/aspnet    3.1                 bdca989bc8d3        6 weeks ago         207MB

Docker Compose

Docker Compose là công cụ cho phép thực thi và quản lý nhiều thành phần của ứng dụng trên các containers khác nhau.

Phần thực hành của Docker Compose chia thành các phần:

  • Health Check & CloudWatch: tích hợp Health Check, CloudWatch
  • Setup Reverse Proxy: sử dụng Reverse Proxy dựa trên NGINX
  • Setup HTTPS NGINX: cài đặt giao thức HTTP Secure (HTTPS)

Health Check & CloudWatch

Trong phần ví dụ Middleware Health Check, chúng ta sử dụng Health Check UI để giám sát thông tin về trạng thái của dịch vụ RemindersManagament. Thông tin Health Check được ghi lại trực tiếp trong “in-memory storage”.

Tuy nhiên, cách làm này chưa thực sự hợp lý:

  • Health Check nên thực thi trên một môi trường độc lập với services
  • Dữ liệu Health cần được lưu trữ trong một cơ sở dữ liệu riêng biệt

Khi thực thi ứng dụng với Docker Compose, chúng ta có thể bổ sung thêm các containers cho Health Check service và Health Check Storage Provider (MySQL Server).

Các bước thực hiện:

Bước 1: Khai báo cấu hình Docker Compose

Trong solution folder FriendReminders, tạo file docker-compose.yml với nội dung

version: '3.8'

services:
  remindersmgtservice:    
    build:
      context: ./Services/RemindersManagement/RemindersManagement.API
      dockerfile: ./Dockerfile
    ports:
      - 8000:8000      
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    env_file:
      - ./aws-secret-dev.env
    networks:
      - webproxy
    depends_on:
      - healthcheckserver
  healthcheckserver:
    image: xabarilcoding/healthchecksui
    depends_on:
      - healthcheckdbserver
    environment:
      - storage_provider=MySql
      - storage_connection=Server=healthcheckdbserver;uid=root;Password=password;database=healthcheckdb
      - Logging:LogLevel:Default=Debug
      - Logging:Loglevel:Microsoft=Warning
      - Logging:LogLevel:HealthChecks=Debug
    ports:
      - 5000:80
    networks:
      - webproxy
  healthcheckdbserver:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: healthcheckdb
      MYSQL_USER: root
      MYSQL_PASSWORD: password
    networks:
      - webproxy

networks:
  webproxy:
    driver: bridge

Những điểm thay đổi cần chú ý:

  • Bổ sung Containers cho health check
    • healthcheckserver: sử dụng healthchecksui image, thực hiện việc giám sát health
    • healthcheckdbserver: sử dụng mysql image, lưu trữ dữ liệu health trong database
  • Trong remindersmgtservice:
    • env_file: AWWS credential cho phép service gửi log từ Serilog đến CloudWatch
    • depends_on: khai báo sự phụ thuộc vào health check service
    • Thực thi Development mode với khai báo ASPNETCORE_ENVIRONMENT

Bên cạnh đó, chúng ta cần tạo file aws-secret-dev.env chứa thông tin AWS Credential

AWS_ACCESS_KEY_ID=[Your_Secret_ID]
AWS_SECRET_ACCESS_KEY=[Your_Secret_Access_Key]

Chú ý

Việc lưu giá trị AWS Credential dưới dạng text file không phải là phương án tối ưu nhất, mặc dù chúng ta có thể chỉ lưu file này trên máy tính local và không commit lên source code repository. Bên cạnh phương án sử dụng *.env file , chúng ta có thể sử dụng Docker Secret áp dụng trong chế độ Docker Swarm, hoặc sử dụng dịch vụ Secret Manager của AWS.

Bước 2: Thay đổi nội dung ConfigureServices trong Startup.cs cho phép service lưu dữ liệu health check xuống MySQL Database

using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using RemindersManagement.API.Domain.Interfaces;
using RemindersManagement.API.Domain.Services;
using RemindersManagement.API.Infrastructure.Data;
using RemindersManagement.API.Infrastructure.Repositories;
using Serilog;

namespace RemindersManagement.API
{
    public class Startup
    {
      ...
      public void ConfigureServices(IServiceCollection services)
      {
          services.AddControllers();
          services.AddScoped<IRemindersRepository, RemindersRepository>();
          services.AddScoped<ICategoriesRepository, CategoriesRepository>();
          services.AddScoped<IRemindersService, RemindersService>();
          services.AddScoped<IUnitOfWork, UnitOfWork>();
          services.AddDbContext<RemindersDbContext>(options => {
              options.UseSqlite("Data Source=FriendReminders.db");
          });    
          // Register the Swagger generator
          services.AddSwaggerGen();
          // Register health check services
          services.AddHealthChecks();

          // Register HealthChecks UI and storage provider
          services
              .AddHealthChecksUI()
              .AddMySqlStorage("Server=healthcheckdbserver;uid=root;Password=password;database=healthcheckdb");
      }
    }
}

ConfigureServices sử dụng method AddMySqlStorage để lưu thông tin health check xuống MySQL server healthcheckdbserver, do vậy trong folder RemindersManagement.API, chúng ta cần cài đặt MySQL storage provider package với lệnh:

dotnet add package AspNetCore.HealthChecks.UI.MySql.Storage

Ngoài ra, do sử dụng Docker Compose, nội dung file cấu hình appsettings.Development.json cũng cần cập nhật lại giá trị endpoint Uri của Health Check:

{
  "HealthChecksUI": {
    "HealthChecks": [
      {
        "Name": "RemindersManagement",
        "Uri": "http://remindersmgtservice:8000/health"
      }
    ]
  },
  "Serilog": {
    "Using": [
      "Serilog.Sinks.Console",
      "AWS.Logger.SeriLog"
    ],
    "LogGroup": "friendreminders/RemindersManagement",
    "Region": "ap-southeast-2",
    "MinimumLevel": {
      "Default": "Information"
    },
    "WriteTo": [
      {
        "Name": "Console"
      },
      {
        "Name": "AWSSeriLog"
      }
    ],
    "Enrich": [
      "FromLogContext"
    ]
  },
  "AllowedHosts": "*"
}

Bước 3: Xác nhận kết quả

Trong folder FriendReminders thực thi lệnh:

docker-compose up --build

Sử dụng Docker Desktop kiểm tra danh sách các containers:

Multi Container Ouput Danh sách Docker Containers trên Docker Desktop

Gửi HTTP Get request đến URL endpoint http://localhost:8000/api/Reminders:

Http Kestrel Get Ouput Nội dung HTTP Response từ Kestrel endpoint /api/Reminders

 content-type: application/json; charset=utf-8 
 date: Tue22 Sep 2020 10:21:23 GMT 
 server: Kestrel 
 transfer-encoding: Identity 

Thông tin Header cho thấy kết quả được trả về từ Kestrel Server. Trong phần tiếp theo, chúng ta sẽ cài đặt NGINX proxy với mục đích hạn chế giao tiếp trực tiếp giữa client và HTTP server.


Setup Reverse Proxy

Có hai mô hình kết hợp việc thực thi ứng dụng Web API và HTTP Server:

  • In-process: Thực thi trên cùng một tiến trình
  • Out-process: Thực thi trên các tiến trình khác nhau

Theo mặc định, ứng dụng ASP.NET Core và HTTP Server - Kestrel kết hợp theo mô hình in-process. Kestrel tiếp nhận HTTP request, đóng gói lại dưới đối tượng HTTPContext trước khi gửi lại cho ứng dụng. Mô hình in-process đem lại tính tối ưu cao hơn so với out-process do hệ thống không cần thực hiện chức năng quản lý tiến trình cũng như chuyển tiếp yêu cầu qua lại giữa các network adapter.

Khi triển khai trong môi trường Production, Kestrel thường kết hợp cùng Reverse Proxy (Internet-facing proxy) cho những mục đích:

  • Hạn chế giao tiếp trực tiếp giữa ứng dụng và bên ngoài
  • Cung cấp thêm một lớp bảo vệ cùng khả năng tuỳ biến cần thiết
  • Đem lại khả năng cân bằng tải - Load Balancing
  • Tăng cường khả năng bảo mật với giao thức HTTPS
  • Giảm tải - offload cho Web/Application Server

Theo phân tích trên, chúng ta sẽ bổ sung một Reverse Proxy - Nginx vào ví dụ Docker Compose. Bên cạnh Nginx, cũng có rất nhiều lựa chọn khác bao gồm: HAProxy, Enyou, Traefik, Apache.

Hướng dẫn:

Việc kết hợp Reverse Proxy và Application Server được áp dụng phổ biến trong mô hình kiến trúc Microservices với thuật ngữ Sidecar Patterns.

Các bước thực hiện:

  • Trong folder RemindersManagement.API, tạo folder Proxy bao gồm:

Dockerfile

FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf

nginx.conf

worker_processes auto;
events { worker_connections 512; }
 
http {
    sendfile on;
    upstream app_servers {
        server remindersmgtservice:8000;
    }
    server {
        listen 80;
        location / {
            proxy_pass  http://app_servers;
        }
    }
}

Trong cấu hình này, Nginx thực thi trên cổng 80 và liên kết với upstream service remindersmgtservice.

  • Cập nhật file docker-compose.yaml:
version: '3.8'

services:
  nginx:
    restart: always
    build:
      dockerfile: Dockerfile
      context: ./Services/RemindersManagement/RemindersManagement.API/Proxy
    ports:
      - "80:80"
      - "443:443"
    networks:
      - webproxy
    depends_on:
      - remindersmgtservice
  remindersmgtservice:    
    build:
      context: ./Services/RemindersManagement/RemindersManagement.API
      dockerfile: ./Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    env_file:
      - ./aws-secret-dev.env 
    networks:
      - webproxy
    depends_on:
      - healthcheckserver
  healthcheckserver:
    image: xabarilcoding/healthchecksui
    depends_on:
      - healthcheckdbserver
    environment:
      - storage_provider=MySql
      - storage_connection=Server=healthcheckdbserver;uid=root;Password=password;database=healthcheckdb
      - Logging:LogLevel:Default=Debug
      - Logging:Loglevel:Microsoft=Warning
      - Logging:LogLevel:HealthChecks=Debug
    ports:
      - 5000:80
    networks:
      - webproxy
  healthcheckdbserver:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: healthcheckdb
      MYSQL_USER: root
      MYSQL_PASSWORD: password
    networks:
      - webproxy

networks:
  webproxy:
    driver: bridge

Chú ý

docker-compose.yaml loại bỏ khai báo ports trong remindersmgtservice do service này không cần giao tiếp trực tiếp với môi trường Docker Host. Mọi messages trao đổi giữa client và Http server phải đi qua và kiểm soát bởi Reverse Proxy.

  • Để xác nhận kết quả, trong folder FriendReminders thực thi lệnh:
docker-compose up --build

Gửi HTTP Get request đến URL endpoint http://localhost/api/Reminders:

Nginx Http Get Ouput Nội dung HTTP Response từ NGINX endpoint /api/Reminders

Thông tin Header cho thấy kết quả được trả về từ NGINX proxy.

 connection: keep-alive 
 content-type: application/json; charset=utf-8 
 date: Tue22 Sep 2020 11:02:40 GMT 
 server: nginx/1.19.2 
 transfer-encoding: Identity 

Setup HTTPS NGINX

Theo đề cập trong phần trước, một trong những chức năng của Reverse Proxy là tăng cường khả năng bảo mật cho một dịch vụ thông qua giao thức HTTPS. Về bản chất, giao thức HTTS là một bản “nâng cấp” của HTTP khi bổ sung thêm một lớp mã hoá thông tin - Secure Socket Layer (SSL). SSL thực hiện việc mã hoá / giải mã thông tin giữa Client và Server thông qua một hạ tầng khoá công khai - Public Key Instrastructure (PKI).

Trong mô hình trao đổi thông tin của PKI, chúng ta sử dụng một cặp khoá, Public / Private Key. Client sử dụng Public Key để mã hoá thông tin gửi đến Server. Server sử dụng Private Key để giải mã thông tin này, đồng thời có trách nhiệm quản lý bảo mật đối với Private Key. Có nhiều thuật toán được áp dụng để tạo ra Public / Private Key, một trong những thuật toán phổ biến nhất là Rivest–Shamir–Adleman (RSA).

Bên cạnh đó, trước khi Client sử dụng Public Key để mã hoá thông tin, câu hỏi đặt ra là Public Key sẽ được chia sẻ như nào giữa Client và Server? Khi Client nhận được Public Key, làm cách nào để Client biết Public Key đó thuộc về Server mà nó đang cần gửi thông tin?

Để thực hiện điều này, Client và Server sẽ cần tin tưởng đến một bên thứ ba - Certificate Authority (CA). CA là một tổ chức quản lý và xác thực danh tính bằng việc sử dụng chữ kí điện tử - Digital Certification. Để tạo ra Certification trên CA, Server cần gửi đến CA Public Key sử dụng cùng với thông tin chứng thực danh tính - Distinguised Name. Phía CA kiểm chứng thông tin này, và cung cấp cho Server một Certification sử dụng cho quá trình trao đổi thông tin với Client.

Trong giai đoạn trao đổi thông tin đầu tiên giữa Client và Server qua giao thức HTTPS với port 443, phía Server sẽ cung cấp Public Key và Certification. Client liên lạc với CA và được chứng thực về thông tin này. Khi việc chứng thực được đảm bảo bởi CA, Client sẽ sử dụng Public Key để mã hoá thông tin gửi đến Server. Trong một số cơ chế, Client có thể tạo thêm một Session Key, mã hoá bởi Public Key khi gửi trả Server, sau đó Client / Server sẽ dựa trên Session Key để trao đổi thông tin.

Trong phần thực hành này, chúng ta sẽ tiến hành việc cài đặt HTTPS trên NGINX. Dựa trên đó, Client sử dụng HTTPS để trao đổi thông tin với remindersmgtservice một cách gián tiếp qua NGINX. NGINX nhận được thông tin từ Client, và chuyển tiếp đến remindersmgtservice qua giao thức HTTP. Trong môi trường Development, Client và Server hoạt động trên cùng một Host, do vậy NGINX chỉ cần thực hiện self-signed certification thay vì gửi yêu cầu đến một CA bên ngoài.

Quá trình tạo self-signed certification:

  • Trên Terminal, xác nhận phiên bản OpenSSL:
openssl version -a

Output:

LibreSSL 2.8.3
built on: date not available
platform: information not available
options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx) 
compiler: information not available
OPENSSLDIR: "/private/etc/ssl"
  • Trong folder RemindersManagement.API\Proxy, tạo file localhost.conf:
[req]
default_bits = 1024
distinguished_name = req_distinguished_name
req_extensions     = req_ext
x509_extensions    = v3_ca

[req_distinguished_name]
countryName                 = Country Name (2 letter code)
countryName_default         = US
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = Texas
localityName                = Locality Name (eg, city)
localityName_default        = Dallas
organizationName            = Organization Name (eg, company)
organizationName_default    = localhost
organizationalUnitName      = organizationalunit
organizationalUnitName_default = Development
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_default          = localhost
commonName_max              = 64

[req_ext]
subjectAltName = @alt_names

[v3_ca]
subjectAltName = @alt_names

[alt_names]
DNS.1   = localhost
DNS.2   = 127.0.0.1

File localhost.conf cung cấp cấu hình của Distinguised Name sẽ sử dụng khi thực hiện yêu cầu tạo Certification.

  • Tạo 2048 bit Private Key localhost.key với thuật toán RSA
openssl genrsa -out localhost.key 2048

Có thể sử dụng câu lệnh sau để hiển thị thông tin của một Private Key

 openssl rsa -check -in localhost.key
  • Tạo self-signed certification localhost.crt với chuẩn mã hoá x509
openssl req -key localhost.key -new -x509 -days 365 -out localhost.crt -config localhost.conf
  • Đăng kí localhost.crt với hệ thống MacOS Keychain
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ./localhost.crt

Cập nhật Nginx Dockerfile để copy Private Key và Certification vào image:

FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf
COPY localhost.crt /etc/ssl/certs/localhost.crt
COPY localhost.key /etc/ssl/private/localhost.key

Do HTTPS request khi chuyển qua HTTP sẽ bị mất một số thông tin gốc (schema, ip…) từ phía Client, chúng ta cần cập nhật nginx.conf cho phép Reverse Proxy thiết lập lại thông tin này trước khi chuyển cho remindersmgtservice:

worker_processes auto;
events { worker_connections 512; }
 
http {
    sendfile on;
    upstream app_servers {
        server remindersmgtservice:8000;
    }
    server {
        listen 80;
        location / {
            proxy_pass  http://app_servers;
        }
    }
    server {
        listen 443 ssl;
        server_name localhost;
        ssl_certificate /etc/ssl/certs/localhost.crt;
        ssl_certificate_key /etc/ssl/private/localhost.key;
        location / {
            proxy_pass         http://app_servers;
            proxy_redirect     off;
            proxy_http_version 1.1;
            proxy_cache_bypass $http_upgrade;
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection keep-alive;
            proxy_set_header   Host $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-Proto $scheme;
            proxy_set_header   X-Forwarded-Host $server_name;
        }
    }
}
  • Đăng kí Forwarded Headers Middleware trong Startup.cs. Middleware này sẽ đọc các thông tin header được thiệt lập trên Nginx và đóng gói lại trong HttpContext:
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using RemindersManagement.API.Domain.Interfaces;
using RemindersManagement.API.Domain.Services;
using RemindersManagement.API.Infrastructure.Data;
using RemindersManagement.API.Infrastructure.Repositories;
using Serilog;

namespace RemindersManagement.API
{
    public class Startup
    {
      public void ConfigureServices(IServiceCollection services)
      {
          services.AddControllers();
          services.Configure<ForwardedHeadersOptions>(options =>
          {
              options.ForwardedHeaders =
                  ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
          });            
          ...
      }

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
          if (env.IsDevelopment())
          {
              app.UseDeveloperExceptionPage();
              app.UseForwardedHeaders();
          }
          else
          {
              app.UseForwardedHeaders();
              app.UseHsts();                
          }
          ...
      }
    }
}
  • Trong folder ReminderFriends, thực hiện lệnh docker-compose up --build, và kiểm tra kết quả theo địa chỉ
https://localhost/swagger/index.html

Khi lần đầu tiên vào địa chỉ trên, trình duyệt (Safari) có thể hiển thị Warning trên do việc chúng ta sử dụng self-signed certification.

Https Confirmation Self-signed certification warning & confirmation

Bỏ qua Warning này và lựa chọn Visit this website, xác nhận Swagger API Document hiển thị thành công. Icon lock trên thanh địa chỉ của trình duyệt cho biết kết nối được thực hiện qua giao thức HTTPS.

Https Swagger Giao diện Swagger của RemindersManagement API qua HTTPS


Tài liệu tham khảo


Copyright © 2019-2022 Tuan Anh Le.