Əvvəlki mövzular hissələri ayrıca izah edirdi: Dockerfile, PostgreSQL və Redis ilə compose, gunicorn və statik fayllar və HTTPS ilə Nginx. Bu mövzu onları bir təkrarlanan buraxılış prosesində birləşdirir: mühitdən konfiqurasiya, proxy arxasında təhlükəsizlik parametrləri, WhiteNoise, çoxmərhələli image, miqrasiyaların buraxılışda bir dəfə işlədiyi compose faylı, health probları, təhlükəsiz sxem dəyişiklikləri və geri qaytarma ilə CI/CD konveyeri.
Dev-dən prod-a
| Məsələ | İnkişaf | Production |
|---|---|---|
DEBUG | True | False |
| Sirlər | settings.py-da | mühit dəyişənləri, heç vaxt image-də yox |
| Server | runserver | Nginx arxasında gunicorn |
| Statik fayllar | runserver verir | collectstatic + WhiteNoise |
| Baza | SQLite və ya lokal konteyner | adlandırılmış volume ilə PostgreSQL |
| HTTPS | yoxdur | TLS-i Nginx (və ya başqa proxy) bağlayır |
| Miqrasiyalar | əl ilə | buraxılışda bir iş |
Qərarların çoxunun arxasındakı qayda: image kodu, mühit konfiqurasiyanı, volume isə datanı saxlayır. Eyni image staging-də və production-da işləməlidir, yalnız mühit dəyişir.
Mühitdən konfiqurasiya
Mühitdən asılı bütün dəyərləri mühit dəyişənlərindən oxuyun. Çatışmayan sirr prosesi dərhal dayandırmalıdır: os.environ["NAME"] KeyError verir və production-da məhz bu lazımdır. İstəyə bağlı dəyərlər üçün kiçik köməkçilər yazın, çünki bool("False") True-dur və "0" sətri də doğru sayılır:
import os
def env_bool(name: str, default: bool = False) -> bool:
raw = os.environ.get(name, str(default))
return raw.strip().lower() in {"1", "true", "yes", "on"}
def env_list(name: str, default: str = "") -> list[str]:
raw = os.environ.get(name, default)
return [x.strip() for x in raw.split(",") if x.strip()]
os.environ["DJANGO_DEBUG"] = "0"
os.environ["DJANGO_ALLOWED_HOSTS"] = "example.com, www.example.com"
print("DEBUG =", env_bool("DJANGO_DEBUG"))
print("ALLOWED_HOSTS =", env_list("DJANGO_ALLOWED_HOSTS"))
print("USE_TLS =", env_bool("USE_TLS", True))DEBUG = False
ALLOWED_HOSTS = ['example.com', 'www.example.com']
USE_TLS = TrueParametrləri base.py, dev.py və prod.py-ə bölün (parametrlər və mühitlər); production bazanı import edib üstündən yazır:
# config/settings/prod.py
import os
import dj_database_url
from .base import * # noqa: F401,F403
from .env import env_bool, env_list
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"] # KeyError = fail fast
DEBUG = env_bool("DJANGO_DEBUG", False)
ALLOWED_HOSTS = env_list("DJANGO_ALLOWED_HOSTS")
CSRF_TRUSTED_ORIGINS = env_list("DJANGO_CSRF_TRUSTED_ORIGINS")
DATABASES = {
"default": dj_database_url.config(
conn_max_age=600, # reuse connections
conn_health_checks=True, # drop dead ones
)
}.env faylı yalnız serverdə durur (icazə 600, git-də və image-də yox) və konteynerlərə env_file ilə verilir:
# .env (on the server, chmod 600, never in git or in the image)
DJANGO_SECRET_KEY=replace-with-a-long-random-value
DJANGO_DEBUG=0
DJANGO_ALLOWED_HOSTS=shop.example.com,localhost
DJANGO_CSRF_TRUSTED_ORIGINS=https://shop.example.com
DATABASE_URL=postgres://shop:change-me@db:5432/shop
POSTGRES_USER=shop
POSTGRES_PASSWORD=change-me
POSTGRES_DB=shop⚠️ Konteynerin health check-i
http://localhost:8000/...çağırırsa,localhost-uDJANGO_ALLOWED_HOSTS-a əlavə edin; əks halda Django öz probunuza400 DisallowedHostcavab verir.