ในสถาปัตยกรรมระบบแบบแยกส่วน (Decoupled Architecture) การแยกเซอร์วิสฐานข้อมูลออกมาทำงานเป็นอิสระจากเว็บแอปพลิเคชัน (เช่น แยก WordPress ออกจาก MariaDB) ช่วยให้การบริหารจัดการข้อมูล การสำรองข้อมูล และการแชร์ฐานข้อมูลร่วมกันระหว่างหลายโปรเจกต์ทำได้อย่างมีประสิทธิภาพ บทความนี้สรุปแนวทางการสร้าง MariaDB 13 Container เป็นบริการฐานข้อมูลกลาง โดยเชื่อมต่อผ่านเครือข่าย Docker Network ชื่อ magi และซิงก์ค่าคอนฟิกร่วมกับไฟล์ .env ส่วนกลาง
1. โครงสร้างโปรเจกต์ (Project Tree)
โครงสร้างไดเรกทอรีที่ได้รับการจัดระเบียบให้ถูกต้องที่ /Users/common/Docker/ จะคงเหลือเฉพาะไฟล์และโฟลเดอร์ที่จำเป็นต่อการทำงานจริง ดังนี้:
/Users/common/Docker/
├── .env <-- ไฟล์ตัวแปรสภาพแวดล้อมส่วนกลาง
└── db_mariadb_13/
├── build.sh <-- สคริปต์เตรียมไดเรกทอรีและสร้าง init security script
├── docker-compose.yml
├── init-scripts/ <-- ไดเรกทอรี Mount ไปยัง /docker-entrypoint-initdb.d
│ └── 01-init-security.sql
└── data/ <-- Bind Mount เก็บข้อมูลดิบของ MariaDB (InnoDB & System Tables)
2. การกำหนดค่าไฟล์ .env ส่วนกลาง
ไฟล์ /Users/common/Docker/.env ใช้เป็นศูนย์กลางควบคุม Credential เพื่อให้ทุก Stack ในเครื่องอ้างอิงข้อมูลชุดเดียวกัน:
# ==========================================
# MariaDB & Application Credentials
# ==========================================
DB_ROOT_PASSWORD=your_secure_root_password
DB_DATABASE=WP71_DEV
WP_DB_NAME=WP71_DEV
DB_USER=app_user
DB_PASSWORD=your_app_password
3. การจัดเตรียมไฟล์ docker-compose.yml
ที่ตำแหน่ง db_mariadb_13/docker-compose.yml กำหนดให้ใช้งานอิมเมจ mariadb:13.0.2 พร้อมทั้งเชื่อมต่อเครือข่าย magi และแมปโฟลเดอร์ init-scripts เข้ากับ /docker-entrypoint-initdb.d แบบ Read-Only เพื่อให้รันคำสั่ง SQL ตอนเริ่มระบบรอบแรกสุด:
services:
mariadb:
image: mariadb:13.0.2
container_name: db_mariadb_13
restart: always
env_file:
- ../.env
environment:
MYSQL_ROOT_PASSWORD: '${DB_ROOT_PASSWORD}'
MYSQL_DATABASE: '${WP_DB_NAME}' # ให้ระบบสร้าง DB และผูกสิทธิ์ให้ User อัตโนมัติ
MYSQL_USER: '${DB_USER}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
ports:
- "3306:3306"
volumes:
- ./data:/var/lib/mysql
- ./init-scripts:/docker-entrypoint-initdb.d:ro
networks:
- magi # ใช้เครือข่ายวงเดียวกันกับ PHP App เพื่อให้ติดต่อกันได้โดยตรง
networks:
magi:
external: true # ดึงวงเน็ตเวิร์กกลาง 'magi' มาใช้งานร่วมกัน
4. สคริปต์ความปลอดภัยเริ่มต้น (init-scripts/01-init-security.sql)
ไฟล์นี้ทำหน้าที่กำหนดสิทธิ์และโครงสร้างผู้ใช้เริ่มต้น โดยจะสร้างผู้ดูแลระบบตัวแทน (เช่น db_admin) พร้อมสิทธิ์เทียบเท่า root และสร้างฐานข้อมูลพร้อมผู้ใช้สำหรับแอปพลิเคชัน:
-- 1. สร้าง Admin User ตัวแทน (db_admin) พร้อมสิทธิ์เทียบเท่า root
CREATE USER IF NOT EXISTS 'db_admin'@'%' IDENTIFIED BY 'your_secure_root_password';
GRANT ALL PRIVILEGES ON *.* TO 'db_admin'@'%' WITH GRANT OPTION;
-- 2. สร้าง Database และ User สำหรับแอปพลิเคชัน
CREATE DATABASE IF NOT EXISTS WP71_DEV CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'app_user'@'%' IDENTIFIED BY 'your_app_password';
GRANT ALL PRIVILEGES ON WP71_DEV.* TO 'app_user'@'%';
FLUSH PRIVILEGES;
5. สคริปต์อัตโนมัติเตรียมระบบ (build.sh)
สคริปต์ build.sh จะอ่านตัวแปรสภาพแวดล้อมจาก .env แล้วสร้างไฟล์ 01-init-security.sql ลงใน init-scripts/ ให้โดยอัตโนมัติ พร้อมตรวจความพร้อมของสิทธิ์ไดเรกทอรีและไฟล์ Compose:
#!/usr/bin/env bash
set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
cd "${SCRIPT_DIR}"
DATA_DIR="${SCRIPT_DIR}/data"
INIT_DIR="${SCRIPT_DIR}/init-scripts"
echo "==> [1/4] Preparing directories..."
mkdir -p "${DATA_DIR}" "${INIT_DIR}"
chmod 755 "${DATA_DIR}" "${INIT_DIR}"
ENV_FILE="${BASE_DIR}/.env"
if [ -f "${ENV_FILE}" ]; then
set -a
source "${ENV_FILE}"
set +a
echo "==> [2/4] Loaded environment variables from central .env"
else
echo "Error: Central .env file not found at ${ENV_FILE}" >&2
exit 1
fi
echo "==> [3/4] Generating initialization security script..."
cat << EOF > "${INIT_DIR}/01-init-security.sql"
-- 1. สร้าง Admin User ตัวแทน (db_admin) พร้อมสิทธิ์เทียบเท่า root
CREATE USER IF NOT EXISTS 'db_admin'@'%' IDENTIFIED BY '${DB_ROOT_PASSWORD}';
GRANT ALL PRIVILEGES ON *.* TO 'db_admin'@'%' WITH GRANT OPTION;
-- 2. สร้าง Database และ User สำหรับแอปพลิเคชัน
CREATE DATABASE IF NOT EXISTS ${DB_DATABASE} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${DB_USER}'@'%' IDENTIFIED BY '${DB_PASSWORD}';
GRANT ALL PRIVILEGES ON ${DB_DATABASE}.* TO '${DB_USER}'@'%';
FLUSH PRIVILEGES;
EOF
echo "==> [4/4] Checking docker-compose.yml configuration..."
if [ ! -f "${SCRIPT_DIR}/docker-compose.yml" ]; then
echo "Error: docker-compose.yml not found in ${SCRIPT_DIR}" >&2
exit 1
fi
echo "==> MariaDB build preparation completed successfully!"
6. การอ้างอิงโฮสต์ฐานข้อมูลฝั่งแอปพลิเคชัน
เมื่อโปรเจกต์ภายนอก (เช่น WordPress Stack) เข้าร่วมเครือข่าย magi จะสามารถเรียกใช้งานฐานข้อมูล MariaDB ผ่านชื่อคอนเทนเนอร์ได้โดยตรง:
DB_HOST=db_mariadb_13
DB_NAME=WP71_DEV
DB_USER=app_user
DB_PASSWORD=your_app_password
จุดเด่นของการออกแบบสถาปัตยกรรมนี้
- External Network (
magi): แยกเครือข่ายกลางเป็นอิสระ ช่วยให้คอนเทนเนอร์ในแต่ละโปรเจกต์ติดต่อกับฐานข้อมูลผ่านชื่อโฮสต์db_mariadb_13ได้ทันที - Automated Entrypoint Init: ใช้กลไกของไดเรกทอรี
/docker-entrypoint-initdb.dรันการสร้างสิทธิ์และผู้ใช้แทนการรันคำสั่งแมนนวล - Local Bind Mount (
./data): จัดเก็บไฟล์ข้อมูลฐานข้อมูลจริงไว้บนเครื่องโฮสต์ ทำให้ตรวจสอบและสำรองข้อมูลได้สะดวก - Centralized Environment (
.env): รวมศูนย์ Credential ไว้ที่จุดเดียว ป้องกันปัญหาค่าคอนฟิกไม่ตรงกันระหว่างสแต็ก
ขั้นตอนการรันระบบ
- สร้าง Docker Network
magiหากยังไม่ได้สร้างในเครื่อง:docker network create magi - ลบไฟล์ SQL ที่ตกค้างหรือไม่ได้ถูกเรียกใช้งาน (ถ้ามี):
rm -f /Users/common/Docker/db_mariadb_13/init.sql /Users/common/Docker/db_mariadb_13/init-scripts/init.sql - เข้าไปยังโฟลเดอร์ MariaDB และสั่งรันสคริปต์เตรียมระบบ:
cd /Users/common/Docker/db_mariadb_13 && ./build.sh - สั่งเริ่มการทำงานของคอนเทนเนอร์:
docker compose up -d - ตรวจสอบสถานะคอนเทนเนอร์:
docker ps
คอนเทนเนอร์db_mariadb_13จะเริ่มทำงานและพร้อมให้บริการแก่แอปพลิเคชันทุกตัวในเครือข่ายmagiทันที
อ่านเพิ่มเติม