Dev Talks

Deploy Rails with Docker Swarm (2) - 流程介紹與設定 Traefik & Rails

簡巧恩, Rails 工程師 Sep 2, 2022

讓我們進到實際操作的部分!這篇主要會先介紹一下後續的文章架構,主要是分成以下三個部分:

  • 設定 Rails & Traefik
  • 設定 AWS
  • 設定 Gitlab runner 自動化部署

因為篇幅的關係,這篇文會先介紹第一部分,後面兩部分也會再另外發新的文章(不知不覺就變成連載系列了)

部署流程


實作流程

  • 本地端進行部署
    • 開啟 rails production server
    • 確認本地端 Docker compose build/up 皆可順利執行
  • 手動 ssh 進入 EC2 部署
    • 將 Traefik 與 Docker Swarm 直接部署在 EC2 裡,詳細的流程會在下一部分的圖裡說明
  • 利用 Gitlab runner 自動部署
    • 將前一步的所有設定、部署指令自動化

實際部署流程

這邊要講的是完整的部署流程上執行了哪些設定,後續的介紹也會將以下四點的順序作為主要架構進行介紹:

  1. 設定 Traefik Service:依照上一篇提到的 Traefik 特性,先設定 reverse proxy(再把 app 掛上去)

  2. 設定 Rails App Service:基本上等於在本地端部署的步驟,也就是確認 Docker compose build/up 可以順利開啟服務

  3. 設定 EC2 與 Route53:在確認設定檔大致完成後,設定並開啟 EC2,將剛剛設定的服務部署上去

  4. 自動化部署 with Gitlab Runner:註冊並撰寫 runner 的腳本(.gitlab-ci.yml),而腳本的內容則是實際在部署時需要對機器本身下的設定,內容如下:

    1. 開啟 Docker Swarm
    2. 創建  traefik-public 的公開 Network,讓 App service 可以使用 traefik 來做 reverse proxy
    3. 指定每次 Traefik 更新時固定使用同個節點
    4. 使用 docker stack 部署 Traefik
    5. 部署 Rails App

實際部署 Docker Swarm 的流程

Rails & Traefik Service


Traefik Service Settings

Traefik 與 Rails App 其實是兩個獨立的服務,因此這邊會將 Traefik 與 Rails App 的設定檔分開,也就是 Traefik 會有一個 traefik.yml 用於部署 traefik stack,而 Rails App 則是使用原始的 docker-compose.yml 去部署 task stack(這邊的 Rails App 叫做 Task-Manager,因此 stack name 取為task

首先在 traefik.yml 中的設定會與一般的 docker compose file 架構相同,這邊我是參考 dockerswarm.rocks 裡提供的 Traefik 設定範例進行設定,不過我們會需要特別設定以下幾點(這部分也可以直接參考我寫好的設定檔 traefik.yml / Task-Manager-Ruby · GitLab):

  • Network:需要新增一個叫 traefik-public 的網路,並且設定為 external,好讓 Rails App 可以透過這個網路與 Traefik 溝通
  • Volumes:新增一個 traefik-public-certificate 的 volume,用於存放已經申請過的憑證
  • Service:分為兩部分需要注意,Command 與 Deploy Label
    • Command:Traefik 的基本設定,需要指定 Docker provider、開啟 Swarm mode,憑證的申請、儲存位置,以及 DNS Challenge 等等
    • Deploy Label:為了要開啟 Traefik Dashboard 而設定的 reverse proxy routing,主要有下列幾點要設定:
      • 開啟 Traefik 並加入 traefik-public Network
      • Dashboard 登入帳密
      • Http/Https host
      • Redirect middleware:當用戶使用 Http 發送請求,自動轉為 Https
      • Load balancer port:當有目的地是 host 的請求,Traefik 需要將其導向的 port
      • 設定 wildcard 驗證過的 domain

到這一步基本上 Traefik 本身已經設定完畢,可以先進 EC2 裡開好 Traefik stack 來檢查是否能正確開啟。

Rails App(Application) Service

接下來要說明的是 Rails App 要怎麼設定,當然這個部署架構不只限定於 Rails App,不過這個步驟可能要依照使用的語言或框架而改動。

首先必須生成一組 RAILS_MASTER_KEY,因為 Rails 在 Production 環境中需要有 RAILS_MASTER_KEY 才能啟動,確定 production server 可正常開啟後,可以來準備我們的 Dockerfile 與 Docker-compose file 來進行 task stack 的設定。

Dockerfile

這部分我使用的是 這個 gem 來幫我自動生成,他會依據專案中的 Gemfile 以及 boxing 本身的設定檔(config/boxing.rb)來自動生成 Dockerfile。另外這個 Gem 的作者(也就是蒼時大大)有特別研究如何生成最小化的 Docker image,因此自動生成的映像檔大約只會有(據他本人所說) 100 MB,下面列出可以另外設定的選項(粗體為我這次有採用的設定):

  • Source Code Root
  • Ignore File
  • Extra Packages: Node.js & Python
  • Revision Information
  • Sentry Support
  • Asset Precompile: True
  • Health Check
補充: OpenBox - Auto generate entrypoint settings,如果將 Boxing 與 OpenBox 同時採用的話,Boxing 生成的 Dockerfile 會將 Entrypoint 自動指定為 OpenBox 生成的 Entrypoint

Docker-compose file

與在本地端設定的 docker-compose.yml 基本上一樣,我在這邊是只有設定三個 service(app/redis/postgres),Network 只有 net 讓三個 service 共享,並加上下面兩項設定:

  • RAILS_MASTER_KEY:剛剛生成的 RAILS_MASTER_KEY 可以先放到 Gitlab 中設定為 CI variable(如果要跑本地測試的話可以將 RAILS_MASTER_KEY 放在 .env、或者設定為 app service 的 environment var,可以參考本地端的 docker-compose Line 55)
  • DATABSE_URL:在 app service 的 environment variable 要特別指定資料庫的路徑,才能正確連線到 postgres service,並且要注意格式為 postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]

做完基本的設定後,在把 Traefik 相關的 routing rules 加到 deploy label 上。這部分和在設定 Traefik 的 deploy labels 一樣,設定完畢後會像這個檔案類似。

補充

Load Balancer Port 設定

假設今天我們的 domain 是 abc.dev 有用戶請求了 traefik.abc.dev(aka 我們的 host name),而我們的 Traefik Dashboard 開在 8080 port,則 Traefik 會將這個 request 導向 8080

Wildcard 相關知識

相關設定的補充知識,需要參考我已經寫好的設定檔

  • Wildcard:ACME 驗證方式 - Let’s Encrypt - 免費的 SSL/TLS 憑證 (letsencrypt.org)
    • 可以直接申請某個 domain 的憑證,讓整個 domain 下的所有 host 都可以使用同一張憑證(domain.sans 部分),不需特地為所有 host 個別申請憑證
    • 屬於 Let’s Encrypt 發放的其中一種憑證格式
  • 給予 route53 權限的原因
    • 因為設定 DNS challenge 與 DNS Challenge Provider 為 route53
    • DNS challenge:需要有 route53 的權限才能動態驗證 *.domain 下的所有 host
    • Route53 提供自動更新憑證的 API

第一部分就到這邊結束,其實做到這個步驟應該就能在本地端進行部署(僅限 Rails 部分)。希望大家與 Docker 可以好好相處,他真的是個好用ㄉ酷東西(


想要閱讀更多來自五倍紅寶石軟體開發的技術分享?歡迎訂閱我們的月報,每月將自動幫你送上最新文章。


分享