为什么不应该使用 Docker 部署数据库

服务容器化变得越来越流行,如今大部分的 Web 服务会首选部署在容器中。容器的优点是否也适用于部署数据库?

很多文章在分析这个问题时会站在:性能、网络、资源隔离等方面来考虑。比如提到多加一层(Union FS)会导致性能下降甚至数据不可靠、Docker 在网络方面的诟病、Docker 的资源隔离不适合用于数据库(同时在一台机器上启动多个数据库实例,共享同一份数据,但两个实例由于隔离互相不可见,就会导致数据混乱的问题)。

我并没有找到 Union FS 会让性能下降多少的性能测试,网络方面虽然遇到过坑但也都能解决,资源隔离通常使用端口号进行互斥即可,保证只有一个实例运行。

Docker 的使用场景并不适用于数据库组件

上边那些并不是最核心的问题,我认为最核心的是 Docker 的使用场景并不适用于数据库组件。

我们来看一下使用 Docker 带来优势:

  1. 标准化应用发布:Docker包含了运行环境和可执行程序,可以跨平台和主机使用;
  2. 节约时间,快速部署和启动:VM 启动一般是分钟级,Docker容器启动是秒级;
  3. 方便构建基于SOA架构或微服务架构的系统:通过服务编排,更好的松耦合;
  4. 节约成本:以前一个虚拟机至少需要几个G的磁盘空间,Docker容器可以减少到MB级;
  5. 方便持续集成:通过与代码进行关联使持续集成非常方便;
  6. 可以作为集群系统的轻量主机或节点:在IaaS平台上,已经出现了CaaS,通过容器替代原来的主机。

以上提到的大多数优势并不适用于数据库的运行环境:数据库通常是长期运行的,数据完整性是重中之重。我们不需要数据库自动扩容(在 Docker 中水平伸缩只能用于无状态计算服务,而不是数据库)、也不需要持续更新数据库的代码来进行持续集成。

数据库版本升级

除了场景不适合之外,另一个问题是数据库软件版本升级。对于无状态应用或者数据库的小版本更新来说,直接修改 Dockerfile 中的版本号并重新构建、重启即可完成升级,但数据库的大版本升级就没有这么简单了,大版本升级数据库版本会伴随数据存储结构的更新,仅仅升级版本是不行的。通常数据库提供商会提供相应的命令来让我们对数据库进行升级,但这样做的前提是数据库不能运行在容器中(需要进入容器才能执行命令、软件版本无法持久化)。

在开发环境中通过 Docker 运行数据库

凡事也不是绝对的,在开发环境中通过 Docker 来运行数据库就是个不错的选择。或者将它用于数据量不大、对可靠性要求不是那么高并且所有东西都放在单机中运行的项目中也是可以的,不过前提是要做好数据的日常备份工作。