☰
DjangoBlog Docker 部署全攻略:docker-compose 一键编排、独立镜像运行与环境变量深度解析
2026/9/28 8:38:23 网站建设 项目流程
  • 后端
  • 前端
  • CMS

【免费下载链接】DjangoBlog

🍺基于Django的博客系统

项目地址:https://gitcode.com/gh_mirrors/dj/DjangoBlog
点击查看免费下载

本文以 DjangoBlog 官方的 Docker 部署文档(docs/docker-en.md)为主线,结合仓库内的 Dockerfile、docker-compose 配置、启动脚本 与 settings.py 源码,系统讲解如何用 Docker 在几分钟内完成博客的容器化部署。读完本文,你将掌握三种部署路径(docker-compose 一键部署、叠加 Elasticsearch 全文检索、独立镜像对接外部 MySQL),并彻底搞懂每一个DJANGO_*环境变量在源码层面如何生效,从而安全、正确地完成生产环境配置。

1. 部署前置条件

在开始之前,请确保本机已安装以下两样软件:

  • Docker Engine:容器运行时,负责拉取镜像、构建镜像并运行容器;
  • Docker Compose:容器编排工具,负责按docker-compose.yml一次性拉起多服务栈。Docker Desktop(macOS / Windows)用户无需单独安装,已内置 Compose。

兼容性提示:本文所有命令均基于文档撰写时的 Compose V1 语法(version: '3'、docker-compose子命令)与当前仓库中的 docker-compose 文件 实测结构;若你的环境使用 Compose V2,可将docker-compose替换为docker compose。

2. 推荐方式:docker-compose 一键部署基础服务栈

官方推荐使用docker-compose一键启动"应用 + 数据库 + 缓存 + 反向代理"的完整服务栈,它会自动完成镜像拉取、项目镜像构建与多容器编排,是上手最快、最省心的部署方式。

2.1 关于 compose 文件位置的说明

原文档中写明"在项目根目录执行docker-compose up -d --build",即假定根目录存在docker-compose.yml。在当前仓库快照中,两个 compose 文件均位于deploy/docker-compose/目录下(经仓库文件检索确认仅有这两份)。因此若从仓库根目录执行,请通过-f显式指定文件路径:

docker-compose -f deploy/docker-compose/docker-compose.yml up -d --build

如果你将项目发布到服务器时习惯把 compose 文件放到根目录,也可以保持原文档的直接写法;二者的服务定义完全相同,只是文件位置不同。

2.2 服务栈拆解:这份 compose 到底编排了哪些容器

打开 deploy/docker-compose/docker-compose.yml 可以看到,基础栈共编排了 4 个服务:

服务名镜像职责端口映射关键配置
dbmysql:latest博客数据库3306:3306自动建库djangoblog,根密码QQQQwww123!@#,数据卷mysql_data:/var/lib/mysql
redisredis:latest缓存服务6379:6379无密码,供DJANGO_REDIS_URL=redis:6379连接
djangoblog本地构建(build: ../..)Django 应用8000:8000启动命令执行 entrypoint.sh,挂载静态文件卷、日志与上传目录
nginxnginx:latest反向代理 + 静态文件80:80、443:443挂载 deploy/nginx.conf,以只读方式共享静态文件卷

几个值得注意的实现细节:

  • 应用镜像来自本地构建:djangoblog服务的build.context指向../../(仓库根目录),dockerfile指定根目录的 Dockerfile,因此--build会先构建应用镜像;
  • 静态文件通过 named volume 共享:static_files:/code/djangoblog/collectedstatic(djangoblog 容器可写、nginx 容器以:ro只读挂载),这是 nginx 直接服务静态资源、Django 只处理动态请求的基础;
  • 服务依赖关系:djangoblog依赖db,db又依赖redis,保证了启动顺序。

2.3 启动命令与访问方式

# 构建并以后台模式启动容器(包含 Django 应用、MySQL、Redis、Nginx) docker-compose -f deploy/docker-compose/docker-compose.yml up -d --build
  • 访问博客:启动完成后,浏览器打开http://127.0.0.1(Nginx 监听 80 端口并转发给容器内的 8000 端口);
  • 数据持久化:原文档描述为"MySQL 数据存放在项目根目录的data/mysql中"。在当前仓库的 compose 文件中,db服务实际使用的是 Docker named volumemysql_data(挂载点为容器内/var/lib/mysql),数据同样在容器重启后不会丢失,且更便于用docker volume管理。若你确实想用宿主机目录,把该卷改成./data/mysql:/var/lib/mysql即可。

2.4 (可选) 叠加 Elasticsearch 启用全文搜索

默认情况下,DjangoBlog 使用 Whoosh 作为本地全文检索后端;如果你希望获得更强的全文搜索能力,可以在基础栈之上叠加 ES 覆盖文件:

