Ошибка подключения pymongo к replica set в docker compose

Задача запустить mongodb replica set из одной ноды и подключиться к нему из другого контейнера через pymongo

После docker compose up -d такое поведение:

  1. Подключение к базе данных происходит успешно через:
    • MongodbCompass к mongodb://admin:admin@localhost:27017
    • docker exec -it api mongosh mongodb://admin:admin@mongodb
  2. Подключиться к бд не получается через pymongo
docker exec -it api python3
import pymongo
client = pymongo.MongoClient("mongodb://admin:admin@mongodb")
client.server_info()  # падает с ошибкой

pymongo.errors.ServerSelectionTimeoutError: Could not reach any servers in [('localhost', 27017)]. Replica set is configured with internal hostnames or IPs?, Timeout: 30s, Topology Description: <TopologyDescription id: 66e555178d7445f5d7997aa8, topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('localhost', 27017) server_type: Unknown, rtt: None, error=AutoReconnect('localhost:27017: [Errno 111] Connection refused (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms)')>]>

Кажется это происходит из-за { _id: 0, host: 'localhost:27017' } в rs.initiate(), я попробовал заменять localhost на mongodb, пробовал ресолвить hostname в ip и заменять localhost на него, однако уже падает mongodb во всех этих случаях с похожей ошибкой:

couldn't connect to server mongodb:27017, connection attempt failed: SocketException: Error connecting to mongodb:27017 (172.18.0.2:27017) :: caused by :: syncConnect connect error :: caused by :: Connection refused"

No host described in new configuration with {version: 1, term: 0} for replica set rs0 maps to this node,"config":{"_id":"rs0","members":[{"_id":0,"host":"mongodb:27017"}]

Хотя из контейнера mongodb можно получать IP хостнейма и подключаться через mongosh к базе данных через него

В конце концов хочется сказать что проблема здесь не в монге, а в pymongo, так как именно на её стороне происходит разрыв соединения, а так же другие решения для подключению к бд работают.

Структура

├── Dockerfile
├── docker-compose.yml
├── mongodb
│   ├── Dockerfile
│   ├── generate-keyfile.sh
│   ├── init.js
│   └── mongod.conf

docker-compose.yml

services:
  mongodb:
    build:
      context: ./mongodb
    ports:
      - "27017:27017"
  api:
    container_name: api
    build:
      context: .

Dockerfile

FROM python:3.12.1-alpine3.19

RUN pip3 install pymongo
RUN apk update
RUN apk add --update nodejs npm
RUN npm install -g mongosh

CMD tail -f

Mongodb

mongodb/Dockerfile

FROM mongo:latest

COPY generate-keyfile.sh /generate-keyfile.sh

RUN mkdir -p /opt/keyfile && \
    /bin/bash /generate-keyfile.sh

COPY mongod.conf /etc/mongod.conf
COPY init.js /docker-entrypoint-initdb.d/init.js
CMD ["mongod", "-f", "/etc/mongod.conf"]

mongodb/mongodb.conf

net:
  port: 27017
  bindIp: 127.0.0.1

security:
  authorization: enabled
  keyFile: /opt/keyfile/mongo-keyfile

replication:
  replSetName: rs0

mongodb/init.js

rs.initiate({_id: 'rs0', members: [{ _id: 0, host: 'localhost:27017' }]});

sleep(10000) // ожидание инициализации

var adminDB = db.getSiblingDB('admin');
adminDB.createUser({user: 'admin', pwd: 'admin', roles: [{ role: 'root', db: 'admin' }]});

Доп информация

rs.status() ->

{
  set: 'rs0',
  date: ISODate('2024-09-14T09:18:26.501Z'),
  myState: 1,
  term: Long('2'),
  syncSourceHost: '',
  syncSourceId: -1,
  heartbeatIntervalMillis: Long('2000'),
  majorityVoteCount: 1,
  writeMajorityCount: 1,
  votingMembersCount: 1,
  writableVotingMembersCount: 1,
  optimes: {
    lastCommittedOpTime: { ts: Timestamp({ t: 1726305496, i: 1 }), t: Long('2') },
    lastCommittedWallTime: ISODate('2024-09-14T09:18:16.735Z'),
    readConcernMajorityOpTime: { ts: Timestamp({ t: 1726305496, i: 1 }), t: Long('2') },
    appliedOpTime: { ts: Timestamp({ t: 1726305496, i: 1 }), t: Long('2') },
    durableOpTime: { ts: Timestamp({ t: 1726305496, i: 1 }), t: Long('2') },
    lastAppliedWallTime: ISODate('2024-09-14T09:18:16.735Z'),
    lastDurableWallTime: ISODate('2024-09-14T09:18:16.735Z')
  },
  lastStableRecoveryTimestamp: Timestamp({ t: 1726305466, i: 1 }),
  electionCandidateMetrics: {
    lastElectionReason: 'electionTimeout',
    lastElectionDate: ISODate('2024-09-14T08:51:46.749Z'),
    electionTerm: Long('2'),
    lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
    lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1726303904, i: 4 }), t: Long('1') },
    numVotesNeeded: 1,
    priorityAtElection: 1,
    electionTimeoutMillis: Long('10000'),
    newTermStartDate: ISODate('2024-09-14T08:51:46.753Z'),
    wMajorityWriteAvailabilityDate: ISODate('2024-09-14T08:51:46.756Z')
  },
  members: [
    {
      _id: 0,
      name: 'localhost:27017',
      health: 1,
      state: 1,
      stateStr: 'PRIMARY',
      uptime: 1601,
      optime: { ts: Timestamp({ t: 1726305496, i: 1 }), t: Long('2') },
      optimeDate: ISODate('2024-09-14T09:18:16.000Z'),
      lastAppliedWallTime: ISODate('2024-09-14T09:18:16.735Z'),
      lastDurableWallTime: ISODate('2024-09-14T09:18:16.735Z'),
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: '',
      electionTime: Timestamp({ t: 1726303906, i: 1 }),
      electionDate: ISODate('2024-09-14T08:51:46.000Z'),
      configVersion: 1,
      configTerm: 2,
      self: true,
      lastHeartbeatMessage: ''
    }
  ],
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1726305496, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('VqlzRHy12WaSQvdaNlDJn08ffBU=', 0),
      keyId: Long('7414418767687450630')
    }
  },
  operationTime: Timestamp({ t: 1726305496, i: 1 })
}

Версии

mongodb - 7.0.14 python - 3.12.1 pymongo - 4.8.0 mongosh - 2.3.1


Ответы (0 шт):