iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
SideProject30

30 天學習 Docker 部署你的專案系列 第 27

DAY 27 - 在我部署的專案使用 Traefik 取得 HTTPS 協定(三)

  • 分享至 

  • xImage
  •  

昨天將 domain 設定好,確定目前的 mydocker.online 是已經跟我們的服務連上的, docker-compose.yml 目前長成如下,那我們今天要一步步來除錯。

version: "3.9"
services:
  app:
    image: krystallll/docker_test:1.0
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      POSTGRES_HOST: db
      POSTGRES_PORT: 5432
    restart: on-failure
    ports:
      - 80:3000
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.app.loadbalancer.server.port=3000"
      - "traefik.http.routers.app.rule=Host(`mydocker.online`)"`
      - "traefik.http.routers.app.entrypoints=web"
      - "traefik.http.routers.app.tls=true"
      - "traefik.http.routers.app.tls.certresolver=letsencrypt"
  db:
    image: postgres:14-alpine
    restart: on-failure
    environment:
      POSTGRES_PASSWORD: password
  # traefik:
    # image: traefik:v2.10
    # command:
      # - "--api.insecure=true"
      # - "--providers.docker=true"
      # - "--providers.docker.exposedbydefault=false"
      # - "--entrypoints.web.address=:80"
      # - "--entrypoints.websecure.address=:443"
      # - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      # - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      # - "--certificatesresolvers.letsencrypt.acme.email=krystal@5xcampus.com"
      # - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    # ports:
      # - "80:80"
      # - "443:443"
      # - "8080:8080"
    # volumes:
      # - "./letsencrypt:/letsencrypt"
      # - /var/run/docker.sock:/var/run/docker.sock

當我將上述註解都打開,並且移除 app 服務的 ports: - 80:3000 (移除是因為 traefik 服務有 80 port ,所以可以由他指揮去 app 服務) 後,重新 docker-compose up ,再去網址 https://mydocker.online 時,不外乎一樣是 404 page not found。

統整一下我搜集到的可能連接不上的所有原因,來一一檢查修改

服務是否有在共同的 Network 下運行?

因為我的 docker-compose.yml 沒有特別設定在哪個網路下執行,所以我們就先來設定一下,確保我的 docker-compose 的所有服務都在同個網路下執行,可以互相通信,如果大家對於 Network 不太熟悉,可以參考 DAY 6 Docker Network(網路)容器與容器間的橋樑

首先我要先建立一個網路,我就取名為 development 好了,那就在我的 AWS EC2 instance 終端機裡面,我可以先確認現在的 Network 有哪些

docker network ls

再來建立名為 development 的網路

docker network create development

https://ithelp.ithome.com.tw/upload/images/20231012/20151035XO8SCnJCVk.png

看到這串 SHA 值就代表建立成功!

接著去 docker-compose.yml 加上這個 development 的網路

version: "3.9"
services:
  app:
    image: krystallll/docker_test:1.0
    networks:
      - development
    (...中間略)
  db:
    image: postgres:14-alpine
    networks:
      - development
    (...中間略)
  traefik:
    image: traefik:v2.10
    networks:
      - development
    (...中間略)
networks:
  development:
    external: true

這邊只有我加上網路的片段,其他都跟本來一樣就先省略。

是否有開啟安全群組?

接者每當我們前面要去 port 3000 或是 8080 我們都有檢查 Security Groups ,但是現在我們在 docker-compose.yml 的 traefik 服務,是開了三個 port 80、443、8080

ports:
   - "80:80"
   - "443:443"
   - "8080:8080"

所以現在要去檢查 Security Groups 是否都有開?

https://ithelp.ithome.com.tw/upload/images/20231012/20151035S4IuAkXz7R.png

發現少了 https 的 443 port,所以我加開了 443 port 的 Security Groups

檢查 docker-compose.yml 設置

我重新翻閱了官網,找到以下兩個 靜態設置 以及 docker labels 這邊列出了所有的設置,我重新配置了一下我的 docker-compose.yml

version: "3.9"
services:
  app:
    image: krystallll/docker_test:1.0
    networks:
      - development
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      POSTGRES_HOST: db
      POSTGRES_PORT: 5432
    restart: on-failure
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app-http.entrypoints=web"
      - "traefik.http.routers.app-https.entrypoints=websecure"
      - "traefik.http.routers.app-http.rule=Host(`mydocker.online`)"
      - "traefik.http.routers.app-https.rule=Host(`mydocker.online`)"
      - "traefik.http.routers.app-https.tls=true"
      - "traefik.http.routers.app-https.tls.certresolver=letsencrypt"
      - "traefik.http.middlewares.https-only.redirectscheme.scheme=https"
      - "traefik.http.routers.app-http.middlewares=https-only"
      - "traefik.http.routers.app-https.service=app"
      - "traefik.http.services.app.loadbalancer.server.port=3000"
  db:
    image: postgres:14-alpine
    networks:
      - development
    restart: on-failure
    environment:
      POSTGRES_PASSWORD: password
  traefik:
    image: traefik:v2.10
    networks:
      - development
    restart: on-failure
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.letsencrypt.acme.email=krystal@5xcampus.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - /var/run/docker.sock:/var/run/docker.sock
networks:
  development:
    external: true

以下來一一說明:

traefik 服務的 command

  1. 開起 traefik 的 Web API
--api.insecure=true
  1. 是否暴露 docker 服務,其實翻成白話就是我不要將 docker 給 traefik 自動追蹤,只有需要被追蹤的服務再加上 traefik.enable=true 就好
--providers.docker.exposedbydefault=false
  1. 建立一個名為 web 的入口點,他的 port 是 80
--entrypoints.web.address=:80
  1. 建立一個名為 websecure 的入口點,他的 port 是 443
--entrypoints.websecure.address=:443
  1. 由 letsencrypt 來建立憑證
--certificatesresolvers.letsencrypt=true
  1. 使用 httpchallenge 來憑證申請
--certificatesresolvers.letsencrypt.acme.httpchallenge=true
  1. letsencrypt 申請的憑證入口點是 web 也就是我們上面設定的 port 80
--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
  1. 申請憑證需要的有用的 email
--certificatesresolvers.letsencrypt.acme.email=krystal@5xcampus.com
  1. letsencrypt 申請來的憑證檔案儲存的路徑
--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json

app 服務的 labels

  1. 上面有說到,代表這個服務歸交警伯伯 traefik 管
traefik.enable=true
  1. app-http 是我取的名字,代表 app-http 這個東東是走 web 這條路,因為 web 正常是 http ,所以我就直接取名為 app-http
traefik.http.routers.app-http.entrypoints=web
  1. 同上,代表 app-https 是走 websecure 這條路
traefik.http.routers.app-https.entrypoints=websecure
  1. 設定 app-httpapp-https 的 Host 是 mydocker.online
traefik.http.routers.app-http.rule=Host(`mydocker.online`)
traefik.http.routers.app-https.rule=Host(`mydocker.online`)
  1. 因為 app-https 是走 443 也就是 https 所以設定 true 代表他需要使用我們申請的憑證
traefik.http.routers.app-https.tls=true
  1. 使用 letsencrypt 來加密解密憑證
traefik.http.routers.app-https.tls.certresolver=letsencrypt
  1. 使用一個名為 https-only 的中介軟體,來固定將 http 轉址到 https (如果我們輸入的網址是 http 他會自動轉址到 https)
traefik.http.middlewares.https-only.redirectscheme.scheme=https
traefik.http.routers.app-http.middlewares=https-only
  1. 將 app-https 這個 router 定義一個叫做 app 的 service
traefik.http.routers.app-https.service=app
  1. 告訴 traefik 這個 app 的 service 是在 3000 port
traefik.http.services.app.loadbalancer.server.port=3000

重新啟動 docker-compose

docker-compose up

去瀏覽器輸入網址 mydocker.online

https://ithelp.ithome.com.tw/upload/images/20231012/20151035Iar0PsCSzd.png
搞了這麼多天就為了這個 https 的鎖呀🥹🎉🎉🎉
然後再根據按鈕按一按可以得來朝思暮想的首頁。
https://ithelp.ithome.com.tw/upload/images/20231012/20151035hG9Zjrtyvk.png
https://ithelp.ithome.com.tw/upload/images/20231012/20151035c6jJlJkEyR.png
另外也可以自己試試,硬是將網址輸入 http://mydocker.online ,他也會自動轉址到 https://mydocker.online 😍😍😍


上一篇
DAY 26 - 要取得協定得先有正確的 Domain
下一篇
DAY 28 - 使用 Volumes 讓我的資料庫保存之前的資料
系列文
30 天學習 Docker 部署你的專案30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言