docker-compose -f deploy/docker-compose/docker-compose.yml \ -f deploy/docker-compose/docker-compose.es.yml up -d --build

-f可以多次使用,Compose 会将两个文件合并编排。查看 deploy/docker-compose/docker-compose.es.yml,它会额外引入两个服务:

  • es:使用liangliangyy/elasticsearch-analysis-ik:8.6.1镜像(已内置 IK 中文分词插件),以discovery.type=single-node单节点模式运行,ES_JAVA_OPTS限制 JVM 堆为 512MB,映射端口9200:9200;
  • kibana:kibana:8.6.1,通过ELASTICSEARCH_HOSTS=http://es:9200连接 ES,映射端口5601:5601,便于可视化调试索引。

同时在djangoblog服务中注入DJANGO_ELASTICSEARCH_HOST=es:9200,这正是触发源码切换到 ES 后端的开关(详见第 6.5 节)。

数据持久化:原文档描述为"ES 数据存放在data/elasticsearch",而当前仓库的 es 覆盖文件挂载的是./bin/datas/es/:/usr/share/elasticsearch/data/,部署时按仓库实际路径确认即可。

版本一致性提醒:当前仓库的 es 覆盖文件中对djangoblog服务的command与links仍引用旧版启动脚本(bin/docker_start.sh)和memcached服务,与主 compose 存在历史版本差异。若叠加启动报错,可参考第 7 节,直接在叠加命令中显式覆盖djangoblog.command为sh /code/djangoblog/deploy/entrypoint.sh。

3. 首次运行初始化:进入容器执行管理命令

当容器首次启动后,应用容器(服务名web,在仓库 compose 中实际名为djangoblog)会自动执行数据库迁移、静态文件收集等初始化工作(详见第 7 节),但你还需要手动创建管理员账号。

# 进入 djangoblog 应用容器 docker-compose exec djangoblog bash # 在容器内执行以下命令: # 创建超级管理员账户(按提示设置用户名、邮箱和密码) python manage.py createsuperuser # (可选) 创建一批测试数据 python manage.py create_testdata # (可选,如果启用了 ES) 重建搜索索引 python manage.py rebuild_index # 退出容器 exit

这些命令对应仓库中的真实管理命令:create_testdata的实现位于 blog/management/commands/create_testdata.py,用于批量生成文章、分类、标签等演示数据;rebuild_index是 django-haystack 提供的标准索引重建命令,对应后端为 djangoblog/elasticsearch_backend.py 或 djangoblog/whoosh_cn_backend.py(由是否启用 ES 决定)。此外仓库还提供build_index(见 blog/management/commands/build_index.py),它会在容器启动时被 entrypoint 自动调用一次。

4. 备选方式:使用独立 Docker 镜像对接外部 MySQL

如果你已经有一套运行中的 MySQL,不需要 Compose 管理数据库,可以直接运行官方发布的应用镜像liangliangyy/djangoblog:

# 从 Docker Hub 拉取最新镜像 docker pull liangliangyy/djangoblog:latest # 运行容器,并通过环境变量连接你的外部数据库 docker run -d \ -p 8000:8000 \ -e DJANGO_SECRET_KEY='your-strong-secret-key' \ -e DJANGO_MYSQL_HOST='your-mysql-host' \ -e DJANGO_MYSQL_USER='your-mysql-user' \ -e DJANGO_MYSQL_PASSWORD='your-mysql-password' \ -e DJANGO_MYSQL_DATABASE='djangoblog' \ --name djangoblog \ liangliangyy/djangoblog:latest
  • 访问博客:启动完成后访问http://127.0.0.1:8000(此时没有 Nginx,直接访问 Django 端口);
  • 创建管理员:
docker exec -it djangoblog python manage.py createsuperuser

该镜像的构建入口与 Compose 完全一致(见第 7 节),因此容器首次启动时同样会自动执行迁移、静态文件收集与索引构建,只需把DJANGO_*数据库变量指向你的外部 MySQL 即可。

5. 配置总览:环境变量逐项解析

项目的大部分生产配置都通过环境变量驱动,你可以在 compose 文件的environment段修改,也可以在docker run时用-e传入。下表完整继承自官方文档,并补充了对应的源码影响位置:

