Docker Compose understanding the ports mapping - mongodb

Docker newbie here. I am trying to understand the meaning of the following:
services:
mongo1:
hostname: mongo1
container_name: mongo1
image: mongo:5.0.6
expose:
- 27017
ports:
- 27011:27017
restart: always
Note the ports: 27011:27017. When the Docker is up and running, I can access the MongoDB server via port 27011, so what is the 27017? And why do I need to expose it like the following?
expose:
- 27017

expose: is a legacy implementation detail of first-generation Docker networking. It does almost nothing in current Docker, and it's always safe to remove it from Compose files. No other changes are required.
ports: describes how to map a port from the host system to a port in the container. The second port number is a fixed property of the image and is typically the "normal" port the container listens on; in your example MongoDB normally listens on port 27017 and the second port number must be exactly that. The first port number can be any otherwise-unused port on the host system.

Related

Docker container getting connection refused from postgres container in docker-compose

I've been beating my head against this for a few days now and I'm finally asking for help after trying to find the solution myself from all over.
I have a docker-compose file that looks like this:
services:
db:
image: ...
container_name: db
ports:
- "8095:5432"
networks:
- mynetwork
springservice:
image: ...
container_name: springservice
depends_on:
- db
ports:
- "8090:8090"
networks:
- mynetwork
environment:
- SPRING_DATASOURCE_URL: jdbc:postgresql://db:8095/dbname
- SPRING_DATASOURCE_USER: user
- SPRING_DATASOURCE_PASSWORD: password
networks:
mynetwork:
driver: bridge
name: mynetwork
Postgres has to be put to another port because we've got 3 postgres containers in that compose, so each get their own port.
Postgres's listen_address is set to "*".
pg_hba is set with "host all 0.0.0.0/0 md5"
Both containers come up, but when I curl from the service container to http://db:8095/ , I get connection refused.
What am I missing here?
Your port mapping is meaningless inside the docker network. This is only a mapping to the host system. Inside the network, the container is always available on its native port.
- SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/dbname
Also note that you don't need to publish the port to access it from inside the network. Doing so for a database can impose security risks. If you can, you should not publish it. That way, it will be only accessible from inside the docker network.

Connect to user-defined network in Docker

I imagine this question has been asked a bunch, but can't seem to find a concise answer...
I have the following Docker Compose:
version: "3.7"
networks:
foo-network:
driver: bridge
services:
foo-pg-db:
image: postgres:9.6.2-alpine
restart: always
volumes:
- ./bootstrap/pg:/docker-entrypoint-initdb.d/
ports:
- 5432:5432
environment:
POSTGRES_USER: admin
networks:
- foo-network
This runs and I'm able to connect to it from my app code with the following URL: "postgres://admin#foo-pg-db/foo", but if I'm trying to connect to this from my Mac, what is the "host" portion of the connection URL? It's not localhost is it?
For me similar thing happened with MySQL container that "localhost" was not identified as valid address for docker container address and using "127.0.0.1" worked.
127.0.0.1 is default address in linux systems, check your hosts file for exact address used by your os
Also, your network has nothing to do with it because you are directly using ports variable :-
ports:
- 5432:5432
This actually binds your container port to host post.
<host_port> : <container_port>

Connecting two a database in a another container with docker-compose

