1. 概述

Docker 是一个用于创建、部署和管理容器的框架。由于容器可以运行任何类型的应用程序,我们自然也想用它来部署数据库管理系统(DBMS)。

在本文中,我们将探讨如何在 Docker 中使用数据库。首先我们会介绍如何在本地安装数据库管理系统,接着讲解容器间的数据持久化机制,最后讨论在生产环境中使用 Docker 部署数据库的可靠性问题。


2. 在本地运行 Docker 镜像

首先,我们需要一个运行在容器中的 DBMS。

2.1. 使用标准 Docker 镜像

第一步是安装 Docker Desktop,然后从 DockerHub 找到目标 DBMS 的镜像。

以 PostgreSQL 为例:

$ docker pull postgres

下载完成后,使用 docker run 启动一个 PostgreSQL 容器。对于 PostgreSQL,需要通过 -e 设置 POSTGRES_PASSWORD 环境变量:

$ docker run -e POSTGRES_PASSWORD=password postgres

接下来,我们测试与数据库容器的连接。

2.2. Java 项目连接数据库

我们可以通过 JDBC 数据源快速验证数据库连接。

默认连接字符串如下

jdbc:postgresql://localhost:5432/postgres?user=postgres&password=password

如果出现连接失败,可能是因为数据库监听的是容器内部网络,而 Java 应用运行在容器外部。

解决方法是将容器端口映射到本地主机。例如将容器的 5432 映射到本地的 5432:

$ docker run -p 5432:5432 -e POSTGRES_PASSWORD=password postgres

这样连接就正常了,可以正常使用 JDBC。

2.3. 运行 SQL 脚本

我们可以通过 docker exec 命令连接到容器内部并执行 SQL 脚本。

首先查看容器 ID:

$ docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                    NAMES
65d9163eece2   postgres   "docker-entrypoint.s…"   27 minutes ago   Up 27 minutes   0.0.0.0:5432->5432/tcp   optimistic_hellman

进入容器:

$ docker exec -it 65d9163eece2 bash

连接数据库并执行 SQL:

root@65d9163eece2:/# psql -U postgres
postgres=# CREATE DATABASE TEST;
CREATE TABLE PERSON(
  ID INTEGER PRIMARY KEY,
  FIRST_NAME VARCHAR(1000),
  LAST_NAME VARCHAR(1000)
);
...

也可以直接在宿主机执行 SQL 文件:

$ docker exec 65d9163eece2 psql -U postgres < dump.sql

这种方式更适用于自动化部署。


3. 使用 Docker Volume 持久化数据

数据库通常需要在容器重启后保留数据。

3.1. 为什么需要 Volume

默认情况下,Docker 会将数据保存在一个临时目录中。使用 docker container stopstart 时数据不会丢失,但一旦使用 docker run 启动新容器,旧数据就会被清除。

3.2. 配置 Volume

查看容器使用的 Volume:

$ docker inspect -f "{{ .Mounts }}" 65d9163eece2
[{volume f1033d3 /var/lib/docker/volumes/f1033d3/_data /var/lib/postgresql/data local true }]

可以看到容器目录 /var/lib/postgresql/data 映射到了宿主机的 /var/lib/docker/volumes/f1033d3/_data

我们可以通过 -v 指定自定义路径:

$ docker run -v C:\docker-db-volume:/var/lib/postgresql/data -e POSTGRES_PASSWORD=password postgres

现在数据库文件会保存在 C:\docker-db-volume 中,即使容器被删除也不会丢失。

如果需要团队协作或跨环境部署,可以使用 Docker Compose 文件统一管理配置。


4. 在生产环境中使用 Docker

Docker Compose 非常适合管理无状态服务,比如 REST 接口后端。但如果要部署数据库这种有状态服务,管理会更复杂。

4.1. 单实例数据库

适用于测试环境或允许短暂停机的生产环境。

配置要点

  • 使用 Volume 存储数据
  • 使用 global 模式限制只运行一个容器

示例 docker-compose.yaml

version: '3'
services:       
  database:
    image: 'postgres'
    deploy:
      mode: global
    environment:
      - POSTGRES_PASSWORD=password
    ports:
      - "5432:5432"
    volumes:
      - "C:/docker-db-volume:/var/lib/postgresql/data"

⚠️ 注意:必须定期备份该目录,避免因配置错误导致数据丢失或损坏。

4.2. 多副本数据库

对于关键生产环境,推荐使用集群方案。

Docker Swarm 和 Kubernetes 支持无状态服务的自动扩缩容、负载均衡和故障转移,但不支持 Volume 的复制。

如果强行使用这些工具部署数据库,可能会导致数据丢失或损坏:

❌ 使用 NFS 或 NAS 作为共享存储不能防止容器重启后数据丢失
❌ 在主从集群中,Docker 编排工具可能会错误地选举多个主节点,导致数据冲突

✅ 推荐方案:

  • 使用数据库自身或硬件级复制机制
  • 使用 PaaS 服务(如 OpenShift、AWS、Azure)
  • 使用 Docker 插件(如 KubeDB、Portworx)

虽然这些方案增加了复杂性,但能有效保障数据安全。


5. 是否应该使用 Docker 部署数据库

5.1. 优势

  • 环境隔离:提供一致的运行环境,便于迁移和升级
  • 快速部署:主流 DBMS 都有官方镜像,可直接拉取运行
  • 不影响性能:特别是 I/O 操作几乎无损耗
$ docker pull postgres
  • 配置简单:只需基础配置即可运行,无需关心底层依赖

5.2. 缺陷

  • 厂商支持有限:部分数据库厂商未提供对容器环境的全面支持
  • 存在脑裂风险:容器快速启动/重启可能引发数据一致性问题
  • 容器不能随意终止:强制停止数据库容器可能导致数据损坏
  • 存储抽象层增加风险:虽然存储驱动已经成熟,但仍然是一个潜在的故障点

6. 总结

Docker 非常适合用于开发、测试或非关键生产环境中的数据库部署。

但在高可用性场景下,建议避免直接使用 Docker,或结合专业的数据库集群方案一起使用,以确保数据安全与系统稳定性。


原始标题:How to Deal With Databases in Docker?