ข้ามไปยังเนื้อหา

ตั้งค่าด้วย Docker

วิธีที่เร็วที่สุดในการได้ PostgreSQL จริงมารันคือ Docker image postgres อย่างเป็นทางการ Docker จะดาวน์โหลดสำเนาฐานข้อมูลที่พร้อมใช้งาน เริ่มรันใน container ที่แยกออกมา แล้วรื้อทิ้งได้สะอาดเมื่อคุณเลิกใช้ — ไม่ต้องติดตั้งทั้งระบบ ไม่มี service หลงเหลือ บทเรียนนี้จะพาคุณจากศูนย์ไปสู่ฐานข้อมูลที่รันอยู่และเชื่อมต่อได้ด้วยคำสั่งไม่กี่บรรทัด

คุณจะต้องมี Docker ติดตั้งและรันอยู่ ทุกอย่างด้านล่างใช้คำสั่ง docker และ docker compose แบบธรรมดา

คำสั่งเดียวนี้จะ pull image หากจำเป็นและเริ่มฐานข้อมูล พร้อมตั้งรหัสผ่าน superuser, publish port มาตรฐาน และเก็บข้อมูลไว้ใน named volume เพื่อให้ข้อมูลรอดจากการ restart container

Terminal window
docker run --name pg \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
-v pgdata:/var/lib/postgresql/data \
-d postgres:17

ทัวร์สั้น ๆ เกี่ยวกับ flag ต่าง ๆ:

  • --name pg ตั้งชื่อที่จำง่ายให้ container เพื่อให้คำสั่งทีหลังอ้างชื่อนี้ได้
  • -e POSTGRES_PASSWORD=secret ตั้งรหัสผ่านสำหรับ user postgres เริ่มต้น ตัวแปรนี้บังคับ ถ้าไม่ใส่ image จะไม่ยอมเริ่มทำงาน
  • -p 5432:5432 แมป PostgreSQL port ของ container ไปยัง port เดียวกันบนเครื่องของคุณ เพื่อให้เครื่องมือบน host เชื่อมต่อกับ localhost:5432 ได้
  • -v pgdata:/var/lib/postgresql/data mount named volume ที่ directory ซึ่ง Postgres ใช้เก็บไฟล์ข้อมูล เพื่อให้ข้อมูลของคุณไม่สูญหายเมื่อ container ถูกลบ
  • -d postgres:17 รัน image อย่างเป็นทางการ tag 17 ในเบื้องหลัง

การพิมพ์คำสั่งนั้นทุกครั้งก็น่าเบื่อ และคุณมักจะอยากได้ GUI ควบคู่ไปกับฐานข้อมูล ไฟล์ docker-compose.yml เก็บการตั้งค่าทั้งหมดไว้ในไฟล์เดียวเพื่อให้คุณเริ่มทุกอย่างได้ด้วย docker compose up ไฟล์นี้รัน PostgreSQL บวกกับ pgAdmin ตัว web GUI ที่คุณจะได้ทัวร์ในบทเรียนถัดไป

services:
postgres:
image: postgres:17
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: appdb
ports:
- '5432:5432'
volumes:
- pgdata:/var/lib/postgresql/data
pgadmin:
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: [email protected]
PGADMIN_DEFAULT_PASSWORD: secret
ports:
- '8080:80'
depends_on:
- postgres
volumes:
pgdata:

บันทึกไฟล์นี้เป็น docker-compose.yml และเริ่มทุกอย่างจาก directory นั้น:

Terminal window
docker compose up -d

ตอนนี้ PostgreSQL อยู่ที่ localhost:5432 และ pgAdmin อยู่ที่ http://localhost:8080 หากคุณอยากใช้ GUI ที่เบากว่า ให้สลับ service pgadmin ด้วย image adminer ที่ให้หน้า admin แบบไฟล์เดียวบน port ของตัวเอง ไม่ว่าทางใดก็ตาม service ฐานข้อมูลไม่เปลี่ยนแปลง

container คือสำเนาที่รันอยู่ของ image, named volume คือที่ที่ไฟล์ข้อมูลจริงอยู่บนเครื่องของคุณ และ client เชื่อมต่อผ่าน port ที่ publish ไว้ volume ถูกแยกออกจาก container โดยตั้งใจเพื่อให้ข้อมูลอยู่รอดได้นานกว่า container ใด ๆ ตัวเดียว

flowchart LR
  V[(pgdata named volume)] --> P[postgres container]
  P -->|port 5432| H[Host machine]
  H --> CLI[psql or driver]
  H --> GUI[pgAdmin in browser]
container, volume และ client

ยืนยันว่า container ทำงานอยู่:

Terminal window
docker ps

คุณควรเห็น row สำหรับ image postgres ที่มีสถานะ Up และการแมป port 0.0.0.0:5432->5432/tcp ตอนนี้เชื่อมต่อด้วย psql ถ้าเครื่อง host ของคุณมี psql อยู่แล้ว ให้ชี้ไปยังฐานข้อมูลด้วย connection string:

Terminal window
psql "postgresql://postgres:secret@localhost:5432/postgres"

ไม่มี psql ในเครื่อง? image มี psql ติดมาอยู่แล้ว ดังนั้นรันจากใน container แทนได้เลย:

Terminal window
docker exec -it pg psql -U postgres

ไม่ว่าทางใดก็ตามคุณจะมาถึง prompt postgres=# พร้อมที่จะรัน SQL เมื่อคุณเสร็จงานสำหรับวันนี้ docker compose down จะหยุดทุกอย่าง เนื่องจากข้อมูลอยู่ใน volume pgdata ข้อมูลจึงยังอยู่ครบในครั้งถัดไปที่คุณเปิด stack ขึ้นมาใหม่

  • named volume คือสิ่งที่ทำให้ข้อมูลของคุณคงอยู่ ลบ container แล้วข้อมูลยังอยู่ ลบ volume แล้วข้อมูลหายไปตลอดกาล
  • 5432 คือ port เริ่มต้นของ PostgreSQL และ postgres คือ superuser เริ่มต้น เครื่องมือต่าง ๆ จะถือค่านี้เป็นค่าตั้งต้น เว้นแต่คุณจะระบุเป็นอย่างอื่น
  • POSTGRES_DB สร้างฐานข้อมูลเพิ่มเติมในการเริ่มต้นครั้งแรก ถ้าไม่ใส่ คุณก็ยังได้ฐานข้อมูล postgres ที่มีอยู่ในตัวให้ทำงานด้วย
  • POSTGRES_PASSWORD จำเป็นต้องมีสำหรับ image อย่างเป็นทางการ ใช้ secret จริงนอกการทดลองในเครื่อง ไม่ใช่ secret
  • ปักหมุดเวอร์ชันหลักอย่าง postgres:17 แทน postgres:latest เพื่อให้การอัปเดต image ไม่ทำให้คุณประหลาดใจด้วยเวอร์ชันที่ต่างออกไป
ตัวเลือกBenefitCost
รันด้วย Dockerเร็ว, disposable, ตั้งค่าเหมือนกันทุกเครื่องมี container overhead และต่างจากการ tune บน production จริงเล็กน้อย
ติดตั้ง PostgreSQL แบบ nativeใกล้เคียงสภาพแวดล้อม production มากกว่า ไม่มี layer เพิ่มติดตั้ง/ถอนยุ่งยากกว่า และต่างกันไปตามแต่ละ OS
ใช้ image default ตรง ๆเริ่มงานได้ทันที ไม่ต้องเขียนอะไรเพิ่มไม่ได้ tune เรื่อง memory หรือ config เฉพาะงาน
เขียน Dockerfile กำหนดเองปรับ config, extension ได้ตามต้องการดูแลและอัปเดต image เองเพิ่มขึ้น
  • ไม่ mount named volume แล้วข้อมูลหายตอน docker compose down -v — ถ้าไม่ผูก volume ไว้กับ data directory ข้อมูลทั้งหมดจะหายไปพร้อม container ตรวจสอบว่า volumes: ผูกไว้ถูกต้องเสมอ
  • รันเป็น superuser เริ่มต้นแม้ตอน dev ในเครื่อง — การใช้ user postgres ตลอดจะซ่อน bug เรื่อง permission ที่จะเจอจริงตอนขึ้น production ควรสร้าง role จำกัดสิทธิ์ไว้ทดสอบตั้งแต่ local
  • ไว้ใจ config แบบ POSTGRES_HOST_AUTH_METHOD=trust แล้วลืมไปว่าไม่ปลอดภัย — ค่านี้สะดวกตอน dev แต่ห้ามนำไปใช้นอกเครื่อง local เด็ดขาด เพราะเปิดให้เชื่อมต่อได้โดยไม่ต้องใช้รหัสผ่าน

💡 ตัวอย่างจากของจริง

docker-library/postgres — official image เป็นจุดเริ่มต้นมาตรฐานที่คอร์สและ tutorial ส่วนใหญ่ใช้ เพราะให้ฐานข้อมูลที่ใช้งานได้จริงในไม่กี่วินาทีโดยไม่ต้องติดตั้งอะไรบนเครื่อง

ทีม backend ทั่วไป — มาตรฐานใช้ docker-compose.yml เป็นทางเข้าโปรเจกต์ เพื่อลดปัญหา “works on my machine” ตอน onboard คนใหม่เข้าทีม

ทำไมต้อง mount named volume ที่ data directory ของ Postgres?
ตัวแปร environment ใดที่ต้องตั้งค่าเพื่อให้ image postgres อย่างเป็นทางการเริ่มต้นได้?
port เริ่มต้นของ PostgreSQL คืออะไร?