Django + MySQL + Redis + Docker + Nginx 生产部署笔记

发布时间:2026/10/30 1:50:10
Django + MySQL + Redis + Docker + Nginx 生产部署笔记

适用范围

本部署方案适用于:

  • Django 后端(Gunicorn)

  • Vue 前端(打包静态资源)

  • MySQL 8.0(生产环境)

  • Redis 7(缓存 / Token / 限流)

  • Nginx(反向代理 + HTTPS)

  • Docker Compose(统一管理)

  • Linux 服务器(CentOS / Ubuntu / Debian)

一、项目目录结构

project-root/ │ ├── back_stage_management_django/ # Django 后端 │ ├── entrypoint.sh # 后端启动脚本(一次性初始化) │ ├── run_sql.py # 初始化 SQL 导入脚本 │ ├── .env.prod # 后端环境变量 │ └── ... │ ├── back-stage-management-front/ # Vue 前端 │ └── dist/ # 前端打包产物 │ └── docker_deploy/ # 部署目录(生产环境) ├── deploy.sh # Linux 一键部署脚本 ├── deploy.bat # Windows 一键部署脚本 ├── docker-compose.yml # 核心编排文件 │ ├── backend/ │ └── Dockerfile # Django 后端镜像构建文件 │ ├── frontend/ │ └── Dockerfile # Vue 前端镜像构建文件 │ └── nginx/ ├── nginx.conf # Nginx 配置(反向代理 + HTTPS) └── ssl/ # SSL 证书目录 ├── yourdomain+2.pem └── yourdomain+2-key.pem

二、后端部署(Django + Gunicorn)

1. 后端 Dockerfile

位于:

docker_deploy/backend/Dockerfile

内容:

FROM python:3.12-slim WORKDIR /app # 安装基础依赖 + MySQL 客户端 RUN apt-get update && apt-get install -y \ build-essential \ && rm -rf /var/lib/apt/lists/* # 安装 Python 依赖 COPY requirements.txt . RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt RUN pip install gunicorn # 复制 Django 项目 COPY . . # 赋予脚本执行权限 RUN chmod +x ./entrypoint.sh ENTRYPOINT ["./entrypoint.sh"]

内容解析:

1. FROM python:3.12-slim

FROM python:3.12-slim

✔ 作用

选择一个轻量级的 Python 3.12 运行环境作为基础镜像。

✔ 为什么用 slim?

  • 镜像体积小

  • 更适合生产环境

  • 更安全(攻击面更小)

Python 3.12 + PyMySQL 是当前 Django 5 的最佳组合。

2. WORKDIR /app

WORKDIR /app

✔ 作用

设置容器内的工作目录为/app。

之后所有命令都在这个目录执行。

3. 安装基础依赖

RUN apt-get update && apt-get install -y \ build-essential \ && rm -rf /var/lib/apt/lists/*

✔ 作用

安装编译工具(gcc、make 等)。

❗ 为什么需要 build-essential?

因为某些 Python 包可能需要编译(例如 cryptography、lxml 等)。

❗ 为什么没有安装 MySQL 客户端?

因为使用的是PyMySQL(纯 Python),不需要:

  • libmysqlclient-dev

  • default-mysql-client

  • pkg-config

镜像更干净、更轻量。

4. 安装 Python 依赖

COPY requirements.txt . RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt RUN pip install gunicorn

✔ 作用

  • 复制 requirements.txt

  • 安装依赖

  • 单独安装 gunicorn(你之前要求过)

✔ 使用清华源加速

非常适合国内环境。

5. 复制 Django 项目

COPY . .

✔ 作用

把整个 Django 项目复制到容器的/app目录。

6. 给 entrypoint.sh 添加执行权限

RUN chmod +x ./entrypoint.sh

✔ 作用

确保 entrypoint.sh 可以被执行。

7. 设置容器启动命令

ENTRYPOINT ["./entrypoint.sh"]

✔ 作用

容器启动时执行 entrypoint.sh。

✔ 为什么不用 CMD?

因为:

  • ENTRYPOINT 更适合“固定启动逻辑”

  • CMD 更适合“可覆盖的命令”

你这里需要固定执行 entrypoint.sh,所以 ENTRYPOINT 是正确选择。

核心功能:

  • 使用 python:3.12-slim

  • 安装依赖

  • 复制项目

  • 使用 entrypoint.sh 启动

2. entrypoint.sh(一次性初始化)

位于:

back_stage_management_django/entrypoint.sh

内容:

#!/bin/bash set -e INIT_FLAG="/app/.initialized" echo "Backend container starting..." if [ ! -f "$INIT_FLAG" ]; then echo "Running initial setup..." echo "Waiting for MySQL..." python - <<EOF import pymysql, os, time, sys host = os.getenv("MYSQL_HOST") port = int(os.getenv("MYSQL_PORT")) user = os.getenv("MYSQL_USER") password = os.getenv("MYSQL_PASSWORD") max_wait = 300 interval = 2 elapsed = 0 while elapsed < max_wait: try: conn = pymysql.connect( host=host, port=port, user=user, password=password, connect_timeout=2 ) conn.close() print("MySQL ready") sys.exit(0) except Exception: time.sleep(interval) elapsed += interval print("MySQL not ready in time") sys.exit(1) EOF echo "Applying migrations..." python manage.py migrate echo "Importing SQL data..." python run_sql.py || true echo "Collecting static files..." python manage.py collectstatic --noinput touch "$INIT_FLAG" else echo "Initialization already done. Skipping migrate & SQL import." fi echo "Starting Gunicorn..." exec gunicorn back_stage_management_django.wsgi:application \ -b 0.0.0.0:8000 \ -w 4 \ --timeout 120

功能:

  • 等待 MySQL 就绪(Python 方式)

  • 第一次启动执行:

    • migrate

    • run_sql.py(初始化数据)

    • collectstatic

  • 之后启动只运行 Gunicorn

这是整个部署的核心,避免重复初始化。

3. 后端环境变量(.env.prod)

位于:

back_stage_management_django/.env.prod

内容:

# =========================== # 基础配置(生产环境) # =========================== # 关闭 Django 调试模式(生产环境必须 False) DEBUG=False # 只允许前端域名访问后端(生产环境必须严格限制) # 示例:ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com ALLOWED_HOSTS=localhost,127.0.0.1,192.168.10.143 # 只允