deploymentoverview
deploymentDjangoapplication is 将Developmentenvironmentincreation application转移 to produceenvironment, 使其able to被user访问 过程. deployment过程涉及 many 个方面, includingserverconfiguration, Webserver设置, datalibraryconfiguration, 静态fileprocessing, security性configurationetc..
Djangoapplication deploymentarchitecture通常including以 under component:
- Webserver: such asNginx, Apache, 负责processing静态file and 反向proxyrequest.
- applicationserver: such asGunicorn, uWSGI, 负责runDjangoapplication.
- datalibraryserver: such asPostgreSQL, MySQL, storeapplicationdata.
- cacheserver: such asRedis, Memcached, improvingapplicationperformance.
- monitortool: such asPrometheus, Grafana, monitorapplicationrunstatus.
提示
Developmentenvironment and produceenvironment应该保持一致, includingPythonversion, 依赖libraryversion, datalibraryclass型etc.. 可以using虚拟environment and Docker来implementationenvironment consistency.
deployment before 准备工作
in deploymentDjangoapplication之 before , 需要completion以 under 准备工作:
1. 设置DEBUG for False
in produceenvironmentin, 必须将DEBUG设置 for False, 否则会暴露敏感information:
# settings.py
DEBUG = False
# 允许 主机list, using通配符*表示允许所 has 主机访问, 但不推荐 in produceenvironmentinusing
ALLOWED_HOSTS = ['example.com', 'www.example.com', '192.168.1.100']
2. configuration静态file
configuration静态file 收集Table of Contents:
# settings.py
# 静态fileURL
STATIC_URL = '/static/'
# 静态file收集Table of Contents, 用于produceenvironment
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# 媒体fileURL
MEDIA_URL = '/media/'
# 媒体filestoreTable of Contents
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
3. configurationdatalibrary
in produceenvironmentin, 推荐usingPostgreSQL or MySQLetc.relationships型datalibrary, 而不 is SQLite:
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
4. installation依赖library
usingpip freezecommands生成依赖librarylist, 然 after in produceenvironmentininstallation:
# 生成依赖librarylist
pip freeze > requirements.txt
# in produceenvironmentininstallation依赖library
pip install -r requirements.txt
5. 收集静态file
usingcollectstaticcommands收集静态file to STATIC_ROOTTable of Contents:
python manage.py collectstatic
6. 执行datalibrarymigration
in produceenvironmentin执行datalibrarymigration:
python manage.py migrate
7. creation超级user
creation用于loginmanagement界面 超级user:
python manage.py createsuperuser
deployment选项
has many 种方式可以deploymentDjangoapplication, 以 under is 一些常用 deployment选项:
1. Nginx + Gunicorn
Nginx is a high performance Webserver, 负责processing静态file and 反向proxyrequest; Gunicorn is a Python WSGI HTTPserver, 负责runDjangoapplication.
installationGunicorn
pip install gunicorn
usingGunicornrunDjangoapplication
gunicorn mysite.wsgi:application --bind 0.0.0.0:8000
configurationNginx
creationNginxconfigurationfile:
# /etc/nginx/sites-available/example.com
server {
listen 80;
server_name example.com www.example.com;
# 静态fileconfiguration
location /static/ {
alias /path/to/your/project/staticfiles/;
}
# 媒体fileconfiguration
location /media/ {
alias /path/to/your/project/media/;
}
# 反向proxyconfiguration
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
启用Nginxconfiguration:
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t # testconfigurationfile
nginx -s reload # 重 new 加载Nginxconfiguration
2. Nginx + uWSGI
uWSGI is 另一个常用 Python WSGI HTTPserver, and Nginx配合using效果良 good .
installationuWSGI
pip install uwsgi
configurationuWSGI
creationuWSGIconfigurationfile:
# uwsgi.ini
[uwsgi]
# projectTable of Contents
chdir = /path/to/your/project
# WSGImodulepath
module = mysite.wsgi:application
# Python虚拟environmentpath
home = /path/to/your/virtualenv
# process数
processes = 4
# thread数
threads = 2
# uWSGI监听 端口
socket = 127.0.0.1:8000
# 启用主process
master = true
# processIDfile
pidfile = /tmp/project-master.pid
# logfile
daemonize = /var/log/uwsgi/project.log
# 静态filemap
static-map = /static=/path/to/your/project/staticfiles
启动uWSGI
uwsgi --ini uwsgi.ini
configurationNginx
Nginxconfiguration and Gunicornclass似, 只需将proxy_pass改 for uwsgi_pass:
# /etc/nginx/sites-available/example.com
server {
listen 80;
server_name example.com www.example.com;
# 静态fileconfiguration
location /static/ {
alias /path/to/your/project/staticfiles/;
}
# 媒体fileconfiguration
location /media/ {
alias /path/to/your/project/media/;
}
# uWSGIconfiguration
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8000;
}
}
3. Dockerdeployment
usingDocker可以implementationapplication containerizationdeployment, improvingdeployment consistency and portability.
creationDockerfile
# Dockerfile
FROM python:3.10
# 设置工作Table of Contents
WORKDIR /app
# copyrequirements.txtfile
COPY requirements.txt .
# installation依赖library
RUN pip install --no-cache-dir -r requirements.txt
# copyprojectfile
COPY . .
# 收集静态file
RUN python manage.py collectstatic --noinput
# 执行datalibrarymigration
RUN python manage.py migrate
# 暴露端口
EXPOSE 8000
# 启动application
CMD ["gunicorn", "mysite.wsgi:application", "--bind", "0.0.0.0:8000"]
creationdocker-compose.ymlfile
# docker-compose.yml
version: '3'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DEBUG=False
- SECRET_KEY=your-secret-key
- DATABASE_URL=postgresql://postgres:postgres@db:5432/mydatabase
depends_on:
- db
volumes:
- ./staticfiles:/app/staticfiles
- ./media:/app/media
db:
image: postgres:14
environment:
- POSTGRES_DB=mydatabase
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
volumes:
- postgres_data:/var/lib/postgresql/data/
volumes:
postgres_data:
构建 and runDockercontainers
# 构建Docker镜像
docker-compose build
# runDockercontainers
docker-compose up -d
4. 云平台deployment
可以using各种云平台来deploymentDjangoapplication, such as:
- Heroku: providing了 simple deployment流程, supportautomationdeployment.
- AWS: providing了 many 种deployment选项, such asElastic Beanstalk, EC2+RDSetc..
- Google Cloud Platform: providing了App Engine, Compute Engineetc.deployment选项.
- Microsoft Azure: providing了App Serviceetc.deployment选项.
静态fileprocessing
in produceenvironmentin, Django不会自动processing静态file, 需要usingWebserver来processing.
1. 收集静态file
usingcollectstaticcommands将所 has application 静态file收集 to 一个Table of Contents:
python manage.py collectstatic
2. configurationWebserver
configurationWebserver (such asNginx, Apache) 来processing静态filerequest:
Nginxconfiguration
location /static/ {
alias /path/to/your/project/staticfiles/;
expires 30d; # 设置静态filecache时间
access_log off; # 关闭静态file访问log
}
Apacheconfiguration
Alias /static/ /path/to/your/project/staticfiles/
<Directory /path/to/your/project/staticfiles/>
Require all granted
Options -Indexes
</Directory>
3. usingCDN
for 于 big 型application, 可以usingCDN ( in 容分发network) 来加速静态file 访问:
# settings.py
# usingCDN 静态fileURL
STATIC_URL = 'https://cdn.example.com/static/'
# 本地静态file收集Table of Contents
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
datalibraryconfiguration
in produceenvironmentin, 推荐usingPostgreSQL or MySQLetc.relationships型datalibrary, 而不 is SQLite.
PostgreSQLconfiguration
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'mydatabase'),
'USER': os.environ.get('DB_USER', 'mydatabaseuser'),
'PASSWORD': os.environ.get('DB_PASSWORD', 'mypassword'),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
'OPTIONS': {
'sslmode': 'require', # 启用SSL连接
},
}
}
MySQLconfiguration
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ.get('DB_NAME', 'mydatabase'),
'USER': os.environ.get('DB_USER', 'mydatabaseuser'),
'PASSWORD': os.environ.get('DB_PASSWORD', 'mypassword'),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '3306'),
'OPTIONS': {
'charset': 'utf8mb4', # supportemoji
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
},
}
}
datalibraryoptimization
- using连接池: such aspgBouncer (PostgreSQL) , ProxySQL (MySQL) , improvingdatalibrary连接efficiency.
- creationindex: for 频繁query 字段creationindex, improvingquery速度.
- 定期backup: 设置定期backup策略, 防止dataloss.
- monitordatalibrary: usingmonitortoolmonitordatalibraryperformance and status.
environmentvariableconfiguration
in produceenvironmentin, 应该usingenvironmentvariable来store敏感information, such asdatalibrarypassword, SECRET_KEYetc., 而不 is 硬编码 in configurationfilein.
usingpython-decouple
python-decouple is a 用于managementenvironmentvariable library, 可以将configuration and code分离:
installationpython-decouple
pip install python-decouple
creation.envfile
# .env
DEBUG=False
SECRET_KEY=your-secret-key-here
ALLOWED_HOSTS=example.com,www.example.com
DB_NAME=mydatabase
DB_USER=mydatabaseuser
DB_PASSWORD=mypassword
DB_HOST=localhost
DB_PORT=5432
in settings.pyinusingenvironmentvariable
# settings.py
from decouple import config
DEBUG = config('DEBUG', default=False, cast=bool)
SECRET_KEY = config('SECRET_KEY')
ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=lambda v: [s.strip() for s in v.split(',')])
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': config('DB_NAME'),
'USER': config('DB_USER'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST'),
'PORT': config('DB_PORT'),
}
}
warning
不要将.envfilesubmitting to version控制systemin, 应该将其添加 to .gitignorefilein.
security性configuration
produceenvironmentin security性configuration非常 important , 可以防止各种攻击, such asSQL注入, 跨站脚本攻击, 跨站request伪造etc..
1. 设置强SECRET_KEY
SECRET_KEY用于encryptionsessiondata, passwordresettokenetc., 必须设置 for 强随机string:
# 生成强SECRET_KEY
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
# settings.py
SECRET_KEY = config('SECRET_KEY')
2. 启用HTTPS
in produceenvironmentin, 必须启用HTTPS, 防止data in 传输过程in被窃取:
- usingLet's Encrypt免费SSLcertificate.
- configurationWebserver强制HTTPS重定向.
- 设置
SECURE_SSL_REDIRECT = True.
3. configurationsecurity头
设置各种security头, improvingapplication security性:
# settings.py
# 强制HTTPS重定向
SECURE_SSL_REDIRECT = True
# HSTSconfiguration, 告诉浏览器始终usingHTTPS访问
SECURE_HSTS_SECONDS = 31536000 # 1年
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
# 防止点击劫持攻击
X_FRAME_OPTIONS = 'DENY'
# 防止XSS攻击
SECURE_BROWSER_XSS_FILTER = True
# 防止MIMEclass型嗅探
SECURE_CONTENT_TYPE_NOSNIFF = True
4. configurationCSRF保护
确保CSRF保护已启用:
# settings.py
MIDDLEWARE = [
# otherin间件...
'django.middleware.csrf.CsrfViewMiddleware',
# otherin间件...
]
5. 限制management员访问
限制management界面 访问, 只允许specificIP访问:
Nginxconfiguration
location /admin/ {
allow 192.168.1.100;
deny all;
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
logprocessing
in produceenvironmentin, 必须configurationlogprocessing, 以便及时发现 and 解决issues:
# settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
'simple': {
'format': '{levelname} {message}',
'style': '{',
},
},
'filters': {
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'file': {
'level': 'INFO',
'class': 'logging.Fileprocessingr',
'filename': '/var/log/django/debug.log',
'formatter': 'verbose',
},
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.Streamprocessingr',
'formatter': 'simple',
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailprocessingr',
'formatter': 'verbose',
},
},
'loggers': {
'django': {
'handlers': ['file', 'console'],
'propagate': True,
},
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'blog': {
'handlers': ['file'],
'level': 'INFO',
'propagate': True,
},
},
}
monitor and maintenance
deployment after , 需要定期monitor and maintenanceapplication, 确保其正常run:
1. monitortool
- Prometheus + Grafana: monitorapplication CPU, memory, diskusingcircumstances, 以及requestresponse时间etc..
- New Relic: providingapplicationperformancemonitor, error跟踪etc.functions.
- Sentry: 实时error跟踪 and monitor.
- ELK Stack: 收集, store and analysislog.
2. 定期maintenance
- update依赖library: 定期update依赖library, 修复security漏洞.
- backupdatalibrary: 定期backupdatalibrary, 防止dataloss.
- cleanlog: 定期cleanlogfile, 防止disk空间不足.
- optimizationdatalibrary: 定期optimizationdatalibrary, such as重建index, clean无用dataetc..
3. automationdeployment
usingautomationdeploymenttool, such asJenkins, GitLab CI/CD, GitHub Actionsetc., 可以简化deployment流程, improvingdeploymentefficiency:
GitHub Actionsexample
# .github/workflows/deploy.yml
name: deployment Django App
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
run: python manage.py test
- name: Collect static files
run: python manage.py collectstatic --noinput
- name: deployment to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.SERVER_PASSWORD }}
script: |
cd /path/to/project
git pull origin main
pip install -r requirements.txt
python manage.py migrate
python manage.py collectstatic --noinput
systemctl restart gunicorn
systemctl restart nginx
练习 1: 准备deploymentenvironment
- creation一个 new Djangoproject.
- 设置DEBUG for False, configurationALLOWED_HOSTS.
- configuration静态file收集Table of Contents.
- 生成requirements.txtfile.
- creation.envfile, store敏感information.
- usingpython-decouple in settings.pyin加载environmentvariable.
练习 2: usingNginx+GunicorndeploymentDjangoapplication
- installationGunicorn and Nginx.
- usingGunicornrunDjangoapplication.
- configurationNginx反向proxy and 静态fileprocessing.
- testapplication is 否可以正常访问.
练习 3: usingDockerdeploymentDjangoapplication
- creationDockerfile.
- creationdocker-compose.ymlfile, package含Djangoapplication and PostgreSQLdatalibrary.
- 构建并runDockercontainers.
- testapplication is 否可以正常访问.