Skip to content

39 - Docker และ Docker Compose

บทนี้จะเพิ่ม Dockerfile และ Docker Compose เพื่อรัน Backend API กับ PostgreSQL ใน environment ที่ทำซ้ำได้

หลังจบบทนี้ผู้อ่านควรเข้าใจ:

  • Dockerfile ใช้ทำอะไร
  • Docker Compose ใช้รันหลาย service อย่างไร
  • ทำไมใน container ต้องใช้ host postgres ไม่ใช่ localhost
  • ส่ง environment variables เข้า container อย่างไร
  • ใช้ healthcheck และ depends_on อย่างไร

สร้างไฟล์:

Dockerfile
FROM eclipse-temurin:25-jre
WORKDIR /app
COPY build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

ก่อน build image ต้อง build jar:

Terminal window
.\gradlew.bat clean build
services:
postgres:
image: postgres:18
container_name: backend-postgres
environment:
POSTGRES_DB: secure_admin
POSTGRES_USER: postgres
POSTGRES_PASSWORD: admin123
ports:
- "5432:5432"
volumes:
- postgres-data:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d secure_admin"]
interval: 5s
timeout: 5s
retries: 10
api:
build: .
container_name: backend-api
environment:
SPRING_PROFILES_ACTIVE: prod
DB_URL: jdbc:postgresql://postgres:5432/secure_admin
DB_USERNAME: postgres
DB_PASSWORD: admin123
JWT_SECRET: 0123456789012345678901234567890123456789012345678901234567890123
ports:
- "8080:8080"
depends_on:
postgres:
condition: service_healthy
volumes:
postgres-data:

สำหรับ postgres:18 ขึ้นไป ให้ mount volume ที่ /var/lib/postgresql ไม่ใช่ /var/lib/postgresql/data เพราะ image รุ่นใหม่จัดเก็บ data directory แบบแยกตาม major version ภายใน path นี้ ถ้าใช้ path เก่า container อาจ start ไม่ขึ้นและแจ้งว่า data อยู่ใน unused mount/volume

ในเครื่องเรา PostgreSQL อาจอยู่ที่:

localhost:5432

แต่ใน Docker Compose service api ต้องต่อไปที่:

postgres:5432

เพราะ localhost ภายใน container หมายถึง container ตัวเอง ไม่ใช่ service PostgreSQL

build jar:

Terminal window
.\gradlew.bat clean build

รัน compose:

Terminal window
docker compose up --build

หยุด:

Terminal window
docker compose down

ลบ volume database:

Terminal window
docker compose down -v

ใช้ -v ด้วยความระวัง เพราะข้อมูล PostgreSQL จะหาย

ไม่ควร commit secret จริง

Section titled “ไม่ควร commit secret จริง”

ตัวอย่างนี้ใส่ password เพื่อการเรียน แต่ในงานจริงควรใช้ .env หรือ secret manager

ตัวอย่าง .env:

DB_PASSWORD=change-me
JWT_SECRET=change-me-to-long-random-secret

แล้ว compose อ่าน:

DB_PASSWORD: ${DB_PASSWORD}
JWT_SECRET: ${JWT_SECRET}

แบบฝึกหัดท้ายบท

Section titled “แบบฝึกหัดท้ายบท”
  1. สร้าง Dockerfile
  2. สร้าง docker-compose.yml
  3. build jar
  4. รัน docker compose up --build
  5. เรียก /swagger-ui/index.html
  6. ลองเปลี่ยน DB_URL เป็น localhost แล้วดู error จากนั้นเปลี่ยนกลับเป็น postgres