I am trying to set up multiservices architecture in my Node.js backend with docker. I have currently two services with two separate databases
version: "3"
services:
server-api-getaway:
build:
context: "."
dockerfile: "./server-api-gateway/Dockerfile"
depends_on:
- db
- redis
ports:
- "7100:7100"
volumes:
- ./server-api-gateway:/usr/src/app/server-api-gateway
environment:
- CHOKIDAR_USEPOLLING=true
- REDIS_URL=redis://cache
- DATABASE_URL=postgres://postgres:postgres@db:3336/dbname
- DATABASE_PORT=3336
- DATABASE_HOST=host.docker.internal
- POSTGRES_DB=dbname
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- PORT=7100
db:
image: postgres
restart: always
environment:
- POSTGRES_DB=dbname
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
ports:
- "3336:3306"
server-user-service:
build:
context: "."
dockerfile: "./server-user-service/Dockerfile"
depends_on:
- user-service-db
ports:
- "7000:7000"
volumes:
- ./server-user-service:/usr/src/app/server-user-service
environment:
- CHOKIDAR_USEPOLLING=true
- REDIS_URL=redis://cache
- DATABASE_URL=postgres://postgres:postgres@user-service-db:3307/dbname
- DATABASE_PORT=3307
- DATABASE_HOST=host.docker.internal
- POSTGRES_DB=dbname
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- PORT=7000
user-service-db:
image: postgres
restart: always
environment:
- POSTGRES_DB=dbname
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
ports:
- "3307:3306"
redis:
image: redis
container_name: cache
restart: always
ports:
- 6379:6379
volumes:
pgdata:
driver: local
pgconf:
driver: local
pglog:
driver: local
I expect both databases to run on different ports, but when I run docker-compose up they are exposed to 5432 port
2021-03-05 07:12:10.111 UTC [1] LOG: listening on IPv4 address
"0.0.0.0", port 5432
When I connect my service to port 5432 everything works fine. But I need two databases to be exposed to different ports. How can I achieve it?
Update
I’ve changed port mapping as was suggested in comments.
user-service-db:
image: postgres
restart: always
environment:
- POSTGRES_DB=dbname
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
ports:
- "5432:3336"
And made a fresh start after docker-compose down
Result remained the same
user-service-db_1 | 2021-03-05 10:01:23.023 UTC [1] LOG:
listening on IPv4 address "0.0.0.0", port 5432
probably there is a detail I am missing
2
Answers
You need to expose the correct port.
Postgres default port is
5432
: i.e. the postgres service in your docker container will listen to port5432
.I guess, on the host, you want to listen
3336
(or3306
?).in this case the mapping must be:
i.e. the format is
HOST:CONTAINER
see also:
As an implementation detail, containers have their own private IP addresses. You can’t usually access these addresses from outside Docker, but when your container tries to connect to the host name
db
, that maps to one of these internal addresses. This means that it’s okay for processes in different containers to listen on the same port, since each process is in its own isolated network space.That means it’s standard for a packaged process to listen on its "normal" port. The output you’re seeing is the output of the PostgreSQL startup; this will always listen on 0.0.0.0:5432 (unless you make tricky modifications to its configuration file).
Connections between containers also always connect to the "normal" port:
Publishing a port makes it accessible from outside Docker, using the host’s IP address (and DNS name). The second
ports:
number needs to match the port number inside the container, the first one can be anything that’s not already in use. Connections between containers never use this."Expose" as a verb means almost nothing in modern Docker.
EXPOSE
in a Dockerfile is mostly documentation and there’s no reason to use the Composeexpose:
setting.