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

容器化Spring Boot应用连接Docker MongoDB出现Socket打开异常

问题描述

我有一个Spring Boot应用(test-service):

  • 容器外运行时,可正常连接非容器化和容器化的MongoDB实例;
  • 容器化运行该应用时,抛出MongoSocketOpenException异常;
  • 进入test-service容器后能ping通容器化的MongoDB,但连接失败;
  • 已排查MongoDB用户权限(添加额外角色、测试test用户),问题仍未解决。

堆栈跟踪

test-service  | 2023-04-15 01:31:14.099  INFO 1 --- [}-mongodb:27018] org.mongodb.driver.cluster               : Exception in monitor thread while connecting to server mongodb:27018
test-service  | 
test-service  | com.mongodb.MongoSocketOpenException: Exception opening socket
test-service  |        at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:70) ~[mongodb-driver-core-4.6.1.jar:na]
test-service  |        at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:180) ~[mongodb-driver-core-4.6.1.jar:na]
test-service  |        at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.lookupServerDescription(DefaultServerMonitor.java:193) ~[mongodb-driver-core-4.6.1.jar:na]
test-service  |        at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:157) ~[mongodb-driver-core-4.6.1.jar:na]
test-service  |        at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
test-service  | Caused by: java.net.ConnectException: Connection refused: mongodb:27018
test-service  |        at java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na]
test-service  |        at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) ~[na:na]
test-service  |        at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) ~[na:na]
test-service  |        at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597) ~[na:na]
test-service  |        at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[na:na]
test-service  |        at java.base/java.net.Socket.connect(Socket.java:633) ~[na:na]
test-service  |        at com.mongodb.internal.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:107) ~[mongodb-driver-core-4.6.1.jar:na]
test-service  |        at com.mongodb.internal.connection.SocketStream.initializeSocket(SocketStream.java:79) ~[mongodb-driver-core-4.6.1.jar:na]
test-service  |        at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:65) ~[mongodb-driver-core-4.6.1.jar:na]
test-service  |        ... 4 common frames omitted

docker-compose.yml

version: "3"
services:
  mongodb:
    image: mongo:6.0.5
    container_name: mongodb
    volumes:
      - mongodb:/data/db
    ports:
      - "27018:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: admin
      MONGO_INITDB_DATABASE: test-service
    platform: linux/arm64
  test-service:
    image: test-service:0.1.0
    container_name: test-service
    volumes:
      - $HOME/config/keystore:/var/keystore
    ports:
      - 8083:8083
    environment:
      MONGO_HOST: mongodb
      MONGO_PORT: 27018
      MONGO_USER: admin
      MONGO_PASSWORD: admin
      MONGO_AUTH_DB: admin
      KEYSTORE_PATH: /var/keystore/dev-env-cert.p12
    platform: linux/arm64
    depends_on:
      - mongodb
volumes:
  mongodb: {}

application.properties

mongodb.host=${MONGO_HOST:localhost}
mongodb.port=${MONGO_PORT:27017}
mongodb.database=test-service
mongodb.authentication-database=${MONGO_AUTH_DB:admin}
mongodb.username=${MONGO_USER:admin}
mongodb.password=${MONGO_PASSWORD:admin}

Mongo配置(Java代码)

@Configuration
public class MongoConfig extends AbstractMongoClientConfiguration {
    @Value("${mongodb.host}")
    private String dbHost;
    @Value("${mongodb.port}")
    private String dbPort;
    @Value("${mongodb.authentication-database}")
    private String dbAuthDb;
    @Value("${mongodb.username}")
    private String dbUsername;
    @Value("${mongodb.password}")
    private String dbPassword;
    @Value("${mongodb.database}")
    private String dbName;

    @Override
    protected String getDatabaseName() {
        return dbName;
    }

    @Override
    protected String getMappingBasePackage() {
        return "com.test.model";
    }

    @Override
    public MongoClient mongoClient() {
        MongoClientSettings settings = MongoClientSettings
            .builder()
            .applyConnectionString(new ConnectionString("mongodb://" + dbHost + ":" 
                + dbPort + "/" + dbName))
            .credential(MongoCredential.createScramSha256Credential(dbUsername, 
                dbAuthDb, dbPassword.toCharArray()))
            .applicationName(dbName)
            .build();
        MongoClient client = MongoClients.create(settings);

        return client;
    }
}

补充说明

已检查容器的admin数据库,尝试添加额外角色并使用test用户测试,但问题仍未解决:

admin> db.getUsers()
{
  users: [
    {
      _id: 'admin.admin',
      userId: new UUID("8730bf38-301c-4123-a8a3-1c651d7b1e4e"),
      user: 'admin',
      db: 'admin',
      roles: [
        { role: 'dbOwner', db: 'test-service' },
        { role: 'root', db: 'admin' }
      ],
      mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]
    },
    {
      _id: 'admin.test',
      userId: new UUID("fb16d8e3-537b-4f67-a6fc-2b22faf6f242"),
      user: 'test',
      db: 'admin',
      roles: [ { role: 'dbOwner', db: 'test-service' } ],
      mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]
    }
  ],
  ok: 1
}

核心问题与修复方案

核心错误

Docker Compose网络中,容器间直接通信需使用MongoDB容器内部的端口(27017),而非宿主机的映射端口(27018)。当前配置MONGO_PORT=27018是错误的,该端口仅对宿主机开放,容器内部无法通过此端口访问MongoDB容器。

修复步骤

  1. 修改docker-compose.yml中test-service的环境变量:
    environment:
      MONGO_HOST: mongodb
      MONGO_PORT: 27017  # 改为MongoDB容器内部的默认端口
      MONGO_USER: admin
      MONGO_PASSWORD: admin
      MONGO_AUTH_DB: admin
      KEYSTORE_PATH: /var/keystore/dev-env-cert.p12
    
  2. 重启服务:
    docker-compose down && docker-compose up -d
    

额外验证(可选)

  • 进入test-service容器,用MongoShell连接验证:
    docker exec -it test-service bash
    # 若容器内无MongoShell,执行以下安装命令
    apt update && apt install -y mongodb-clients
    # 连接MongoDB容器
    mongosh mongodb:27017/test-service -u admin -p admin --authenticationDatabase admin
    
  • 检查MongoDB容器启动状态:
    docker logs mongodb
    
    确认日志中出现Waiting for connections字样,说明服务就绪。

为什么ping通但连接失败?

  • ping基于ICMP协议,仅验证主机可达性,不校验端口是否开放;
  • 你尝试访问的27018端口在MongoDB容器内部并未开放,因此连接被拒绝。

内容的提问来源于stack exchange,提问作者Molasses

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:15:18