Linux Server

Container Deployment on Linux Server

ในการ Deploy AtlasX Container บนเครื่อง server ที่เป็น Linux นั้นสามารถทำได้ง่าย ๆ เพียงแค่ใช้ Docker Compose ก็สามารถทำให้ container รันขึ้นมาได้

Prerequisite

บนเครื่อง server ที่จะทำการ deploy จะต้องมีการเตรียม library ต่าง ๆ ตามนี้

  1. Docker Engine – ใช้ในการรัน container
  2. Docker Compose – เป็น CLI ที่ใช้ในการรัน container ด้วย manifest file
  3. Container Registry – ใช้ในการเก็บ image ของ container
  4. Reverse Proxy (Nginx, Apache, Traefik, etc.) – ใช้ในการ redirect ไปยัง container ที่ต้องการ
  5. Docker Manifest File – ไฟล์ที่ใช้ในการรัน container ด้วย Docker Compose ดาวน์โหลดได้จากที่นี่

Docker Compose file

ทางทีม AtlasX ได้เลือกใช้ Traefik Proxy เป็น Reverse Proxy และ Service Load Balancer ในการจัดการ traffic ที่จะเข้ามาในแอพพลิเชั่น ดังนั้นไฟล์ docker-compose.yaml จึงมีการกำหนดให้ใช้งานร่วมกับ Traefik Proxy ด้วย ซึ่งจะมีรูปแบบดังนี้

version: '3.8'

services:
  webservice:
    image: '${WEBSERVICE_IMAGE}:${WEBSERVICE_VERSION}'
    container_name: atlasx-webservice
    networks:
      - frontend
    labels:
      - 'traefik.enable=true'
      # HTTP
      - 'traefik.http.routers.${WEBSERVICE_PROJECT_NAME}.entrypoints=web'
      # HTTPS
      # - 'traefik.http.routers.${WEBSERVICE_PROJECT_NAME}.entrypoints=websecure'
      # - 'traefik.http.routers.${WEBSERVICE_PROJECT_NAME}.tls=true'
      - 'traefik.http.routers.${WEBSERVICE_PROJECT_NAME}.rule=Host(`${WEBSERVICE_URL}`) && PathPrefix(`/${WEBSERVICE_BASEPATH}`)'
      - 'traefik.http.routers.${WEBSERVICE_PROJECT_NAME}.middlewares=${WEBSERVICE_PROJECT_NAME}-stripprefix'
      - 'traefik.http.middlewares.${WEBSERVICE_PROJECT_NAME}-stripprefix.stripprefix.prefixes=/${WEBSERVICE_BASEPATH}'
      - 'traefik.http.services.${WEBSERVICE_PROJECT_NAME}.loadbalancer.server.port=8080'
    environment:
      - ASPNETCORE_BASEPATH=/${WEBSERVICE_BASEPATH}
    restart: unless-stopped
  webapp:
    image: '${WEBAPP_IMAGE}:${WEBAPP_VERSION}'
    container_name: atlasx-webapp
    networks:
      - frontend
    labels:
      - 'traefik.enable=true'
      # HTTP
      - 'traefik.http.routers.${WEBAPP_PROJECT_NAME}.entrypoints=web'
      # HTTPS
      # - 'traefik.http.routers.${WEBAPP_PROJECT_NAME}.entrypoints=websecure'
      # - 'traefik.http.routers.${WEBAPP_PROJECT_NAME}.tls=true'
      - 'traefik.http.routers.${WEBAPP_PROJECT_NAME}.rule=Host(`${WEBAPP_URL}`) && PathPrefix(`/${WEBAPP_BASEPATH}`)'
      - 'traefik.http.routers.${WEBAPP_PROJECT_NAME}.middlewares=${WEBAPP_PROJECT_NAME}-stripprefix'
      - 'traefik.http.middlewares.${WEBAPP_PROJECT_NAME}-stripprefix.stripprefix.prefixes=/${WEBAPP_BASEPATH}'
      - 'traefik.http.services.${WEBAPP_PROJECT_NAME}.loadbalancer.server.port=8080'
    restart: unless-stopped

networks:
  frontend:
    external: true
Note

ในการกำหนดค่าต่าง ๆ เพื่อให้ Traefik Proxy สามารถค้นหา container ได้นั้น จะต้องมีการกำหนดค่าในส่วนของ labels ซึ่งถ้ามีการใช้งาน Reverse Proxy อื่น ๆ ก็สามารถลบ label ในส่วนที่เกี่ยวข้องกับ Traefik Proxy ออกไปได้

จะสังเกตได้ว่าในไฟล์ docker-compose.yaml จะมีการกำหนดให้รัน container 2 ตัวคือ webapp และ webservice ซึ่งเราสามารถกำหนดให้มีกี่ตัวก็ได้ อีกทั้งยังมีการกำหนด environment variable ในการกำหนดค่าต่าง ๆ อีกด้วย

Configuration

Environment Variables

