Blog Article
آموزش گام به گام داکرایز کردن پروژه جنگو به همراه PostgreSQL و Redis
آموزش جامع و گامبهگام داکرایز کردن جنگو با Dockerfile چندمرحلهای، پیکربندی Docker Compose، دیتابیس PostgreSQL و Redis برای محیط پروداکشن و سرور لینوکس.
آموزش گام به گام داکرایز کردن جنگو به همراه PostgreSQL و Redis

جمله معروف «روی سیستم من کار میکرد، ولی روی سرور کار نمیکند» یکی از رایجترین کابوسهای توسعهدهندگان بکاند است. زمانی که پروژههای پایتونی بزرگتر میشوند و وابستگیهایی مانند دیتابیس PostgreSQL، سیستم کش Redis و صفهای تسک غیرهمگام (مانند Celery) به معماری برنامه اضافه میشوند، هماهنگ نگهداشتن محیط محلی توسعه با سرور پروداکشن به چالش بزرگی تبدیل میشود. استفاده اصولی از داکر جنگو این شکاف سنتی را برای همیشه پر میکند.
کانتینریسازی به کمک داکر (Docker) به شما امکان میدهد تا تمام بخشهای برنامه—از کدهای پایتون و وبسرور گرفته تا پایگاه داده و صف پیام—را در قالب کانتینرهای مجزا، ایزوله و تکرارپذیر بستهبندی کنید. این رویکرد زیربنای ورود به دنیای مدرن توسعه وب و دواپس است و استقرار بدون دردسر را تضمین میکند.
در این مقاله راهنمای عملی، یاد میگیرید که چگونه یک پروژه واقعی پایتون و جنگو را به همراه پایگاه داده PostgreSQL و کش/بروکر Redis به استانداردترین شکل ممکن داکرایز کنید. همچنین با نحوه نگارش Dockerfile چندمرحلهای (Multi-stage)، تنظیم فایل docker-compose.yml، مدیریت اجرای مایگریشنها و پیکربندی متغیرهای محیطی در یک سرور واقعی لینوکس آشنا خواهید شد.
چرا داکرایز کردن جنگو در اکوسیستم مدرن دواپس حیاتی است؟
داکرایز کردن صرفاً قرار دادن یک برنامه داخل کانتینر نیست؛ بلکه ایجاد یک معماری قابل اعتماد، ماژولار و مقیاسپذیر برای چرخه حیات نرمافزار است. برنامهنویسانی که تسلط کافی بر آموزش جنگو پیدا میکنند، خیلی زود متوجه نیاز شدید پروژهها به یکپارچگی زیرساخت میشوند.
۱. ایزولهسازی کامل وابستگیها
دیگر نیازی نیست نگران تداخل نسخههای پایتون روی سیستمعامل سرور، تفاوت نسخه کتابخانههای C (مانند libpq-dev برای دیتابیس) یا تفاوتهای معماری سیستم محلی با سرور باشید. کانتینر محیطی صددرصد مستقل و ایزوله را در اختیار وباپلیکیشن شما میگذارد.
۲. راهاندازی سریع محیط توسعه تیم (Onboarding)
توسعهدهنده جدید بدون نیاز به نصب دستی PostgreSQL، تنظیم دسترسی کاربران دیتابیس، نصب سرویس Redis و پیکربندی متغیرها، تنها با اجرای دستور docker compose up --build میتواند کل استک بکاند را در چند دقیقه روی ماشین خود بالا بیاورد.
۳. آمادهسازی برای پایپلاینهای CI/CD
کانتینرهای داکر خشت بنای اتوماسیون مدرن هستند. وقتی سرویس شما کانتینری باشد، پیادهسازی تست خودکار و اتوماسیون استقرار و پیادهسازی خطوط لوله CI/CD با داکر و گیتلب به سادهترین شکل ممکن پیادهسازی خواهد شد.
گام اول: ساختار پیشنهادی پروژه جنگو با داکر
برای ایجاد یک معماری تمیز و حرفهای، ساختار دایرکتوریهای پروژه خود را به شکل زیر سازماندهی کنید:
my_django_project/
├── docker/
│ ├── django/
│ │ ├── Dockerfile
│ │ └── entrypoint.sh
│ └── nginx/
│ └── default.conf
├── src/
│ ├── manage.py
│ ├── config/
│ │ ├── __init__.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ └── requirements/
│ ├── base.txt
│ └── production.txt
├── .env.example
├── .env.production
├── .dockerignore
└── docker-compose.ymlفایل .dockerignore یکی از مهمترین فایلهایی است که نباید آن را نادیده بگیرید. قرار دادن محتویات زیر در .dockerignore مانع از انتقال فایلهای اضافه و سنگین به کانتینر میشود:
__pycache__
*.pyc
*.pyo
*.pyd
.Python
env/
venv/
.venv/
.git/
.gitignore
.env
.idea/
.vscode/
media/
staticfiles/گام دوم: نوشتن Dockerfile بهینه چندمرحلهای (Multi-stage Build)
یک اشتباه رایج میان توسعهدهندگان، استفاده از ایمیجهای حجیم و کامپایل کردن کتابخانهها در ایمیج نهایی پروداکشن است. با استفاده از روش چندمرحلهای (Multi-stage)، اندازه ایمیج جنگو را به حداقل رسانده و آسیبپذیریهای امنیتی پکیجهای بیلد را از محیط نهایی حذف میکنیم.
فایل docker/django/Dockerfile را با ساختار زیر ایجاد کنید:
# ----------------------------------------------------
# Stage 1: Build & Dependency Wheel Generation
# ----------------------------------------------------
FROM python:3.12-slim-bookworm AS builder
# جلوگیری از نوشتن فایلهای .pyc و فعالسازی لاگ زنده در کنسول
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
WORKDIR /app
# نصب ابزارهای موردنیاز کامپایل C برای پکیجهایی مانند psycopg
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY src/requirements/ /app/requirements/
RUN pip install --upgrade pip \
&& pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements/production.txt
# ----------------------------------------------------
# Stage 2: Final Production Image
# ----------------------------------------------------
FROM python:3.12-slim-bookworm
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
APP_HOME=/home/app/web
WORKDIR $APP_HOME
# نصب کتابخانههای سی شارپ زمان اجرا (Runtime) و ابزار netcat برای Healthcheck
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 \
netcat-openbsd \
curl \
&& rm -rf /var/lib/apt/lists/*
# ایجاد کاربر و گروه غیر ریشه (Non-root user) جهت افزایش امنیت
RUN addgroup --system appgroup && adduser --system --group appuser
# کپی کردن پکیجهای پایتون بیلد شده از استیج اول
COPY --from=builder /app/wheels /wheels
RUN pip install --no-cache-dir /wheels/* && rm -rf /wheels
# انتقال سورسکد پروژه و اسکریپت Entrypoint
COPY src/ $APP_HOME/
COPY docker/django/entrypoint.sh /entrypoint.sh
# اصلاح دسترسی فایلها برای کاربر غیراصل
RUN sed -i 's/\r$//g' /entrypoint.sh \
&& chmod +x /entrypoint.sh \
&& mkdir -p $APP_HOME/staticfiles $APP_HOME/mediafiles \
&& chown -R appuser:appgroup $APP_HOME
USER appuser
ENTRYPOINT ["/entrypoint.sh"]
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "3", "--timeout", "120", "config.wsgi:application"]مزایای کلیدی این Dockerfile:
- استفاده از Multi-stage: کامپایلرهایی مانند
gccدر ایمیج نهایی قرار نمیگیرند؛ در نتیجه حجم ایمیج از ۷۰۰ مگابایت به کمتر از ۱۵۰ مگابایت کاهش مییابد. - کاربر Non-Root (
appuser): اجرای کانتینر با سطح دسترسی کاربر عادی مانع از اکسپلویتهای دسترسی Root در سرور لینوکس میشود. - لایه کش Wheeled: با کپی کردن مجزای requirements، داکر فرایند کش کردن لایهها را به بهترین شکل انجام میدهد.
گام سوم: نوشتن اسکریپت Entrypoint برای مدیریت دیتابیس و مهاجرتها
یک معضل رایج در راهاندازی کانتینرهای وابسته، راهاندازی سریعتر وبسرور قبل از آماده شدن دیتابیس است. با نوشتن اسکریپت docker/django/entrypoint.sh، ابتدا از در دسترس بودن کامل PostgreSQL و Redis اطمینان حاصل میکنیم و سپس دستورات اولیه را اجرا مینماییم:
#!/bin/sh
set -e
echo "در حال بررسی وضعیت اتصال به پایگاه داده PostgreSQL..."
while ! nc -z $POSTGRES_HOST $POSTGRES_PORT; do
sleep 0.5
done
echo "پایگاه داده PostgreSQL آماده پاسخگویی است!"
# اجرای دستورات الزامی در زمان آغاز کانتینر
python manage.py collectstatic --no-input --clear
# اجرای خودکار مایگریشنها در صورت فعال بودن فلگ
if [ "$AUTO_MIGRATE" = "true" ]; then
echo "در حال اعمال آخرین Migrationهای جنگو..."
python manage.py migrate --no-input
fi
exec "$@"برای تسلط بیشتر روی ابزارهای ترمینال و خط فرمان سرور جهت خطایابی این اسکریپتها، مطالعه نقشه راه تسلط بر لینوکس سرور برای برنامهنویسان بکاند پایتون دید جامعی به شما خواهد داد.
گام چهارم: پیکربندی کامل Docker Compose
برای اجرای هماهنگ کانتینرهای جنگو، دیتابیس PostgreSQL و ردیس (Redis)، از ابزار Docker Compose استفاده میکنیم. فایل docker-compose.yml در ریشه پروژه را به این شکل تنظیم کنید:
version: '3.8'
services:
postgres:
image: postgres:16-alpine
container_name: django_postgres_db
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend_network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: django_redis_cache
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
networks:
- backend_network
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
retries: 5
web:
build:
context: .
dockerfile: docker/django/Dockerfile
container_name: django_web_app
restart: unless-stopped
env_file:
- .env.production
environment:
- POSTGRES_HOST=postgres
- POSTGRES_PORT=5432
- REDIS_HOST=redis
- REDIS_PORT=6379
- AUTO_MIGRATE=true
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
ports:
- "8000:8000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- backend_network
volumes:
postgres_data:
redis_data:
static_volume:
media_volume:
networks:
backend_network:
driver: bridgeگام پنجم: پیکربندی متغیرهای محیطی و تنظیمات جنگو
در فایل src/config/settings.py پروژه جنگو، از متغیرهای سیستم برای کانفیگ دیتابیس و کش استفاده کنید. برای مدیریت تمیز متغیرها از پکیجهای مدرنی مانند django-environ یا pydantic-settings بهره ببرید.
نمونه تنظیمات دیتابیس و ردیس در settings.py:
import os
import environ
env = environ.Env(
DEBUG=(bool, False)
)
# دیتابیس PostgreSQL
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': env('POSTGRES_DB', default='djangodb'),
'USER': env('POSTGRES_USER', default='djangouser'),
'PASSWORD': env('POSTGRES_PASSWORD', default='secretpassword'),
'HOST': env('POSTGRES_HOST', default='postgres'),
'PORT': env('POSTGRES_PORT', default='5432'),
}
}
# سیستم کش و ذخیرهسازی نشستها با Redis
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": f"redis://:{env('REDIS_PASSWORD', default='')}@{env('REDIS_HOST', default='redis')}:{env('REDIS_PORT', default='6379')}/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
# مسیر فایلهای استاتیک و مدیا
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'mediafiles')فایل نمونه متغیرهای محیطی (.env.production):
DEBUG=False
SECRET_KEY=your-super-strong-and-unique-secret-key-for-production
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com,127.0.0.1,localhost
POSTGRES_DB=production_db
POSTGRES_USER=db_admin_user
POSTGRES_PASSWORD=UltraSecurePostgresPassword2026!
REDIS_PASSWORD=UltraSecureRedisPassword2026!گام ششم: اجرای سرویسها و تست عملکرد در لینوکس سرور
برای راهاندازی کل استک روی سرور، کافی است دستور زیر را در ترمینال سرور اجرا کنید:
docker compose up -d --buildدستورات پرکاربرد برای مدیریت سرویسها:
| دستور | کاربرد |
|---|---|
docker compose ps | مشاهده وضعیت سلامت و پورت کانتینرها |
docker compose logs -f web | بررسی لاگهای زنده وباپلیکیشن جنگو |
docker compose exec web python manage.py createsuperuser | ایجاد کاربر ادمین داخل کانتینر جنگو |
docker compose down -v | متوقف کردن کانتینرها همراه با حذف Volumeها (هشدار: حذف اطلاعات) |
اگر در مرحله اتصال Gunicorn به وبسرور Nginx بر روی سرورهای واقعی با ارورهای ۵۰۲ یا Permission مواجه شدید، حتماً راهنمای حل خطاهای متداول استقرار جنگو با Nginx و Gunicorn روی لینوکس سرور را مطالعه کنید.
نکات کلیدی امنیت و عملکرد در محیط پروداکشن
برای اطمینان از عملکرد بدون وقفه و افزایش امنیت سرویس در محیط لینوکس سرور، این موارد را رعایت کنید:
- محدودسازی منابع کانتینر (Resource Limits): برای جلوگیری از مصرف بیش از حد رم توسط پرسوجوهای سنگین جنگو یا نشت حافظه، در بخش
deploy.resourcesبرای هر سرویس سقف رم و پردازنده تعریف کنید. - پشتیبانگیری خودکار از دیتابیس: یک کرونجاب (Cron Job) روی سرور لینوکس تنظیم کنید تا با دستور
docker compose exec -T postgres pg_dump -U $POSTGRES_USER $POSTGRES_DBبه صورت روزانه از پایگاه داده نسخه پشتیبان بردارد. - جداسازی ترافیک در شبکه Docker: پورت دیتابیس Postgres و کش Redis را در فایل Compose به پورتهای سرور (
ports: - "5432:5432") متصل نکنید! تنها اشتراک آنها در شبکه داخلیbackend_networkکافی است تا از بیرون سرور در معرض خطر حمله قرار نگیرند.
سوالات متداول (FAQ)
آیا باید دیتابیس اصلی پروداکشن را حتماً داخل داکر اجرا کنیم؟
برای پروژههای کوچک و متوسط، داکرایز کردن PostgreSQL به همراه Volumeهای ماندگار (Named Volumes) کاملاً استاندارد و پایدار است. با این حال، در پروژههای انترپرایز با ترافیک داده بسیار سنگین، استفاده از دیتابیسهای ابری مدیریتشده (Managed Databases) یا نصب مستقل PostgreSQL مستقیم روی هاست لینوکس ترجیح داده میشود.
تفاوت استفاده از Redis به عنوان کش با Redis به عنوان واسط Celery چیست؟
ردیس میتواند به طور همزمان هر دو نقش را بازی کند. در جنگو با اختصاص دادن دیتابیس ایندکس شماره ۱ (/1) برای کش و دیتابیس شماره ۰ (/0) برای صف بروکر پیام Celery، میتوانید هر دو وظیفه را با بالاترین کارایی در یک سرور Redis کانتینری اجرا نمایید.
دستور collectstatic را کجا باید اجرا کنیم؟
بهترین جا برای جمعآوری استاتیکها، اجرای آن در زمان بیلد ایمیج یا داخل اسکریپت entrypoint.sh است تا قبل از شروع ترافیک وبسرور، تمام استایلها در ولوم اشتراکی آماده شده باشند.
جمعبندی و مراحل بعدی
داکرایز کردن پروژه جنگو به همراه دیتابیس PostgreSQL و Redis، توسعه وباپلیکیشنهای شما را به سطحی استاندارد و حرفهای ارتقا میدهد. با حذف ناسازگاریهای محیطی، مدیریت بهینه متغیرها و بهرهگیری از Dockerfile چندمرحلهای، امنیت و سرعت استقرار برنامههایتان تضمین میشود.
گام منطقی بعدی، اتصال این مجموعه به یک Reverse Proxy مانند Nginx با گواهی SSL رایگان Let's Encrypt و ساخت خط لوله Continuous Deployment است. اگر برای پیادهسازی زیرساختهای سروری، معماری اختصاصی بکاند یا مشاوره مهاجرت به کلود به راهکاری مطمئن نیاز دارید، میتوانید از طریق بخش تماس و همکاری با Arcory با من در ارتباط باشید.