You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过Docker Compose在3307端口运行MySQL遇连接拒绝问题求助

问题:Docker Compose中MySQL自定义端口失效导致Prisma连接失败

问题描述

我尝试在单台机器上部署多个Prisma数据库服务,但无法通过Docker Compose让MySQL在3306以外的端口运行,Prisma始终报连接拒绝错误。

相关配置与日志

docker-compose.yml

version: '3'
services:
  hackernews:
    image: prismagraphql/prisma:1.8
    restart: always
    ports:
      - "${CLIENT_PORT}:${INTERNAL_PORT}"
    environment:
      PRISMA_CONFIG: |
        port: $INTERNAL_PORT
        managementApiSecret: $PRISMA_MANAGEMENT_API_SECRET
        databases:
          default:
            connector: mysql
            host: mysql
            port: $SQL_INTERNAL_PORT
            user: root
            password: $SQL_PASSWORD
            migrations: true
  mysql:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: $SQL_PASSWORD
    volumes:
      - ./custom/:/etc/mysql/conf.d/my.cnf
      - mysql:/var/lib/mysql
volumes:
  mysql:

docker-compose.override.yml

version: '3'
services:
  mysql:
    expose:
      - "${SQL_INTERNAL_PORT}"
    ports:
      - "${SQL_CLIENT_PORT}:${SQL_INTERNAL_PORT}"

.env 文件

SQL_PASSWORD=myuniquepassword
SQL_INTERNAL_PORT=3307
SQL_CLIENT_PORT=3307

报错信息

hackernews_1 | Exception in thread "main" java.sql.SQLTransientConnectionException: database - Connection is not available, request timed out after 5008ms.
hackernews_1 | at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:548)
hackernews_1 | at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:186)
hackernews_1 | at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:145)
hackernews_1 | at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:83)
hackernews_1 | at slick.jdbc.hikaricp.HikariCPJdbcDataSource.createConnection(HikariCPJdbcDataSource.scala:18)
hackernews_1 | at slick.jdbc.JdbcBackend$BaseSession.<init>(JdbcBackend.scala:439)
hackernews_1 | at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:47)
hackernews_1 | at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:38)
hackernews_1 | at slick.basic.BasicBackend$DatabaseDef.acquireSession(BasicBackend.scala:218)
hackernews_1 | at slick.basic.BasicBackend$DatabaseDef.acquireSession$(BasicBackend.scala:217)
hackernews_1 | at slick.jdbc.JdbcBackend$DatabaseDef.acquireSession(JdbcBackend.scala:38)
hackernews_1 | at slick.basic.BasicBackend$DatabaseDef$$anon$2.run(BasicBackend.scala:239)
hackernews_1 | at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
hackernews_1 | at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
hackernews_1 | at java.lang.Thread.run(Thread.java:748)
hackernews_1 | Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=mysql)(port=3307)(type=master) : Connection refused (Connection refused)
hackernews_1 | at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:161)
hackernews_1 | at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.connException(ExceptionMapper.java:79)
hackernews_1 | at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1040)
hackernews_1 | at org.mariadb.jdbc.internal.util.Utils.retrieveProxy(Utils.java:490)
hackernews_1 | at org.mariadb.jdbc.MariaDbConnection.newConnection(MariaDbConnection.java:144)
hackernews_1 | at org.mariadb.jdbc.Driver.connect(Driver.java:90)
hackernews_1 | at slick.jdbc.DriverDataSource.getConnection(DriverDataSource.scala:101)
hackernews_1 | at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:341)
hackernews_1 | at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:193)
hackernews_1 | at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:430)
hackernews_1 | at com.zaxxer.hikari.pool.HikariPool.access$500(HikariPool.java:64)
hackernews_1 | at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:570)
hackernews_1 | at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:563)
hackernews_1 | at java.util.concurrent.FutureTask.run(FutureTask.java:266)

docker ps 输出

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ab721996469d mysql:5.7 "docker-entrypoint.s鈥� 42 minutes ago Up 55 seconds 3306/tcp two_mysql_1
7aab98e2b8d7 prismagraphql/prisma:1.8 ""/bin/sh -c /app/sta鈥�" 2 hours ago Restarting (1) Less than a second ago two_hackernews_1

问题分析

从docker ps输出能明显看到,MySQL容器只监听了默认的3306/tcp端口,而非你指定的3307。核心原因有两个:

  1. MySQL配置文件挂载错误:你把./custom/目录直接挂载成了/etc/mysql/conf.d/my.cnf文件,导致MySQL无法读取正确的端口配置,只能用默认的3306启动。
  2. 容器端口不匹配:虽然你在override.yml里暴露了3307端口,但MySQL本身并没有在这个端口运行,所以Prisma尝试连接3307时会被拒绝。

解决方案

步骤1:修复MySQL配置文件与挂载路径

  1. 在项目根目录创建custom文件夹,里面新建my.cnf文件,内容如下:
[mysqld]
port = 3307
bind-address = 0.0.0.0  # 允许容器内部/外部访问
  1. 修改docker-compose.yml中MySQL的volumes配置,把目录挂载改成文件挂载:
volumes:
  - ./custom/my.cnf:/etc/mysql/conf.d/my.cnf  # 确保是文件到文件的挂载
  - mysql:/var/lib/mysql

步骤2:确保所有端口配置一致

检查并确认:

  • .env里的SQL_INTERNAL_PORT=3307和my.cnf的port=3307完全一致
  • Prisma配置中的databases.default.port: $SQL_INTERNAL_PORT指向容器内部的MySQL端口(3307)
  • override.yml里的expose和ports配置保持不变,它们负责把容器内部的3307映射到主机的3307

步骤3:清理旧容器与数据卷,重新启动

因为之前的MySQL数据卷可能保留了默认端口的配置,需要彻底清理后重启:

# 停止并删除容器、网络、数据卷
docker-compose down -v
# 重新构建并启动服务
docker-compose up -d

验证是否生效

  1. 查看容器端口状态:
docker ps

此时MySQL容器的PORTS应该显示类似0.0.0.0:3307->3307/tcp的内容。

  1. 进入MySQL容器验证端口:
docker exec -it two_mysql_1 mysql -uroot -p$SQL_PASSWORD -e "SHOW GLOBAL VARIABLES LIKE 'port';"

输出应该显示port | 3307。

完成以上步骤后,Prisma就能正常连接到3307端口的MySQL了。


内容的提问来源于Stack Exchange,提问作者提供的相关信息:

  • MySQL容器:0.0.0.0:3307->3307/tcp two_mysql_1
  • Prisma容器:7aab98e2b8d7 prismagraphql/prisma:1.8(状态:Restarting (1) Less than a second ago two_hackernews_1)
  • .env配置:SQL_PASSWORD=myuniquepassword; SQL_INTERNAL_PORT=3307; SQL_CLIENT_PORT=3307
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:08:19