iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0

前言

昨天透過 GitHub Actions 成功將我的 SpringBoot 模組容器化並部署到了 GCE,容器 run 是 run 了起來,但內部的 SpringBoot 啟動時出現 "Communications link failure" 錯誤,因為它無法連接到資料庫,所以今天主要目標是解決 SpringBoot 應用在 GCE 上的資料庫連接問題:

Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Caused by: java.net.ConnectException: Connection refused

實作

我決定在同一台 GCE 實例上部署 MySQL 容器來解決這個問題,避免額外的雲端資料庫成本,因為我看網路上好像沒有免費額度的 MySQL 雲服務,所以最終選擇在同一台 GCE 上運行 MySQL 容器,只求先快速解決問題,因為我想趕快看到我的專案順利運作起來,順便學習一下容器網路配置。

MySQL 容器部署

在 GCE Console 用 SSH 連進 VM 並啟動 MySQL 容器:

sudo docker run -d \
  --name mysql-db \
  -e MYSQL_ROOT_PASSWORD=Password123 \
  -e MYSQL_DATABASE=XXX_BASE \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  --restart unless-stopped \
  mysql:8.0

Docker 網路隔離

即使 MySQL 容器正常運行,SpringBoot 應用仍然無法連接。網路測試:

docker exec playground ping mysql-db
# 結果:ping: bad address 'mysql-db'

docker exec 意思是連進容器裡面執行終端機指令的意思

原因

兩個容器運行在不同的 Docker 網路中:

  • SpringBoot 容器:default 網路
  • MySQL 容器:default 網路(但相互隔離)

Docker 的預設行為是為每個容器創建獨立的網路命名空間,即使在同一主機上的容器也無法直接通過容器名稱互相訪問。

Docker 自定義網路

# 創建自定義網路
sudo docker network create playground-network

# 將容器連接到同一網路
sudo docker network connect playground-network mysql-db
sudo docker network connect playground-network playground

在啟動時指定網路

docker run --network playground-network ...

GitHub Actions workflow 中的部署指令:

sudo docker run -d --name $SERVICE --restart unless-stopped -p 8080:8080 $IMAGE_URL

這個指令沒有指定 --network 參數的話,每次重部署容器會連接到預設網路。

應用配置調整

將資料庫連接字串從:

url: jdbc:mysql://localhost:3306/CORE_BASE

改為:

url: jdbc:mysql://mysql-db:3306/CORE_BASE

MySQL 8.0 認證問題

即使網路連接成功,MySQL 8.0 還是認證錯誤:

Public Key Retrieval is not allowed

在連接字串中加入:

url: jdbc:mysql://mysql-db:3306/CORE_BASE?useSSL=false&serverTimezone=Asia/Taipei&allowPublicKeyRetrieval=true

總結

Docker 網路機制

  • 網路隔離原理:每個容器預設在獨立的網路命名空間中運行
  • 容器間通信:需要透過自定義網路或網路連接來實現
  • DNS 解析:在同一自定義網路中,容器可以透過容器名稱互相訪問

CI/CD 流程的網路配置

在部署腳本考慮網路配置,避免每次部署後失去網路連接:

sudo docker run -d --name $SERVICE --network playground-network --restart unless-stopped -p 8080:8080 $IMAGE_URL

容器 Debug

  • 網路測試docker exec container ping target
  • 日誌分析docker logs -f containerdocker logs --tail N container
  • 網路檢查docker network lsdocker network inspect network-name
  • 容器狀態docker ps -adocker inspect container

MySQL 8.0 在容器環境中的配置

  • 認證機制需要額外的連接參數
  • 容器間的網路通信需要正確的主機名稱配置
  • 資料持久化需要使用 volume 掛載

下一步改進方向

  1. 完善 CI/CD 流程:修改 GitHub Actions workflow 包含正確的網路配置
  2. 監控和日誌:建立更完善的應用監控機制
  3. 資料備份:為 MySQL 容器建立定期備份策略
  4. 服務健康檢查:在部署腳本中加入服務健康狀態驗證

上一篇
Day 24 | 第三階段系統優化 | 繼續 GitHub Actions + GCE 部署:回頭把某些概念 solidify 一下
系列文
系統設計一招一式:最基本的功練到爛熟就是殺手鐧,從單體架構到分布式系統的 Lab 實作筆記25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言