การจัดการสภาพแวดล้อมด้วย Docker และการใช้ Modern Python Tools (uv)
ทำไมโค้ดรันได้ที่เครื่องเรา แต่พังเมื่อไปรันที่เครื่องเพื่อนหรือ Server?
"ห่อ" (Package) ทุกอย่างที่แอปพลิเคชันต้องใช้รวมไปด้วยกันเลย นั่นคือที่มาของ Container
เทคโนโลยีที่ช่วยให้เราสามารถรันแอปพลิเคชันในสภาพแวดล้อมที่แยกขาดจากกัน (Isolated) โดยใช้ทรัพยากรของ OS ร่วมกัน
หนัก (GBs), Boot ช้า, เปลืองทรัพยากรเพราะต้องจำลอง Hardware และ OS
เบา (MBs), Boot เร็วมาก, ใช้ Kernel ร่วมกับ Host OS
แพลตฟอร์ม Open Source ยอดนิยมที่สุดสำหรับการสร้าง (Build), ส่งมอบ (Ship), และรัน (Run) แอปพลิเคชันในรูปแบบ Container
"Docker ช่วยให้นักพัฒนาแพ็คแอปฯ และ Dependencies ทั้งหมดใส่กล่องเดียว แล้วเอาไปรันที่ไหนก็ได้"
Client-Server Architecture
เครื่องมือที่เราใช้สั่งงาน (CLI) เช่นคำสั่ง docker build, docker run
ตัวทำงานเบื้องหลัง (dockerd) ทำหน้าที่สร้าง, รัน, และจัดการ Container
ที่เก็บ Image (เช่น Docker Hub) เหมือน GitHub แต่เก็บ Docker Image
DockerfileDockerfile → Image
Upload to Registry
Image → Container
An extremely fast Python package installer and resolver, written in Rust.
# สร้าง Project ใหม่
$ uv init my-project
# เพิ่ม Package
$ uv add django
# รันคำสั่ง
$ uv run manage.py runserver
ไฟล์ Text ที่บรรจุชุดคำสั่งสำหรับสร้าง Docker Image
FROM python:3.13-slim
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Docker จะอ่านบรรทัดเหล่านี้จากบนลงล่างเพื่อสร้าง Image Layer
กำหนด Base Image ที่จะใช้เป็นรากฐาน
FROM python:3.13-slim
กำหนด Directory ทำงานภายใน Container (เหมือน cd เข้าไป)
WORKDIR /app
คัดลอกไฟล์จากเครื่องเรา (Host) เข้าไปใน Image
# Copy ไฟล์ requirements.txt เข้าไปก่อน
COPY requirements.txt .
# Copy โค้ดทั้งหมด (. คือ current dir) เข้าไปใน workdir
COPY . .
💡 Tip: ควร Copy ไฟล์ requirements ก่อน code เพื่อใช้ประโยชน์จาก Docker Cache
รันคำสั่ง Linux ในขณะที่กำลัง สร้าง (Build) Image
มักใช้สำหรับติดตั้ง Package หรือ Setup Environment
RUN pip install --no-cache-dir -r requirements.txt
# หรือถ้าใช้ uv
RUN uv sync
คำสั่งที่จะรันเมื่อ เริ่ม (Start) Container
ต่างจาก RUN ตรงที่ CMD ทำงานตอน Run time, RUN ทำงานตอน Build time
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
⚠️ Dockerfile ควรมี CMD เดียว (ถ้ามีหลายอัน อันสุดท้ายจะถูกใช้)
เปลี่ยน Dockerfile ให้กลายเป็น Image
# รูปแบบ
$ docker build -t <name>:<tag> <path>
# ตัวอย่าง
$ docker build -t mysite:v1 .
-t : ตั้งชื่อ Tag ให้ Image (Naming). : ตำแหน่งของ Dockerfile (Current Directory)นำ Image มาสร้างเป็น Process ที่ใช้งานได้จริง
$ docker run -d -p 8080:8000 --name myapp mysite:v1
docker ps
ดู Container ที่กำลังรันอยู่
docker ps -a
ดู Container ทั้งหมด (รวมที่หยุดไปแล้ว)
docker stop <id>
หยุด Container
docker rm <id>
ลบ Container
docker images
ดู Image ทั้งหมดในเครื่อง
การตั้งค่า Configuration โดยไม่ต้องแก้โค้ด (เช่น SECRET_KEY, DEBUG Mode)
# ใช้ flag -e
$ docker run -e DEBUG=False -e SECRET_KEY=1234 mysite:v1
เพื่อความปลอดภัย (Security) และความยืดหยุ่น (Flexibility) ทำให้ Image เดียวกัน รันได้ทั้ง Dev, Staging, และ Production แค่เปลี่ยน Env Vars
อย่าลืมไฟล์นี้! สำคัญเหมือน .gitignore
ใช้ระบุไฟล์ที่ไม่ต้องการ Copy เข้าไปใน Image เพื่อ:
# .dockerignore
__pycache__
*.pyc
.git
.env
venv/
.venv/
การรวมพลังของ Docker และ uv
uv ติดตั้ง dependencies ได้เร็วกว่า pip มาก ทำให้ระยะเวลา build docker ลดลง
จัดการ Virtualenv ได้ดี และมี Cache management ที่มีประสิทธิภาพ
uv.lock file ช่วยให้มั่นใจว่า Dependencies ใน Container ตรงกับที่เครื่อง Dev เป๊ะๆ
หมายเหตุ: PythonAnywhere ไม่รองรับ Docker Custom Image ในแพ็คเกจฟรี เราจะใช้ uv เพื่อจัดการ Environment และ Deploy แบบ Traditional
สร้างโปรเจกต์ Django ด้วย uv, ทดลอง Dockerize, และ Deploy จริงบน Cloud
เปิด Terminal ใน VS Code แล้วทำตามขั้นตอน
# 1. ติดตั้ง uv (ถ้ายังไม่มี)
pip install uv
# 2. สร้างโปรเจกต์ใหม่
uv init week3_lab
cd week3_lab
# 3. เพิ่ม Django (uv จะสร้าง venv ให้เอง)
uv add django
# 1. สร้าง Django Project ชื่อ mysite
uv run django-admin startproject mysite .
*อย่าลืมจุด (.) ข้างหลัง เพื่อสร้างใน folder ปัจจุบัน
# 2. ทดลองรัน (Local)
uv run manage.py migrate
uv run manage.py runserver
ตรวจสอบที่ http://127.0.0.1:8000 ว่าเว็บขึ้นหรือไม่
สร้างไฟล์ชื่อ Dockerfile (ไม่มีนามสกุล) ในโฟลเดอร์หลัก:
FROM python:3.12-slim
# ติดตั้ง uv ใน image
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
WORKDIR /app
# Copy ไฟล์ config ของ uv
COPY pyproject.toml uv.lock ./
# Install dependencies
RUN uv sync --frozen
# Copy โค้ด
COPY . .
# รัน server
CMD ["uv", "run", "manage.py", "runserver", "0.0.0.0:8000"]
# 1. Build Image
docker build -t django-uv-lab .
# 2. Run Container
docker run -p 8000:8000 django-uv-lab
✅ ถ้าเข้า localhost:8000 ได้ แสดงว่า Docker ทำงานถูกต้อง
กด Ctrl+C ใน terminal เพื่อหยุด Container
PythonAnywhere ไม่รองรับ Docker (Free Tier) เราต้อง Export requirements เพื่อไปใช้กับ pip แบบดั้งเดิม
# 1. Export requirements.txt ด้วย uv
uv export > requirements.txt
# 2. แก้ไข mysite/settings.py
ALLOWED_HOSTS = ['*'] # หรือใส่ชื่อ domain ของ pythonanywhere
# 3. Push ขึ้น GitHub (Repo ใหม่)
git init
git add .
git commit -m "Ready for deploy"
git push ...
git clone https://github.com/User/Repo.git
mkvirtualenv --python=/usr/bin/python3.10 myenv
pip install -r requirements.txt
/home/username/repo_name/home/username/.virtualenvs/myenvmysite.settingsPodman คือ Container Engine แบบ Open Source ที่ไม่มี Daemon (Daemonless) และเน้นความปลอดภัย
ใช้ CLI ส่งคำสั่งไปหา Docker Daemon (dockerd) ที่รันเป็น Background Process ด้วยสิทธิ์ Root
⚠️ ถ้า Daemon ล่ม Container ทั้งหมดจะดับไปด้วย [10]
ทำงานแบบ Process ปกติของ Linux (Direct Process) ไม่ต้องผ่าน Daemon ตัวกลาง
✅ ปลอดภัยกว่า และแยกการทำงานอิสระต่อกัน [11]
เครื่องมือจัดการ Container แบบ GUI (Graphical User Interface) ที่ใช้งานฟรีและ Open Source
ทางเลือกทดแทน Docker Desktop (ที่เริ่มมีการคิดค่าบริการสำหรับองค์กรขนาดใหญ่) [12]
รองรับ Windows, macOS, Linux
brew install podman-desktop หรือโหลด dmg file"แทบไม่ต้องเปลี่ยนอะไรเลย"
# สร้าง Alias เพื่อใช้คำสั่ง docker เหมือนเดิม [15]
$ alias docker=podman
# คำสั่งใช้งานเหมือนกัน 99%
$ docker run -d -p 80:80 nginx
➔ $ podman run -d -p 80:80 nginx
podman-compose ทดแทน หรือใช้ฟีเจอร์ Pods ของ Podman [17]
Podman สามารถจัดการ "Pod" ได้เหมือน Kubernetes (ซึ่ง Docker ปกติทำไม่ได้)
Container ใน Pod เดียวกัน คุยกันผ่าน localhost ได้เลย!
# สร้าง Pod ว่างๆ
$ podman pod create --name my-pod -p 8080:80
# รัน Container เข้าไปใน Pod นั้น
$ podman run -dt --pod my-pod nginx
docker.io/library/httpd [18]*หมายเหตุ: บน Windows การรัน Podman ครั้งแรกอาจใช้เวลาสักพักในการสร้าง WSL2 VM