环境变量默认值 / 示例说明源码影响位置
DJANGO_SECRET_KEYyour-strong-secret-key务必改成随机复杂字符串!生产安全的核心settings.py L31-L32
DJANGO_DEBUGFalse是否开启 Django 调试模式,生产必须Falsesettings.py L34
DJANGO_MYSQL_HOSTmysql数据库主机名(Compose 内为服务名db)settings.py L114
DJANGO_MYSQL_PORT3306数据库端口settings.py L115-L116
DJANGO_MYSQL_DATABASEdjangoblog数据库名称settings.py L111
DJANGO_MYSQL_USERroot数据库用户名settings.py L112
DJANGO_MYSQL_PASSWORDdjangoblog_123数据库密码settings.py L113
DJANGO_REDIS_URLredis:6379/0Redis 连接地址(用于缓存)settings.py L295-L301
DJANGO_ELASTICSEARCH_HOSTelasticsearch:9200ES 主机地址,设置后切换全文检索后端settings.py L210-L233
DJANGO_EMAIL_HOSTsmtp.example.org邮件服务器地址settings.py L311
DJANGO_EMAIL_PORT465邮件服务器端口settings.py L312
DJANGO_EMAIL_USERuser@example.org发信邮箱账户settings.py L313
DJANGO_EMAIL_PASSWORDyour-email-password发信邮箱密码settings.py L314
DJANGO_EMAIL_USE_SSLTrue是否启用 SSLsettings.py L310
DJANGO_EMAIL_USE_TLSFalse是否启用 TLSsettings.py L309
DJANGO_ADMIN_EMAILadmin@example.org接收异常报告的管理员邮箱settings.py L318
DJANGO_BAIDU_NOTIFY_URLhttp://data.zz.baidu.com/...百度站长平台链接推送接口settings.py L304-L305

6. 环境变量在源码中如何生效

理解了环境变量表,再看它们在settings.py中真实的读取逻辑,你就能明白"改哪个变量会引发什么行为"。

6.1 布尔变量的解析规则

DJANGO_DEBUG、DJANGO_EMAIL_USE_SSL/TLS等布尔型变量并不是简单的字符串,而是经过env_to_bool统一解析(settings.py L19-L21):

def env_to_bool(env, default): str_val = os.environ.get(env) return default if str_val is None else str_val == 'True'

即:变量未设置时返回默认值;设置时只有字符串字面量True才解析为真,其余任何写法(true、1、yes)都会被当作False。这一点在配置 compose 环境时很容易踩坑,务必写成True/False。

6.2 DEBUG 的默认值陷阱

注意 settings.py L34 的代码:

DEBUG = env_to_bool('DJANGO_DEBUG', True)

若你不设置DJANGO_DEBUG,源码默认值是True(开发模式)——这与文档表格中的示例值False并不等价。生产部署时必须在 compose 或docker run中显式设置DJANGO_DEBUG=False,否则调试模式会把敏感信息暴露给访客。仓库的 docker-compose.yml 中已经显式写入了DJANGO_DEBUG=False,这是正确的生产姿势。

6.3 SECRET_KEY 与 MySQL 连接

SECRET_KEY在 settings.py L31-L32 通过os.environ.get('DJANGO_SECRET_KEY') or 'n9ceqv38...'读取——内置默认值仅用于本地开发,生产环境必须覆盖,否则所有部署此项目的站点将共享同一把密钥,存在被伪造签名会话的风险。

MySQL 连接(settings.py L109-L116)则完整读取DJANGO_MYSQL_DATABASE / USER / PASSWORD / HOST / PORT五个变量,并强制使用utf8mb4字符集以支持完整 Unicode(包括 emoji)存储。

6.4 Redis 缓存的切换

当设置DJANGO_REDIS_URL时(settings.py L295-L301),CACHES会切换到 Django 内置的redis.RedisCache后端,LOCATION被拼接为redis://<DJANGO_REDIS_URL>;未设置时则回退到项目默认的缓存方案。注意在 compose 中该变量的写法是redis:6379(不含redis://前缀和数据库编号),源码会自动补全协议头。

6.5 Elasticsearch 后端的自动切换

这是最值得关注的一处联动逻辑(settings.py L210-L250):

  • 只要检测到DJANGO_ELASTICSEARCH_HOST环境变量,就会构造ELASTICSEARCH_DSL配置(支持ELASTICSEARCH_VERIFY_CERTS、ELASTICSEARCH_USERNAME/PASSWORD等附加变量);
  • 随后HAYSTACK_CONNECTIONS依据'ELASTICSEARCH_DSL' in locals()自动选择后端:启用 ES 时使用 djangoblog/elasticsearch_backend.py 的ElasticSearchEngine,否则回退到 djangoblog/whoosh_cn_backend.py 的WhooshEngine(索引目录whoosh_index)。

这解释了为什么第 2.4 节只需叠加一个 compose 文件、注入一个环境变量,全文检索后端就会从 Whoosh 平滑切换为 Elasticsearch。

6.6 邮件与错误报告

settings.py L308-L318 显示,邮件功能使用 SMTP 后端,EMAIL_USE_SSL默认True、EMAIL_USE_TLS默认False(两者互斥,同时为True会冲突);DJANGO_ADMIN_EMAIL会写入ADMINS,当DEBUG=False时 Django 会把未捕获异常以邮件形式发送给该管理员。也就是说,邮件变量不仅用于发送评论通知等业务邮件,也是生产环境异常告警的通道。

