Ошибка подключения pymongo к replica set в docker compose
Задача запустить mongodb replica set из одной ноды и подключиться к нему из другого контейнера через pymongo
После docker compose up -d
такое поведение:
- Подключение к базе данных происходит успешно через:
- MongodbCompass к mongodb://admin:admin@localhost:27017
docker exec -it api mongosh mongodb://admin:admin@mongodb
- Подключиться к бд не получается через 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