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 stop
和 start
时数据不会丢失,但一旦使用 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,或结合专业的数据库集群方案一起使用,以确保数据安全与系统稳定性。