ใน manifest template จะมีไฟล์ example.env ซึ่งจะเป็นไฟล์ที่ใช้ในการกำหนดค่าต่าง ๆ ของแอพพลิเคชั่น ซึ่งจะมีรูปแบบดังนี้

# Web Service
WEBSERVICE_IMAGE="atlasx-registry.cdg.co.th/atlasx/webservice"
WEBSERVICE_VERSION=
WEBSERVICE_PROJECT_NAME=
WEBSERVICE_BASEPATH=
WEBSERVICE_URL=

# Web Application
WEBAPP_IMAGE="atlasx-registry.cdg.co.th/atlasx/webapp"
WEBAPP_VERSION=
WEBAPP_PROJECT_NAME=
WEBAPP_BASEPATH=
WEBAPP_URL=

ให้ทำการคัดลอกไฟล์ example.env และเปลี่ยนชื่อไฟล์เป็น .env และกำหนดค่าต่าง ๆ ให้ถูกต้อง (Docker Compose จะอ่านค่าจากไฟล์ .env โดยอัตโนมัติ)

Definition

  • WEBSERVICE_IMAGE : เป็นชื่อของ Web Service Image ที่จะใช้ในการรัน container
  • WEBSERVICE_VERSION : เป็น tag ของ Web Service Image ที่จะใช้ในการรัน container
  • WEBSERVICE_PROJECT_NAME : เป็นชื่อของ service ที่จะนำไประบุบน Traefik Proxy และจะต้องไม่ซ้ำกับชื่อ service ที่มีอยู่แล้วบนเครื่องนั้น ๆ (แนะนำให้ตั้งเป็นชื่อโครงการ เช่น ax-portalmea-smartlife-api)
  • WEBSERVICE_BASEPATH : เป็น Base Path ของ Web Service ที่จะให้ reverse proxy เข้ามา
  • WEBSERVICE_URL : เป็น URL ของ Web Service ที่จะให้ reverse proxy เข้ามา
  • WEBAPP_IMAGE : เป็นชื่อของ Web Application Image ที่จะใช้ในการรัน container
  • WEBAPP_VERSION : เป็น tag ของ Web Application Image ที่จะใช้ในการรัน container
  • WEBAPP_PROJECT_NAME : เป็นชื่อของ service ที่จะนำไประบุบน Traefik Proxy และจะต้องไม่ซ้ำกับชื่อ service ที่มีอยู่แล้วบนเครื่องนั้น ๆ (แนะนำให้ตั้งเป็นชื่อโครงการ เช่น ax-portal-apimea-smartlife-api)
  • WEBAPP_BASEPATH : เป็น Base Path ของ Web Application ที่จะให้ reverse proxy เข้ามา และจะต้องตรงกับ base href ที่กำหนดตอน build Angular ด้วย
  • WEBAPP_URL : เป็น URL ของ Web Application ที่จะให้ reverse proxy เข้ามา

Docker Compose Configuration

ในไฟล์ docker-compose.yaml จะมีการกำหนดให้แต่ละ container รันอยู่ใน network frontend

networks:
  - frontend

ซึ่งเป็น network ภายในของ Docker ทำให้ container ใด ๆ ที่อยู่ network วงเดียวกัน สามารถเชื่อมต่อกันได้ รวมถึง reverse proxy ด้วย และเราได้กำหนดให้ network นี้เป็น external network เป็นการบอก Docker Compose ว่าให้ใช้ network ที่สร้างด้วย Docker ไม่ใช่จาก Docker Compose

networks:
  frontend:
    external: true

ดังนั้นเราจึงต้องสร้าง network นี้ก่อนที่จะรัน Docker Compose ด้วยคำสั่ง (ในกรณีที่ยังไม่มี network นี้อยู่)

docker network create frontend

Deployment

เมื่อตั้งค่าทุกอย่างเรียบร้อยแล้ว ให้มั่นใจว่าไฟล์ต่าง ๆ อยู่ในโฟลเดอร์ที่ถูกต้อง

MyProject/
├── .env
└── docker-compose.yaml

และทำการรัน Docker Compose ด้วยคำสั่ง

docker-compose up -d

เมื่อรันเสร็จแล้ว ให้เข้าไปที่ URL ของ Web Application ที่กำหนดไว้ในไฟล์ .env แล้วเราจะเห็นว่า Web Application ทำงานได้ปกติ

TLS

สำหรับการ deploy application ให้สามารถเข้าใช้งานผ่าน HTTPS ได้ เราจะต้องกำหนดให้ application ของเราเข้าถึงได้ผ่านทาง websecure entrypoints ของ Traefik Proxy ดังนี้

labels:
  - 'traefik.http.routers.${WEBSERVICE_PROJECT_NAME}.entrypoints=websecure'
  - 'traefik.http.routers.${WEBSERVICE_PROJECT_NAME}.tls=true'

ซึ่งเดิม entrypoints จะเป็น web ให้เราเปลี่ยนเป็น websecure จะทำให้ application เข้าได้ผ่าน HTTPS เท่านั้น

Note

หากต้องการให้ application เข้าได้ทั้ง HTTP และ HTTPS ให้ใช้ web,websecure แทน