7. 镜像构建与容器启动的完整流程

理解了配置,再看应用镜像本身。根目录的 Dockerfile 采用两阶段构建,这是理解"为什么--build会比较慢"以及"静态资源从哪来"的关键。

7.1 阶段一:Node 前端构建

FROM node:20-alpine AS frontend-builder WORKDIR /app COPY frontend/package*.json ./frontend/ RUN cd frontend && npm config set registry https://registry.npmjs.org/ && npm ci COPY frontend/ ./frontend/ COPY templates/ ./templates/ RUN cd frontend && npm run build

前端工程位于 frontend/,基于 Vite + Tailwind 构建(见 frontend/vite.config.js);由于模板中的 Tailwind 类名需要参与扫描,构建阶段同时拷贝了 templates/。构建产物输出到blog/static/blog/dist。

7.2 阶段二:Python 运行时

FROM python:3.11 RUN apt-get update && apt-get install default-libmysqlclient-dev gettext -y RUN pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt \ && pip install --no-cache-dir gunicorn[gevent] && pip cache purge COPY . . RUN rm -rf /code/djangoblog/blog/static/blog/dist COPY --from=frontend-builder /app/blog/static/blog/dist /code/djangoblog/blog/static/blog/dist ENTRYPOINT ["/code/djangoblog/deploy/entrypoint.sh"]

python:3.11基础镜像安装 MySQL 客户端库(用于django.db.backends.mysql驱动)和 gettext(用于compilemessages国际化编译);依赖安装完毕后,从第一阶段拷贝前端构建产物,并清掉源码树中可能残留的旧产物。

7.3 entrypoint:容器启动即自动初始化

容器启动后执行的 deploy/entrypoint.sh 会按顺序自动完成:

python manage.py makemigrations && \ python manage.py migrate && \ python manage.py collectstatic --noinput && \ python manage.py compress --force && \ python manage.py build_index && \ python manage.py compilemessages

即:生成并执行数据库迁移、收集静态文件到collectedstatic、压缩静态资源、构建搜索索引、编译翻译文件——首次启动时这些步骤已经替你完成,这也是为什么第 3 节只需要创建超级管理员。全部成功后,最终以 Gunicorn 启动服务:

exec gunicorn djangoblog.wsgi:application \ --workers 1 --bind 0.0.0.0:8000 \ --worker-class gevent --threads 4

采用 gevent 协程 worker + 每 worker 4 线程的组合(入口模块见 djangoblog/wsgi.py),在单 worker 情况下仍能并发处理请求。

7.4 Nginx:静态资源与反向代理

deploy/nginx.conf 中监听 80 端口:/static/请求通过alias直接命中collectedstatic目录(expires max设置长缓存);其余请求由proxy_pass http://djangoblog:8000转发给 Django,并透传X-Real-IP、X-Forwarded-For、Host头。静态文件之所以能被 nginx 读取,正是得益于 compose 中static_files命名卷在 djangoblog(读写)与 nginx(只读)两个容器之间的共享挂载。

8. 部署完成后的安全检查清单

部署完成后,请务必对照以下几点逐项确认(尤其是密钥与数据库、邮件相关项):

  1. 更换DJANGO_SECRET_KEY为一个随机、复杂、足够长的字符串(可用python -c "import secrets; print(secrets.token_urlsafe(50))"生成);
  2. 确认DJANGO_DEBUG=False,并验证异常页面不再展示堆栈与调试工具栏;
  3. 核对数据库变量与你的 MySQL 实例(用户名、密码、库名、主机、端口)完全一致,且数据库密码已从默认值QQQQwww123!@#或djangoblog_123改为强密码;
  4. 配置邮件变量(DJANGO_EMAIL_*),否则生产环境的异常告警邮件无法送达DJANGO_ADMIN_EMAIL;
  5. 如启用全文搜索,确认DJANGO_ELASTICSEARCH_HOST指向可达的 ES 实例,并已在容器内执行过索引构建/重建;
  6. 检查http://127.0.0.1能正常访问博客,/admin/后台可用管理员账号登录。

完成以上步骤,你的 DjangoBlog 便已在 Docker 环境中稳定运行。若需要更完整的集群化部署方案,可继续阅读仓库中的 Kubernetes 部署指南 与中文版 Docker 部署文档。

  • 后端
  • 前端
  • CMS

【免费下载链接】DjangoBlog

🍺基于Django的博客系统

项目地址:https://gitcode.com/gh_mirrors/dj/DjangoBlog
点击查看免费下载
上一篇:d3d8to9终极指南:让经典Direct3D 8游戏在现代Windows系统上完美运行
下一篇:如何用d3d8to9让老游戏在Windows 10/11上焕发新生:终极兼容性解决方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询