I'm trying to set up a docker-compose where one container has the database and the other one has the application. To my best knowledge, I need to connect two containers with a network.
version: "3"
services:
psqldb:
image: "postgres"
container_name: "psqldb"
environment:
- POSTGRES_USER=usr
- POSTGRES_PASSWORD=pwd
- POSTGRES_DB=mydb
ports:
- "5432:5432"
expose:
- "5432"
volumes:
- $HOME/docker/volumes/postgres/:/var/lib/postgresql/data
networks:
- backend
sbapp:
image: "dsb"
container_name: "dsb-cont"
ports:
- "8080:8080"
expose:
- "8080"
depends_on:
- psqldb
networks:
- backend
networks:
backend:
I also tried it with setting network driver to bridge (which didn't change the end result)
networks:
backend:
driver: bridge
I'm using the following url to connect to the database
spring.datasource.url=jdbc:postgresql://psqldb:5432/mydb
I also tried to expose the port and connect using localhost
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
I also tried to use port 5433 instead of 5432.
No matter what combination I used, I got the following error
Connection to psqldb:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
in my app container. However, my database container remains up and I can connect to it fine from host with the url
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
I can also connect to the database from host if I remove psqldb container entirely from docker-compose.yml (and use the latter connection url).
If it makes any difference, I'm using Spring
Boot for application with the Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
and I'm building the image with the command
docker build --build-arg JAR_FILE=target/*.jar -t dsb .
What am I missing in the two container setup?
The issue I had was that docker depends_on only starts the containers in the defined order but doesn't wait for them to be actually ready.
https://docs.docker.com/compose/startup-order/

How to run a docker mongo?

I have a local mongod running where I developed my app.
Now i created a Mongo Docker Image and run the container.
I use docker-compose:
version: '3.1'
services:
mongo:
image: mongo:latest
restart: always
ports:
- "27017:27017"
Somehow my local mongo instance is always being used (probably because both are being accessed by localhost:27017). Only when i go to windows task manager and really kill the mongod instance, the docker mongo is used. What do i need to change to have both running?
Thanks!
Change the port 27017 to another port so that you can access the second instance on that port:
ports:
- "27018:27017"
This exposes the docker internal port 27017 to your machine's 27018 port.
So your first local mongo instance will run on 27017 and this docker instance will run on 27018 (This can be any free port). Make sure no other local service is using this port.

docker run mongo image on a different port

The short question is can I run mongo from mongo:latest image on a different port than 27017 (for example on 27018?)
If yes, how can I do this inside a docker-compose.yml file in order ro be able to type the following command:
docker-compose run
The longer story:
I have an app running in AWS EC2 instance. The app consists of a mongodb and a web application. Now I decided to separate part of this app into its own microservice running in the same AWS inside docker container (two containers one for another mongo and one for a web app). I think the problem is I can not have mongodb running on port 27017 and at the same time another mongodb running inside a docker container on port 27017. Right? I have this assumption because when I stop the first mongo (my app mongo), my docker mongo works.
So I am trying to make the second mongo (the one that is inside the docker container), to run in a different port and my second web app (the one inside another docker conianter), to listen to mongo on a different port. Here is my attempt to change the docker-compose file:
version: '2'
services:
webapp:
image: myimage
ports:
- 3000:3000
mongo:
image: mongo:latest
ports:
- 27018:27018
And inside my new app, I changed the mongo url to:
monog_url = 'mongodb://mongo:27018'
client = MongoClient(monog_url, 27018)
Well, the same if I say:
monog_url = 'mongodb://mongo:27018'
client = MongoClient(monog_url)
But when I run docker-compose run, it still does not work, and I get the following errors:
ERROR: for mongo driver failed programming external
connectivity on endpoint: Error starting userland proxy:
listen tcp 0.0.0.0:27017: bind: address already in use
Or
pymongo.errors.ServerSelectionTimeoutError:
mongo:27018: [Errno -2] Name or service not known
You can tell MongoDB to listen on a different port in the configuration file, or by using a command-line parameter:
services:
mongo:
image: 'mongo:latest'
command: mongod --port 27018
ports:
- '27018:27018'
You can run processes inside a container and outside on the same port. You can even run multiple containers using the same port internally. What you can't do is map the one port from the host to a container. Or in your case, map a port that is already in use to a container.
For example, this would work on your host:
services:
webapp:
image: myimage
ports:
- '3000:3000'
mongo:
image: 'mongo:latest'
ports:
- '27018:27017'
mongo2:
image: mongo:latest
ports:
- '27019:27017'
The host mongo listens on 27017. The host also maps ports 27018 and 27019 to the container mongo instances, both listening on 27017 inside the container.
Each containers has its own network namespace and has no concept of what is running in another container or on the host.
Networks
The webapp needs to be able to connect to the mongo containers internal port. You can do this over a container network which allows connections between the container and also name resolution for each service
services:
webapp:
image: myimage
ports:
- '3000:3000'
networks:
- myapp
depends_on:
- mongo
mongo:
image: 'mongo:latest'
ports:
- '27018:27017'
networks:
- myapp
networks:
myapp:
driver: bridge
From your app the url mongo://mongo:27017 will then work.
From your host need to use the mapped port and an address on the host, which is normally localhost: mongo://localhost:27018
Default communication between different containers running on the same host
I solved the problem, not by running the container in a different port though, but by learning one new feature in docker-compose version 2 and that is we do not need to specify links or networks. The newly created containers by default will be part of docker0 network and hence they can communicate with each other.
As Matt mentioned, we can run processes inside containers on the same port. They should be isolated. So the problem can not be that the docker container and the host are using the same port. The problem is perhaps there is an attempt to forward a used port in host to another port in container.
Below is a working docker-compose file:
version: '2'
services:
webapp:
image: myimage
ports:
- 3000:3000
mongo:
image: mongo:latest
I looked at the mongo:latest docker file in github, and realized they exposed 27017. So we do not need to change the port or forward host ports to the running mongo container. And the mongo url can stay on the same port:
monog_url = 'mongodb://mongo:27017'
client = MongoClient(monog_url, 27017)
Docker run an image on a different port
So the above solution solved the problem, but as for the question title 'docker run mongo image on a different port', the simplest way is just to change the docker-compose to:
version: '2'
services:
web:
image: myimage
mongo:
image: mongo:latest
command: mongod --port 27018
Mongo is now running on 27018 and the following url is still accessible inside the web:
monog_url = 'mongodb://mongo:27018'
client = MongoClient(monog_url, 27018)
I had the same problem
I changed ports in my docker-compose.yml file and this work for me
In doing so, i don't change port in my connection string
mongo:
image: mongo
ports:
- "27018:27018"