Docker / Python апп containerize хийх

Python апп containerize хийх

Python аппликейшнийг Docker-т тохируулах нь Node.js-тэй төстэй боловч хэдэн онцлогтой: requirements.txt, virtual environment, болон Python-д зориулагдсан image сонголт.

FastAPI апп бэлдэх

код
myapi/
├── main.py
├── requirements.txt
└── .dockerignore

main.py

python
from fastapi import FastAPI
from datetime import datetime

app = FastAPI()

@app.get("/")
def root():
    return {"message": "Сайн уу, Docker!"}

@app.get("/health")
def health():
    return {"status": "ok", "timestamp": datetime.now().isoformat()}

requirements.txt

код
fastapi==0.110.0
uvicorn[standard]==0.27.1

.dockerignore

код
__pycache__
*.pyc
*.pyo
.env
.env.*
.git
.gitignore
venv/
.venv/
*.md
tests/

Dockerfile

dockerfile
FROM python:3.12-slim

WORKDIR /app

# Эхлээд requirements хуулна — layer cache
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
bash
docker build -t myapi .
docker run -p 8000:8000 myapi

http://localhost:8000/docs — FastAPI автоматаар Swagger UI үүсгэнэ.

Virtual environment шаардлагагүй

Ердийн Python хөгжүүлэлтэд virtual environment (venv) ашиглах нь зайлшгүй — системийн Python-той package хоорондын конфликтоос зайлсхийхийн тулд.

Container дотор Python нь тусдаа, тусгаарлагдсан орчинд ажилладаг тул venv шаардлагагүй. pip install нь шууд системийн Python-д суулгана — энэ нь зөв.

dockerfile
# ✅ Container-д шаардлагагүй
# RUN python -m venv /venv
# ENV PATH="/venv/bin:$PATH"

# ✅ Энгийнээр суулгана
RUN pip install --no-cache-dir -r requirements.txt

Multi-stage build — Python

dockerfile
# ── Stage 1: dependencies ─────────────────────
FROM python:3.12 AS builder

WORKDIR /app
COPY requirements.txt .

# --user flag: /root/.local-д суулгана
RUN pip install --user --no-cache-dir -r requirements.txt

# ── Stage 2: production ───────────────────────
FROM python:3.12-slim

WORKDIR /app

# builder stage-аас суулгасан package-уудыг хуулна
COPY --from=builder /root/.local /root/.local
COPY . .

# PATH тохируулна
ENV PATH=/root/.local/bin:$PATH

EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Flask апп — жишээ

FastAPI-г мэдэхгүй бол Flask-тай ч адилхан:

app.py

python
from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/")
def index():
    return jsonify({"message": "Сайн уу, Docker!"})

@app.route("/health")
def health():
    return jsonify({"status": "ok"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

requirements.txt

код
flask==3.0.2
gunicorn==21.2.0

Dockerfile

dockerfile
FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 5000

# Production: gunicorn ашиглана
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]

Python base image сонголт

| Image | Хэмжээ | Хэрэглэх үед | | -------------------- | ------- | ---------------------------------- | | python:3.12 | ~1 GB | Development, debugging | | python:3.12-slim | ~130 MB | Production, ихэнх апп | | python:3.12-alpine | ~55 MB | Хамгийн жижиг, C extension-гүй апп |

alpine дээр зарим C extension (numpy, pandas, psycopg2) compile хийхэд асуудал гардаг. Тиймээс slim нь ихэнх тохиолдолд тохиромжтой.

pip cache устгах

dockerfile
# ✅ Cache-г устгана — image хэмжээ багасна
RUN pip install --no-cache-dir -r requirements.txt

# ❌ Cache үлдэнэ — image томорно
RUN pip install -r requirements.txt

Development — hot reload

dockerfile
# Dockerfile.dev
FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

# --reload: файл өөрчлөгдөхөд автоматаар дахин ачаалана
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
bash
docker run -p 8000:8000 -v $(pwd):/app myapi:dev

Environment variable

python
import os

DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./test.db")
DEBUG = os.getenv("DEBUG", "false").lower() == "true"
bash
docker run -e DATABASE_URL=postgresql://... -e DEBUG=true -p 8000:8000 myapi

Дараагийн хичээлд:

PostgreSQL-ийг Docker container дотор ажиллуулах — environment variable, volume, psql холболт.