为什么我最终放弃了 Conda 部署

预计阅读时间:10 分钟

这是「把自己部署到互联网上」系列的第 19 篇。

上一篇,我把 Conda 和 Docker 放在个人博客生产部署场景里做了一次对比。结论不是 Conda 不好,也不是 Docker 永远更高级,而是:如果只是本地开发、数据分析、短期实验,Conda 很舒服;但如果是长期运行、多服务组合、多项目共存,并且后续要迁移和维护的个人博客,Docker 更适合我的目标

这一篇不再泛泛对比,而是从自己的过程出发,复盘为什么我最终放弃了 Conda 部署。

一开始,我确实想用 Conda。长期写 Python 的人,很容易把 Conda 当成自然选择。本地开发时,它管理 Python 版本和依赖很方便:

conda create -n blog python=3.11
conda activate blog
pip install -r requirements.txt

如果只是为了第一天跑起来,这条路很直接:服务器上装 Miniconda,创建环境,安装依赖,启动项目,再用 Nginx 代理出去。不用写 Dockerfile,不用理解容器网络,不用处理数据卷,也不用写 Docker Compose。对快速验证来说,它很有吸引力。

但真正开始想生产部署时,问题接踵而至。

原因一:环境不只等于 Python 依赖

一个博客项目要长期运行,除了 Python 包,还会涉及系统依赖、环境变量、数据库、静态资源、服务启动方式、进程守护、日志路径、Nginx 代理、HTTPS 证书、上传目录和备份目录。Conda 能很好地管理 Python 版本和一部分依赖,但它不负责整个服务运行环境

这意味着我需要额外补很多东西。

服务怎么后台运行?

nohupscreentmuxsystemd,还是 supervisor

数据库怎么跑?

装在系统里,单独用 Docker,还是作为系统服务?

Nginx、证书、日志、上传目录又放在哪里?

这些都可以做,但会依赖大量手动约定。

而手动约定最大的问题,写在 README.md文档里面还好,单纯靠记性,几个月后被自己忘掉落。

原因二:启动方式越来越像补丁

本地开发时,启动项目很简单:

conda activate blog
python app.py

或者:

uvicorn main:app --host 0.0.0.0 --port 8000

但生产环境和开发环境不一样,不能只靠一个前台命令长期跑。要考虑服务崩了怎么办,服务器重启后怎么办,日志写到哪里,环境变量怎么加载,多个服务的启动顺序怎么处理。

如果继续用 Conda,这些问题通常要交给其他工具,

比如 systemdsystemd 很稳定,也适合管理 Linux 服务,但我就需要把 Conda 环境路径、项目目录、启动命令、用户权限和日志配置都写进 service 文件。后面如果还有第二个、第三个项目,每个项目都要类似处理。

最后部署结构会变成:

  • Conda 管 Python 环境
  • systemd 管进程
  • Nginx 管入口
  • 数据库另管
  • 日志另管
  • 配置文件另管

这套“组合拳”可以工作,但在个人维护场景里,多少有点杂乱。

过段时间,回头看项目时,想能在一个地方看到它需要哪些服务、端口、环境变量、数据目录和启动方式。这也是我转向 Docker Compose 的原因之一。

原因三:是多项目共存

个人博客只是第一步。后面还有个人官网、作品站,也可能部署小工具或实验项目。如果每个项目都用 Conda 环境,理论上没问题:

blog 环境
site 环境
tool 环境
api 环境

但项目不只是 Python 环境。每个项目还会有启动脚本、环境变量、日志目录、上传目录、数据库连接、Nginx 配置、静态资源路径和备份方式。

如果这些都散落在服务器不同位置,多项目共用一台服务器时就会越来越难维护。我希望每个项目都有清晰边界:配置在哪里,数据在哪里,日志在哪里,怎么启动和停止,依赖哪些服务。Conda 可以隔离 Python 包,但它不是完整的项目部署边界

原因四:迁移

在创建项目前期,个人博客是长期项目,服务器以后可能会迁移。可能是续费太贵,可能是配置不够,可能是换云厂商,也可能是系统需要重做。

如果一年后换服务器,我希望能快速地把博客重新拉起来。使用 Conda 部署时,我要重新安装 Miniconda、创建环境、安装依赖、补系统依赖、恢复环境变量、恢复数据库和上传文件、恢复 Nginx 配置、恢复 systemd 或其他启动脚本,还要确认端口和防火墙。

这当然可以通过写文档解决,但文档容易滞后。实际环境里手动改过什么,有时候就懒得记,过一段时间可能自己都忘了。

Docker 也不是免迁移。数据卷、配置文件、环境变量、证书、数据库备份一样要处理。但如果 Dockerfile 和 Docker Compose 写得清楚,应用运行环境、服务关系和启动方式更容易固化。迁移时,我更像是在恢复一套声明好的项目结构,而不是回忆服务器上曾经手动装过什么。

原因五:部署过程能不能沉淀

这个合集系列不只是为了把博客跑起来,也是在把过程沉淀成文章、经验和后续可复用的资产。如果部署大量依赖手工操作,文章会写得很散,读者难以复用,我自己以后也难复盘。

如果部署过程可以文件化,比如 Dockerfile、docker-compose.yml.env 示例、Nginx 配置、目录结构说明、数据备份策略,它就更容易沉淀。文章也不只是记录“我在服务器上做了什么”,而是输出一套更清晰的部署结构。

不是因为 Conda 不能用才放弃。Conda 能用,而且在本地开发、数据分析、内部工具、小脚本和轻量实验里很好用。我放弃它,是因为它不再是这个场景里的最优选择。

转向 Docker 后,解决几个问题:

  1. 通过 Dockerfile 记录项目运行依赖
  2. 通过 Compose 记录服务关系
  3. 让应用、数据库、Nginx 有更清晰的边界
  4. docker compose up -ddocker compose downdocker compose logs 统一管理启停和日志
  5. 让多个项目更容易共存
  6. 让迁移不完全依赖记忆。

当然,Docker 也会带来新的问题,比如镜像构建、数据卷、网络、端口映射、容器日志、权限和备份。但这些问题更符合我后续长期维护的方向。

小结

这次选择也给我一个提醒:不要只用开发习惯决定生产部署

  • 本地开发看重方便、快速、灵活;
  • 生产部署看重稳定、可复现、可维护、可迁移。

目标不同,工具选择就可能不同。

下一篇,我会继续拆一个基础问题:Docker 和 Docker Compose 到底分别解决什么问题?在真正写部署文件之前,先把这两个概念讲清楚。


本文由 楸木 原创,转载请注明出处。

相关推荐

发现更多