為開發環境在啟動時預先填充資料庫的模式和資料
在本地開發期間,使用基本資料和模式預置資料庫是一種常見的做法,可以增強開發和測試工作流程。透過模擬真實場景,這種做法有助於及早發現前端問題,確保資料庫管理員和軟體工程師之間的協調一致,並促進更順暢的協作。預置資料庫提供了諸多好處,如自信的部署、跨環境的一致性和早期問題檢測,最終改善了整個開發過程。
在本指南中,您將學習如何
- 使用 Docker 啟動一個 Postgres 容器
- 使用 SQL 指令碼預置 Postgres
- 透過將 SQL 檔案複製到 Docker 映象中來預置 Postgres
- 使用 JavaScript 程式碼預置 Postgres
在 Docker 中使用 Postgres
Postgres 的官方 Docker 映象提供了一種在開發機器上執行 Postgres 資料庫的便捷方式。Postgres Docker 映象是一個預先配置好的環境,封裝了 PostgreSQL 資料庫系統。它是一個獨立的單元,可以在 Docker 容器中直接執行。透過使用此映象,您可以快速輕鬆地設定一個 Postgres 例項,而無需手動配置。
先決條件
要跟隨本操作指南,需要滿足以下先決條件
啟動 Postgres
按照以下步驟啟動一個 Postgres 的快速演示
開啟終端並執行以下命令來啟動一個 Postgres 容器。
本示例將啟動一個 Postgres 容器,將埠
5432
暴露到主機上,以允許本地執行的應用程式使用密碼mysecretpassword
連線到它。$ docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=mysecretpassword postgres
透過選擇容器並檢查 Docker Dashboard 上的日誌,驗證 Postgres 是否已啟動並正在執行。
PostgreSQL Database directory appears to contain a database; Skipping initialization 2024-09-08 09:09:47.136 UTC [1] LOG: starting PostgreSQL 16.4 (Debian 16.4-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit 2024-09-08 09:09:47.137 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432 2024-09-08 09:09:47.137 UTC [1] LOG: listening on IPv6 address "::", port 5432 2024-09-08 09:09:47.139 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" 2024-09-08 09:09:47.142 UTC [29] LOG: database system was shut down at 2024-09-08 09:07:09 UTC 2024-09-08 09:09:47.148 UTC [1] LOG: database system is ready to accept connections
從本地系統連線到 Postgres。
psql
是 PostgreSQL 互動式 shell,用於連線到 Postgres 資料庫並允許您開始執行 SQL 命令。假設您已經在本地系統上安裝了psql
工具,現在是時候連線到 Postgres 資料庫了。在本地終端上執行以下命令$ docker exec -it postgres psql -h localhost -U postgres
您現在可以在
psql
提示符下執行任何您需要的 SQL 查詢或命令。使用
\q
或\quit
退出 Postgres 互動式 shell。
使用 SQL 指令碼預置 Postgres 資料庫
現在您已經熟悉了 Postgres,是時候看看如何用示例資料來預置它了。在此演示中,您將首先建立一個包含 SQL 命令的指令碼。該指令碼定義了資料庫和表結構,並插入了示例資料。然後,您將連線到資料庫以驗證資料。
假設您已經有一個正在執行的 Postgres 資料庫例項,請按照以下步驟來填充資料庫。
建立一個名為
seed.sql
的空檔案,並新增以下內容。CREATE DATABASE sampledb; \c sampledb CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(50), email VARCHAR(100) UNIQUE ); INSERT INTO users (name, email) VALUES ('Alpha', 'alpha@example.com'), ('Beta', 'beta@example.com'), ('Gamma', 'gamma@example.com');
該 SQL 指令碼建立了一個名為
sampledb
的新資料庫,連線到它,並建立了一個users
表。該表包括一個自動遞增的id
作為主鍵,一個最大長度為 50 個字元的name
欄位,以及一個最多 100 個字元的唯一email
欄位。建立表後,
INSERT
命令將三名使用者及其各自的姓名和電子郵件插入到users
表中。這個設定構成了一個用於儲存具有唯一電子郵件地址的使用者資訊的基本資料庫結構。填充資料庫。
現在是時候使用
<
運算子將seed.sql
的內容直接輸入到資料庫中了。該命令用於對名為sampledb
的 Postgres 資料庫執行名為seed.sql
的 SQL 指令碼。$ cat seed.sql | docker exec -i postgres psql -h localhost -U postgres -f-
查詢執行後,您將看到以下結果
CREATE DATABASE You are now connected to database "sampledb" as user "postgres". CREATE TABLE INSERT 0 3
執行以下
psql
命令來驗證名為 users 的表是否已在資料庫sampledb
中填充。$ docker exec -it postgres psql -h localhost -U postgres sampledb
現在您可以在
psql
shell 中執行\l
來列出 Postgres 伺服器上的所有資料庫。sampledb=# \l List of databases Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges -----------+----------+----------+------------+------------+------------+-----------------+----------------------- postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | sampledb | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | =c/postgres + | | | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | =c/postgres + | | | | | | | postgres=CTc/postgres (4 rows)
要從 users 表中檢索所有資料,請輸入以下查詢
sampledb=# SELECT * FROM users; id | name | email ----+-------+------------------- 1 | Alpha | alpha@example.com 2 | Beta | beta@example.com 3 | Gamma | gamma@example.com (3 rows)
使用
\q
或\quit
退出 Postgres 互動式 shell。
透過繫結掛載 SQL 指令碼來預置資料庫
在 Docker 中,掛載指的是讓主機系統上的檔案或目錄在容器內可訪問。這讓您可以在主機和容器之間共享資料或配置檔案,從而實現更大的靈活性和永續性。
現在您已經學會了如何啟動 Postgres 並使用 SQL 指令碼預置資料庫,是時候學習如何將 SQL 檔案直接掛載到 Postgres 容器的初始化目錄 (/docker-entrypoint-initdb.d
) 中了。/docker-entrypoint-initdb.d
是 PostgreSQL Docker 容器中的一個特殊目錄,用於在容器首次啟動時初始化資料庫。
在執行以下步驟之前,請確保停止任何正在執行的 Postgres 容器(及其卷),以防止埠衝突。
$ docker container stop postgres
修改
seed.sql
檔案,包含以下條目CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, name VARCHAR(50), email VARCHAR(100) UNIQUE ); INSERT INTO users (name, email) VALUES ('Alpha', 'alpha@example.com'), ('Beta', 'beta@example.com'), ('Gamma', 'gamma@example.com') ON CONFLICT (email) DO NOTHING;
建立一個名為
Dockerfile
的文字檔案,並複製以下內容。# syntax=docker/dockerfile:1 FROM postgres:latest COPY seed.sql /docker-entrypoint-initdb.d/
此 Dockerfile 將
seed.sql
指令碼直接複製到 PostgreSQL 容器的初始化目錄中。使用 Docker Compose。
使用 Docker Compose 可以更輕鬆地管理和部署帶有已填充資料的 PostgreSQL 容器。這個 compose.yml 檔案定義了一個名為
db
的 Postgres 服務,它使用最新的 Postgres 映象,設定了一個名為sampledb
的資料庫,以及使用者postgres
和密碼mysecretpassword
。services: db: build: context: . dockerfile: Dockerfile container_name: my_postgres_db environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: mysecretpassword POSTGRES_DB: sampledb ports: - "5432:5432" volumes: - data_sql:/var/lib/postgresql/data # Persistent data storage volumes: data_sql:
它將主機上的埠
5432
對映到容器的5432
埠,讓您可以從容器外部訪問 Postgres 資料庫。它還定義了data_sql
來持久化資料庫資料,確保在容器停止時資料不會丟失。需要注意的是,只有當您想從非容器化程式連線到資料庫時,才需要進行到主機的埠對映。如果您將連線到資料庫的服務容器化,您應該透過自定義的橋接網路連線到資料庫。
啟動 Compose 服務。
假設您已將
seed.sql
檔案放在與 Dockerfile 相同的目錄中,執行以下命令$ docker compose up -d --build
現在是時候驗證
users
表是否已填充資料了。$ docker exec -it my_postgres_db psql -h localhost -U postgres sampledb
sampledb=# SELECT * FROM users; id | name | email ----+-------+------------------- 1 | Alpha | alpha@example.com 2 | Beta | beta@example.com 3 | Gamma | gamma@example.com (3 rows) sampledb=#
使用 JavaScript 程式碼預置資料庫
現在您已經學會了如何使用各種方法(如 SQL 指令碼、掛載卷等)來填充資料庫,是時候嘗試使用 JavaScript 程式碼來實現它了。
建立一個 .env 檔案,內容如下
POSTGRES_USER=postgres POSTGRES_DB_HOST=localhost POSTGRES_DB=sampledb POSTGRES_PASSWORD=mysecretpassword POSTGRES_PORT=5432
建立一個名為 seed.js 的新 JavaScript 檔案,內容如下
以下 JavaScript 程式碼匯入了
dotenv
包,該包用於從.env
檔案中載入環境變數。.config()
方法讀取.env
檔案並將環境變數設定為process.env
物件的屬性。這讓您可以安全地將資料庫憑證等敏感資訊儲存在程式碼之外。然後,它從 pg 庫中建立一個新的 Pool 例項,該庫提供了一個用於高效資料庫互動的連線池。
seedData
函式被定義為執行資料庫填充操作。它在指令碼的末尾被呼叫以啟動填充過程。try...catch...finally 塊用於錯誤處理。require('dotenv').config(); // Load environment variables from .env file const { Pool } = require('pg'); // Create a new pool using environment variables const pool = new Pool({ user: process.env.POSTGRES_USER, host: process.env.POSTGRES_DB_HOST, database: process.env.POSTGRES_DB, port: process.env.POSTGRES_PORT, password: process.env.POSTGRES_PASSWORD, }); const seedData = async () => { try { // Drop the table if it already exists (optional) await pool.query(`DROP TABLE IF EXISTS todos;`); // Create the table with the correct structure await pool.query(` CREATE TABLE todos ( id SERIAL PRIMARY KEY, task VARCHAR(255) NOT NULL, completed BOOLEAN DEFAULT false ); ` ); // Insert seed data await pool.query(` INSERT INTO todos (task, completed) VALUES ('Watch netflix', false), ('Finish podcast', false), ('Pick up kid', false); `); console.log('Database seeded successfully!'); } catch (err) { console.error('Error seeding the database', err); } finally { pool.end(); } }; // Call the seedData function to run the script seedData();
啟動填充過程
$ node seed.js
您應該會看到以下命令
Database seeded successfully!
驗證資料庫是否已正確填充
$ docker exec -it postgres psql -h localhost -U postgres sampledb
sampledb=# SELECT * FROM todos; id | task | completed ----+----------------+----------- 1 | Watch netflix | f 2 | Finish podcast | f 3 | Pick up kid | f (3 rows)
回顧
在啟動時用模式和資料預置資料庫對於建立一個一致且真實的測試環境至關重要,這有助於在開發早期識別問題,並協調前端和後端的工作。本指南為您提供了使用各種方法(包括 SQL 指令碼、Docker 整合和 JavaScript 程式碼)實現預置的知識和實踐步驟。