I have mongodb replicaset with Traefik. I configured the mongodb with 3 instances using docker compose (I do understant that is not optimal with all mongo instances in one server – let us skip that part). I want to use Traefik as a proxy server to support TCP security with letsencrypts. I managed to configure my websites with TLS but I am unable to connect to mongodb via mongo compass application. All instances using Traefik network.
I tried to use the following configuration
mongodb compose file
networks:
starlink:
name: traefik_starlink
external: true
services:
# If on a linux server, use the hostname provided by the docker compose file
# e.g. HOSTNAME = mongo1, mongo2, mongo3
# If on MacOS add the following to your /etc/hosts file.
# 127.0.0.1 mongo1
# 127.0.0.1 mongo2
# 127.0.0.1 mongo3
# And use localhost as the HOSTNAME
mongo1:
image: mongo:latest
hostname: mongo1
container_name: mongo1
command:
[
"--replSet",
"rs0",
"--bind_ip_all",
"--port",
"27018",
"--keyFile",
"/etc/mongodb/pki/keyfile",
]
restart: always
ports:
- 27018:27018
networks:
- starlink
volumes:
- ${PWD}/rs_keyfile:/etc/mongodb/pki/keyfile
- ./data/mongo/mongo1_data:/data/db
- ./data/mongo/mongo1_config:/data/configdb
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
extra_hosts:
- "host.docker.internal:host-gateway"
env_file:
- ./.env
labels:
- traefik.enable=true
- traefik.tcp.routers.mongo1.entrypoints=mongo_db_1
- traefik.tcp.routers.mongo1.service=mongo1
- traefik.tcp.routers.mongo1.tls=true
- traefik.tcp.routers.mongo1.tls.certresolver=letsencrypt
- traefik.tcp.services.mongo1.loadbalancer.server.port=27018
- traefik.tcp.routers.mongo1.tls.domains[0].main=${DOMAIN}
- traefik.tcp.routers.mongo1.rule=HostSNI(`mongo.${DOMAIN}`)
- traefik.tcp.routers.mongo1.tls.passthrough=true
mongo2:
image: mongo:latest
hostname: mongo2
container_name: mongo2
command:
[
"--replSet",
"rs0",
"--bind_ip_all",
"--port",
"27019",
"--keyFile",
"/etc/mongodb/pki/keyfile",
]
restart: always
ports:
- 27019:27019
networks:
- starlink
volumes:
- ${PWD}/rs_keyfile:/etc/mongodb/pki/keyfile
- ./data/mongo/mongo2_data:/data/db
- ./data/mongo/mongo2_config:/data/configdb
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
extra_hosts:
- "host.docker.internal:host-gateway"
env_file:
- ./.env
labels:
- traefik.enable=true
- traefik.tcp.routers.mongo2.entrypoints=mongo_db_2
- traefik.tcp.routers.mongo2.service=mongo2
- traefik.tcp.routers.mongo2.tls=true
- traefik.tcp.routers.mongo2.tls.certresolver=letsencrypt
- traefik.tcp.services.mongo2.loadbalancer.server.port=27018
- traefik.tcp.routers.mongo2.tls.domains[0].main=${DOMAIN}
- traefik.tcp.routers.mongo2.rule=HostSNI(`mongo.${DOMAIN}`)
- traefik.tcp.routers.mongo2.tls.passthrough=true
mongo3:
image: mongo:latest
hostname: mongo3
container_name: mongo3
command:
[
"--replSet",
"rs0",
"--bind_ip_all",
"--port",
"27020",
"--keyFile",
"/etc/mongodb/pki/keyfile",
]
restart: always
ports:
- 27020:27020
networks:
- starlink
volumes:
- ${PWD}/rs_keyfile:/etc/mongodb/pki/keyfile
- ./data/mongo/mongo3_data:/data/db
- ./data/mongo/mongo3_config:/data/configdb
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
extra_hosts:
- "host.docker.internal:host-gateway"
env_file:
- ./.env
labels:
- traefik.enable=true
- traefik.tcp.routers.mongo3.entrypoints=mongo_db_3
- traefik.tcp.routers.mongo3.service=mongo3
- traefik.tcp.routers.mongo3.tls=true
- traefik.tcp.routers.mongo3.tls.certresolver=letsencrypt
- traefik.tcp.services.mongo3.loadbalancer.server.port=27018
- traefik.tcp.routers.mongo3.tls.domains[0].main=${DOMAIN}
- traefik.tcp.routers.mongo3.rule=HostSNI(`mongo.${DOMAIN}`)
- traefik.tcp.routers.mongo3.tls.passthrough=true
From the mongodb replicaset, I can see that the instances can see each other and the replicaset configuration is set successfully.
Running “rs.status()”
rs0 [direct: secondary] test> rs.status()
{
set: 'rs0',
date: ISODate("2024-06-24T21:06:52.394Z"),
myState: 2,
term: Long("55"),
syncSourceHost: 'mongo1:27018',
syncSourceId: 0,
heartbeatIntervalMillis: Long("2000"),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 3,
writableVotingMembersCount: 3,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1719263210, i: 1 }), t: Long("55") },
lastCommittedWallTime: ISODate("2024-06-24T21:06:50.754Z"),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1719263210, i: 1 }), t: Long("55") },
appliedOpTime: { ts: Timestamp({ t: 1719263210, i: 1 }), t: Long("55") },
durableOpTime: { ts: Timestamp({ t: 1719263210, i: 1 }), t: Long("55") },
lastAppliedWallTime: ISODate("2024-06-24T21:06:50.754Z"),
lastDurableWallTime: ISODate("2024-06-24T21:06:50.754Z")
},
lastStableRecoveryTimestamp: Timestamp({ t: 1719263180, i: 1 }),
electionParticipantMetrics: {
votedForCandidate: true,
electionTerm: Long("55"),
lastVoteDate: ISODate("2024-06-24T20:55:40.686Z"),
electionCandidateMemberId: 0,
voteReason: '',
lastAppliedOpTimeAtElection: { ts: Timestamp({ t: 1719262514, i: 1 }), t: Long("53") },
maxAppliedOpTimeInSet: { ts: Timestamp({ t: 1719262514, i: 1 }), t: Long("53") },
priorityAtElection: 1,
newTermStartDate: ISODate("2024-06-24T20:55:40.708Z"),
newTermAppliedDate: ISODate("2024-06-24T20:55:41.191Z")
},
members: [
{
_id: 0,
name: 'mongo1:27018',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 682,
optime: { ts: Timestamp({ t: 1719263210, i: 1 }), t: Long("55") },
optimeDurable: { ts: Timestamp({ t: 1719263210, i: 1 }), t: Long("55") },
optimeDate: ISODate("2024-06-24T21:06:50.000Z"),
optimeDurableDate: ISODate("2024-06-24T21:06:50.000Z"),
lastAppliedWallTime: ISODate("2024-06-24T21:06:50.754Z"),
lastDurableWallTime: ISODate("2024-06-24T21:06:50.754Z"),
lastHeartbeat: ISODate("2024-06-24T21:06:51.525Z"),
lastHeartbeatRecv: ISODate("2024-06-24T21:06:51.023Z"),
pingMs: Long("0"),
lastHeartbeatMessage: '',
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp({ t: 1719262540, i: 1 }),
electionDate: ISODate("2024-06-24T20:55:40.000Z"),
configVersion: 1,
configTerm: 55
},
{
_id: 1,
name: 'mongo2:27019',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 684,
optime: { ts: Timestamp({ t: 1719263210, i: 1 }), t: Long("55") },
optimeDate: ISODate("2024-06-24T21:06:50.000Z"),
lastAppliedWallTime: ISODate("2024-06-24T21:06:50.754Z"),
lastDurableWallTime: ISODate("2024-06-24T21:06:50.754Z"),
syncSourceHost: 'mongo1:27018',
syncSourceId: 0,
infoMessage: '',
configVersion: 1,
configTerm: 55,
self: true,
lastHeartbeatMessage: ''
},
{
_id: 2,
name: 'mongo3:27020',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 682,
optime: { ts: Timestamp({ t: 1719263210, i: 1 }), t: Long("55") },
optimeDurable: { ts: Timestamp({ t: 1719263210, i: 1 }), t: Long("55") },
optimeDate: ISODate("2024-06-24T21:06:50.000Z"),
optimeDurableDate: ISODate("2024-06-24T21:06:50.000Z"),
lastAppliedWallTime: ISODate("2024-06-24T21:06:50.754Z"),
lastDurableWallTime: ISODate("2024-06-24T21:06:50.754Z"),
lastHeartbeat: ISODate("2024-06-24T21:06:51.527Z"),
lastHeartbeatRecv: ISODate("2024-06-24T21:06:51.525Z"),
pingMs: Long("0"),
lastHeartbeatMessage: '',
syncSourceHost: 'mongo1:27018',
syncSourceId: 0,
infoMessage: '',
configVersion: 1,
configTerm: 55
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1719263210, i: 1 }),
signature: {
hash: Binary(Buffer.from("e741ccfce88c1a4956338a7b086bb3676a8230e9", "hex"), 0),
keyId: Long("7381057184014008325")
}
},
operationTime: Timestamp({ t: 1719263210, i: 1 })
}
Traefik compose file is configured as follow:
networks:
starlink:
driver: bridge
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
env_file:
- ./.env
command:
- "--log.level=DEBUG"
- --api.dashboard=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.mongo_db_1.address=:27021
- --entrypoints.mongo_db_2.address=:27022
- --entrypoints.mongo_db_3.address=:27023
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entryPoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.websecure.asDefault=true
- --entrypoints.websecure.http.tls.certresolver=letsencrypt
- --certificatesresolvers.letsencrypt.acme.tlschallenge=true
#- --certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
- --certificatesresolvers.letsencrypt.acme.email=${EMAIL}
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
networks:
- starlink
ports:
- 27021:27018
- 27022:27019
- 27023:27020
- 443:443
- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik/letsencrypt:/letsencrypt
labels:
- traefik.enable=true
- traefik.http.routers.traefik.rule=Host(`nginx.${DOMAIN}`)
- traefik.http.routers.traefik.entrypoints=websecure
- traefik.http.routers.traefik.service=api@internal
- traefik.http.routers.traefik.tls.certresolver=letsencrypt
- traefik.http.middlewares.httpsonly.redirectscheme.scheme=https
- traefik.http.middlewares.httpsonly.redirectscheme.permanent=true
- traefik.http.routers.httpsonly.middlewares=httpsonly
- traefik.http.routers.traefik.middlewares=auth
- traefik.http.middlewares.auth.basicauth.users=${TRAEFIK_PASSWORD_BASIC_AUTH}
I tried to connect using the following connection string
mongodb://<USER>:<PASSWORD>@mongo.rocketdev.dev:27021,mongo.rocketdev.dev:27022,mongo.rocketdev.dev:27023/?replicaSet=rs0
but I’m always getting “Server selection timed out after 30000 ms”
This is an image from Traefik dashboard
enter image description here
Can someone help me understanding what is the issue?