我們在 D10 - Database by Docker 時,介紹了如何透過架設 MySQL,
不過,當我們要把應用程式跟資料庫連接起來時,還是很容易會遇到問題,
因此今天來說說,要如何讓 Express 的 API 使用架好的資料庫。
要在 Server 上連接資料庫,Node.JS 的生態系中有很多套件可以使用,
我們今天用 Sequelize 當作範例,
除了 sequelize
套件以外,還會需要安裝資料庫的驅動,MySQL 對應的是 mysql2 套件。
我們會需要定義 Sequelize 要使用的 Config,同時 Config 的值是讀取 .env
的內容:
# config/config.js
export default {
development: {
dialect: 'mysql',
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
}
}
DB_HOST=host.docker.internal
DB_PORT=3306
DB_DATABASE=ithelp
DB_USERNAME=louis
DB_PASSWORD=my-password
DB_ROOT_PASSWORD=root-password
這裡要注意一個小細節,
我們等等要讓程式是透過 Port 3306 去連接 MySQL,
因此要讓 Container 內可以連接到主機本身的 Port,
這裡必需把 Container 內要使用的 DB_HOST 定義為 host.docker.internal
。
(官方文件可參考: I want to connect from a container to a service on the host)
為了測試與資料庫的連接,我們直接定義一個 API 的內容是對資料庫的一筆 Query,
然而,這時資料庫都還沒有內容,因此不用查詢真實的資料,而是透過 MySQL 幫我們回傳 1+1 就可以了,
只要 MySQL 有回傳加起來的結果,那就表示連接成功,即使沒有資料也可以測試,
import Router from 'express';
import { Sequelize } from 'sequelize';
import config from '../config/config.js';
const router = Router();
const sequelize = new Sequelize(config.development);
router.get('/test-connection', async (_, res) => {
const result = await sequelize.query('select 1+1');
return res.json({ result });
});
export default router;
再次來到 Docker compose 的定義檔,
我們要定義兩個 Container,一個是 MySQL,另一個則是 Express,
version: "3"
services:
mysqldb:
image: mysql:8
ports:
- ${DB_PORT}:3306
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_ROOT_HOST=${DB_HOST}
- MYSQL_DATABASE=${DB_DATABASE}
- MYSQL_USER=${DB_USERNAME}
- MYSQL_PASSWORD=${DB_PASSWORD}
volumes:
- ./db:/var/lib/mysql
express:
build: .
ports:
- 3000:3000
env_file:
- .env
extra_hosts:
- "host.docker.internal:host-gateway"
這裡有第二個小細節,
在 Docker Compose 要讓 DB_HOST=host.docker.internal
能順利生效,我們必須要在加入一個特殊的參數: extra_hosts
,
接著就能跑起來了:
$ docker compose up -d
$ curl http://localhost:3000/test-connection
{"result":[[{"1+1":2}],[{"1+1":2}]]}%
看到了執行結果 1+1 = 2,
我們並沒有在程式內運算 1+1,而是下了 SQL 語法讓 MySQL 幫我們計算,
因此我們藉此確認 Express 跟資料庫已經順利連接 ?,
後續,就能比較安心地開始開發了,
那我們今天就到這邊,範例程式碼可以在 這裡 找到。