Docker生产环境实际使用全流程疑问:Django栈部署、数据持久化及自动化发布
先解决你当前数据丢失的直接问题
你当前执行的下线命令带了删除卷的参数:docker-compose -f docker-compose.prod.yml down -v,其中-v参数的作用就是删除该compose配置声明的所有命名卷,这是你每次下线数据都丢失的核心原因,如果你只是要停止服务不删除数据,直接执行不带-v的命令即可:
docker-compose -f docker-compose.prod.yml down
如果不加-v重启后还是找不到数据,大概率是compose的项目名发生了变化:compose默认用当前目录名作为项目前缀生成卷名,如果你移动了compose文件的存放目录,或者手动指定了-p参数修改项目名,就会生成新的空白卷,旧数据还存在原卷中,你可以执行docker volume ls查看所有本地卷确认。
接下来逐个解答你的疑问:
1. 数据持久化与代码迭代方案
你需要先把数据分成两类区别处理:
- 状态数据:包括数据库数据、用户上传的媒体文件,这类数据不能和代码、镜像绑定,就用你当前的命名卷挂载存储即可,只要不主动删除卷,容器销毁重建数据不会丢失。
- 无状态代码/静态资源:就是你日常迭代的前后端代码,这类内容直接打包到镜像里即可,迭代流程很固定:
- 本地开发完成后把代码推到Git仓库
- 服务器拉取最新代码,执行
docker-compose -f docker-compose.prod.yml up -d --build,compose会自动重建有变更的服务镜像,用新容器替换旧容器 - 如果涉及数据库表结构变更,额外执行
docker-compose -f docker-compose.prod.yml exec web python manage.py migrate即可,静态文件你配置的挂载已经可以自动同步,不需要手动拷贝。
2. 部署流程与数据存储方案
如果你的业务当前是单服务器部署,完全不需要上Swarm或者Kubernetes,Docker Compose足够支撑需求:
- 数据库数据:就用命名卷挂载到宿主机,定期做备份即可,备份命令参考:
备份文件可以同步到其他存储介质避免服务器故障丢失数据。docker-compose -f docker-compose.prod.yml exec db pg_dump -U <你的数据库用户名> <数据库名> > ./backup_$(date +%Y%m%d).sql - 媒体文件:量小的话继续用命名卷挂载,定期备份;量大的话直接对接云服务商的对象存储,修改Django的存储后端即可,不需要存在本地服务器。
- 一键自动化发布可以用CI/CD工具实现,配置规则为Git主分支有新提交时,自动连接服务器拉取代码、执行构建更新命令、执行数据库迁移,全程不需要手动操作。
3. 架构相关疑问
Docker本质是统一运行环境的打包工具,既可以用来部署中间件,也可以直接打包业务代码运行,没有使用场景限制。
业务专属的状态数据不需要放到代码仓库或者镜像里,存储在独立的存储介质(宿主机卷、云数据库、对象存储)即可,不需要跟着代码版本迭代,只需要做好定期备份和备份版本管理。
你提到的「修改仓库内容后直接推送到服务器生效」的架构完全可以落地,就是上述的CI/CD流程,只要提前做好发布前的自动化测试环节,不会有稳定性问题,目前绝大多数中小团队都用这套方案。
4. 生产无感知发布方案
单服务器部署不需要切换IP,也不会出现端口冲突,用反向代理就可以实现无缝发布:
你可以在compose配置里给web服务加上滚动更新配置和健康检查,发布时compose会先启动新版本的容器,等健康检查通过后再停止旧版本容器,全程不会影响用户访问。如果怕出问题,也可以先启动新版本容器,手动验证正常后再切Nginx流量、下线旧容器。
如果业务量级足够大,再考虑多服务器+负载均衡的方案,发布时把流量逐步切到新集群即可,你当前的阶段用单服务器滚动更新完全够用。
5. 容器开机自启方案
两步即可解决:
- 先设置Docker服务开机自启,systemd体系的服务器执行:
systemctl enable docker - 在你的compose配置的每个服务下添加
restart: always参数,示例:
该参数会在Docker服务启动时,自动拉起对应容器,除非你手动停止容器。services: web: build: context: ./app dockerfile: Dockerfile.prod restart: always # 其余配置保持不变
内容的提问来源于stack exchange,提问作者odyssy3105

