Administrator
发布于 2026-01-29 / 1 阅读
0
0

Docker Compose 连接服务器现有 MySQL 完整方案

背景

在服务器上已经运行了一个 MySQL 服务(端口 3309),现在需要使用 Docker Compose 启动 Spring Boot 应用,并连接到这个已存在的 MySQL 数据库,而不是在 Docker 容器中再启动一个新的 MySQL。

完整解决方案

一、修改 docker-compose.yml

1. 注释掉 MySQL 容器配置

# mysql:
#   image: mysql:8.0
#   container_name: springboot-mysql
...
#   mem_limit: 256m

2. 修改 app 服务的数据库连接配置

app:
  build:
    context: .
    dockerfile: Dockerfile
  container_name: springboot-app
  restart: always
  ports:
    - "8080:8080"
  environment:
    # 修改数据库连接配置,连接服务器现有 MySQL
    SPRING_DATASOURCE_URL: jdbc:mysql://host.docker.internal:3309/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    SPRING_DATASOURCE_USERNAME: newuser
    SPRING_DATASOURCE_PASSWORD: 123456
...
  mem_limit: 256m

3. 移除 mysql-data 卷定义

volumes:
  # 移除 mysql-data 卷
  redis-data:

二、MySQL 用户授权

由于 Docker 容器需要从容器网络访问宿主机的 MySQL,需要给数据库用户授予相应的权限。

1. 连接到 MySQL

mysql -u root -p

2. 创建用户并授权(MySQL 8.0+ 语法)

-- 创建用户(如果不存在)
CREATE USER IF NOT EXISTS 'newuser'@'%' IDENTIFIED BY '123456';

-- 授予 demo 数据库的所有权限
GRANT ALL PRIVILEGES ON demo.* TO 'newuser'@'%';

-- 刷新权限
FLUSH PRIVILEGES;

3. 验证权限

-- 查看用户权限
SHOW GRANTS FOR 'newuser'@'%';

-- 查看用户信息
SELECT host, user FROM mysql.user WHERE user = 'newuser';

三、关键修改点说明

1. 数据库连接配置

配置项 原值 新值 说明
主机地址 mysql host.docker.internal 指向宿主机
端口 3306 3309 服务器 MySQL 实际端口
用户名 root newuser 使用指定的数据库用户
密码 123456 123456 保持不变

2. host.docker.internal 说明

host.docker.internal 是 Docker 提供的特殊 DNS 名称,用于从容器内部访问宿主机。

平台支持情况:

  • ✅ Docker Desktop(Windows/Mac):原生支持
  • ❌ Linux:不支持

Linux 替代方案:

如果服务器是 Linux 系统,需要将 host.docker.internal 替换为宿主机的实际 IP 地址。

查看宿主机 IP 的命令:

# 快速查看主网卡 IP
ip route get 1.1.1.1 | awk '{print $7}'

# 查看所有 IP
hostname -I

选择物理网卡(如 eth0ens33)的 IP,不要选择 127.0.0.1172.17.0.1

修改后的配置示例:

SPRING_DATASOURCE_URL: jdbc:mysql://192.168.1.100:3309/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true

3. 依赖关系调整

移除了 app 服务对 mysql 容器的依赖,因为不再启动 MySQL 容器:

depends_on:
  redis:
    condition: service_healthy

4. 卷定义清理

移除了不再使用的 mysql-data 卷:

volumes:
  redis-data:

四、常见问题解决

问题1:Access denied for user 'newuser'@'172.18.0.1'

原因: 用户没有从 Docker 容器网络访问的权限。

解决: 执行 MySQL 授权命令,使用 @'%' 允许从任意 IP 访问。

问题2:MySQL 8.0+ GRANT 语法错误

错误信息: ERROR 1410 (42000): You are not allowed to create a user with GRANT

原因: MySQL 8.0+ 不允许在 GRANT 语句中使用 IDENTIFIED BY

解决: 先创建用户,再授予权限。

-- 正确的语法
CREATE USER IF NOT EXISTS 'newuser'@'%' IDENTIFIED BY '123456';
GRANT ALL PRIVILEGES ON demo.* TO 'newuser'@'%';
FLUSH PRIVILEGES;

问题3:Linux 上 host.docker.internal 不工作

解决: 使用宿主机实际 IP 地址替代。

五、启动服务

完成以上配置后,启动 Docker Compose 服务:

# 构建并启动所有服务
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看应用日志
docker-compose logs -f app

# 重启应用服务
docker-compose restart app

六、总结

通过以上方案,我们实现了 Docker Compose 连接服务器现有 MySQL 的目标,主要步骤包括:

  1. 注释掉 docker-compose.yml 中的 MySQL 容器配置
  2. 修改 app 服务的数据库连接配置,指向宿主机 MySQL
  3. 移除对 MySQL 容器的依赖和卷定义
  4. 在 MySQL 中为容器用户授予访问权限
  5. Linux 环境需要使用宿主机实际 IP 替代 host.docker.internal

这样可以避免重复启动 MySQL 服务,节省服务器资源,同时保持应用的正常运行。


评论