目的?
以往在用 docker compose 快速啟動服務,常常會遇到:
- 在一台全新的機器或開發環境中,都需要手動進入docker內部db容器,手動執行初始化(init)資料庫結構的 SQL 腳本,接著再執行資料(seed)的 SQL 腳本來填充初始資料
- 流程不僅繁瑣,而且容易出錯,特別是在多個環境(如開發、測試、生產)中部署時
比如在某專案中,固定會有個 products
的資料表,並且每次部署到新主機第一次啟動時,去打端點都一定會跳sqlalchemy.exc.ProgrammingError: (psycopg2.errors.UndefinedTable) relation "table_name" does not exist
資料表不存在的錯誤,都得透過手動執行 Python 腳本 create_db_data.py + SQLAlchemy 語法來建表與插入資料
PostgreSQL 官方 image docker-entrypoint-initdb.d/ 機制
PostgreSQL 官方 image 內建的 docker-entrypoint.sh
會在容器初始化(第一次建立資料 volume)時,自動執行 /docker-entrypoint-initdb.d/
目錄底下的 .sql
或 .sh
檔案。
只要是在 /docker-entrypoint-initdb.d/
的 .sql
或 .sh
檔案,Postgres 會在 第一次啟動資料庫 時自動執行
初始化 SQL 檔案
創建 init-scripts
資料夾並在底下建立了三個 SQL 檔
1 | project/ |
在001_enable_extensions.sql
中,確保 pgcrypto 可用(因為用了 gen_random_uuid())產生 UUID
1 | CREATE EXTENSION IF NOT EXISTS "pgcrypto"; |
在002_create_table.sql
,寫建立資料表的 SQL
1 | CREATE TABLE IF NOT EXISTS products ( |
插入固定資料
1 | INSERT INTO products (name, description, price, in_stock) |
在 docker-compose.yaml 中掛載 init-scripts
最後在 docker-compose.yaml
中掛載 init-scripts
目錄
1 | services: |
這樣每次啟動時容器時,Postgres 容器就會:
- 執行 001_enable_extensions.sql → 啟用 UUID
- 執行 002_create_table.sql → 建立 products 資料表
- 執行 003_seed_data.sql → 插入三筆固定商品
結果
啟動後,我們可以進容器查詢資料:
1 | docker exec -it my_postgres psql -U myuser -d mydb -c "SELECT * FROM products;" |
應就能看到類似結果:
1 | id | name | description | price | in_stock | created_at | updated_at |
若您覺得這篇文章對您有幫助,歡迎分享出去讓更多人看到⊂◉‿◉つ~
留言版