I'm currently working on an api.
When I run my api on my local computer I can connect to MongoDB but when I run it from the docker container, I cannot connect to MongoDB
I tried this to connect to the container :
mongodb://0.0.0.0:27018
and
mongodb://127.0.0.1:27018
I also check if the two containers can communicate together and they can so I don't know how to do it
There is my docker-compose
version: "3.9"
services:
api:
build:
context: .
dockerfile: Dockerfile
ports:
- "3001:3001"
volumes:
- .:/app
mongo:
container_name: "sell-mongodb"
image: mongo
ports:
- "27018:27017"
volumes:
- mongodb-data:/data/db/
volumes:
mongodb-data:
Use mongodb://mongo:27017.
Use mongo as hostname, because it is the name of your MongoDB service in Docker Compose. By default, Docker enables you to access other containers by this service hostnames.
Do not use 27018 port when connecting from within another container, as it is a port exposed to your host machine. Port 27017 on the other hand should be accessible by default from the internal docker network, i.e. from other containers.
See https://docs.docker.com/compose/compose-file/compose-file-v3/#ports
Related
Good morning guys.
I'm having a problem connecting a nodejs application, in a container, to another container that contains a redis server. On my local machine I can connect the application to this redis container without any problem. However, when trying to upload this application in a container, a timeout error is returned.
I'm new to docker and I don't understand why I can connect to this docker container in the application running locally on my machine but that same connection doesn't work when I upload the application in a container.
I tried using docker-compose, but from what I understand it will upload in another container to the redis server, instead of using the redis container that is already in docker.
To connect to redis I'm using the following code:
createClient({
socket: {
host: process.env.REDIS_HOST,
port: Number(process.env.REDIS_PORT)
}
});
Where REDIS_HOST is the address of my container running on the server and REDIS_PORT is the port where this container is running on my server.
To run redis on docker I used the following guide: https://redis.io/docs/stack/get-started/install/docker/
I apologize if my problem was not very clear, I'm still studying docker.
You mentioned you are using Docker Compose. Here's an example showing how to start Redis in a container, and make your Node application wait for that container then use an environment variable in your Node application to specify the name of the host to connect to Redis on. In this example it connects to the container running Redis that I've called "redis":
version: "3.9"
services:
redis:
container_name: redis_kaboom
image: "redislabs/redismod"
ports:
- 6379:6379
volumes:
- ./redisdata:/data
entrypoint:
redis-server
--loadmodule /usr/lib/redis/modules/rejson.so
--appendonly yes
deploy:
replicas: 1
restart_policy:
condition: on-failure
node:
container_name: node_kaboom
build: .
volumes:
- .:/app
- /app/node_modules
command: sh -c "npm run load && npm run dev"
depends_on:
- redis
ports:
- 8080:8080
environment:
- REDIS_HOST=redis
So in your Node code you'd then use the value of process.env.REDIS_HOST to connect to the right Redis host. Here, I'm not using a password or a non-standard port, you could also supply those as environment variables that match the configuration of the Redis container in Docker Compose too if you needed to.
Disclosure: I work for Redis.
I'm running an instance of a web application in my Docker container and am also running a MongoDB container so when I launch the web app I can easily connect to the DB on the app's connection page.
The issue is that I'm not sure how to reach the Mongo container from my web app and am not sure if my host/port connection info is correct.
My Docker Setup
As you can see the container is up and running with both mongo and web app services running without errors
I build the two through docker-compose.yml
version: "3.3"
services:
web:
image: grafana-asw-v3
container_name: grafana-asw-v3
restart: always
build: .
ports:
- "13000:3000"
volumes:
- grafana-storage:/var/lib/grafana
stdin_open: true
tty: true
db:
container_name: mongo
image: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
volumes:
- grafana-mongo-db:/var/lib/mongo
ports:
- "27018:27017"
volumes:
grafana-mongo-db: {}
grafana-storage: {}
Issue
With everything up and running I'm attempting to connect through the web app, but I seem to be using the wrong connection info...
I assumed to use "hostMachine:port" (roxane:27018), but it's not connecting. Is there something I overlooked here?
There were two changes I had to make to fix this issue:
Modify the bind_ip in mongod.conf via making this change to my docker-compose file
db:
container_name: mongo
image: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
volumes:
- grafana-mongo-db:/var/lib/mongo
ports:
- "27018:27017"
command: mongod --bind_ip 0.0.0.0
I needed to refer to the IP address instead of the hostname in the cli in my we application. (Thanks to this answer for help with this one)
Short answer
db service is in the same network than web service not in host network.
As you named your services via container_name you shoud be able to use the connection string mongodb://mongo:27017
Explanation
By default, docker containers run under a bridge network allowing them to communicate without viewing your host network.
When using ports in a compose file, you define that you want to map an internal port of the container to the host port
"27018:27017" => I want to expose the container port number 27017 to the host port number 27018.
As a result, you could expose your web frontend without exposing your mongo service :
version: "3.3"
services:
web:
image: grafana-asw-v3
container_name: grafana-asw-v3
restart: always
build: .
ports:
- "13000:3000"
volumes:
- grafana-storage:/var/lib/grafana
stdin_open: true
tty: true
db:
container_name: mongo
image: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
volumes:
- grafana-mongo-db:/var/lib/mongo
volumes:
grafana-mongo-db: {}
grafana-storage: {}
I used kartoza's docker images for Geoserver and Postgis and started them in two docker containers using the provided docker-compose.yml:
version: '2.1'
volumes:
geoserver-data:
geo-db-data:
services:
db:
image: kartoza/postgis:12.0
volumes:
- geo-db-data:/var/lib/postgresql
ports:
- "25434:5432"
env_file:
- docker-env/db.env
restart: on-failure
healthcheck:
test: "exit 0"
geoserver:
image: kartoza/geoserver:2.17.0
volumes:
- geoserver-data:/opt/geoserver/data_dir
ports:
- "8600:8080"
restart: on-failure
env_file:
- docker-env/geoserver.env
depends_on:
db:
condition: service_healthy
healthcheck:
test: curl --fail -s http://localhost:8080/ || exit 1
interval: 1m30s
timeout: 10s
retries: 3
The referenced .env files are:
db.env
POSTGRES_DB=gis,gwc
POSTGRES_USER=docker
POSTGRES_PASS=docker
ALLOW_IP_RANGE=0.0.0.0/0
geoserver.env
GEOSERVER_DATA_DIR=/opt/geoserver/data_dir
ENABLE_JSONP=true
MAX_FILTER_RULES=20
OPTIMIZE_LINE_WIDTH=false
FOOTPRINTS_DATA_DIR=/opt/footprints_dir
GEOWEBCACHE_CACHE_DIR=/opt/geoserver/data_dir/gwc
GEOSERVER_ADMIN_PASSWORD=myawesomegeoserver
INITIAL_MEMORY=2G
MAXIMUM_MEMORY=4G
XFRAME_OPTIONS='false'
STABLE_EXTENSIONS=''
SAMPLE_DATA=false
GEOSERVER_CSRF_DISABLED=true
docker-compose up brings both containers up and running with no errors giving them names backend_db_1 (Postgis) and backend_geoserver_1 (Geoserver). I can access Geoserver running in backend_geoserver_1 under http://localhost:8600/geoserver/ as expected. I can connect an external, AWS-based Postgis as a data store to my docker-based Geoserver instance without any problems. I can also access the Postgis running in the docker container backend_db_1 from PgAdmin, with psql from the command line and from the Webstorm IDE.
However, if I try to use my Postgis running in backend_db_1 as a data store for my Geoserver running in backend_geoserver_1, I get the following error:
> Error creating data store, check the parameters. Error message: Unable
> to obtain connection: Cannot create PoolableConnectionFactory
> (Connection to localhost:25434 refused. Check that the hostname and
> port are correct and that the postmaster is accepting TCP/IP
> connections.)
So, my Geoserver in backend_geoserver_1 can connect to Postgis on AWS, but not to the one running in another docker container on the same localhost. The Postgis in backend_db_1 in its turn can be accessed from many other local apps and tools, but not from Geoserver running in a docker container.
Any ideas what I am missing? Thanks!
just add the network_mode in YAML in db and geoserver and set it to host
network_mode: host
note that this will ignore the expose option and will use the host network an containers network
I'm making a React-Native app using Rest API (NodeJS, Express) and PostgreSQL.
Everything work good when hosted on my local machine.
Everything work good when API is host on my machine and PostgreSQL in docker container.
But when backend and frontend is both in docker, database is reachable from all my computer in local, but not by the backend.
I'm using docker-compose.
version: '3'
services:
wallnerbackend:
build:
context: ./backend/
dockerfile: ../Dockerfiles/server.dockerfile
ports:
- "8080:8080"
wallnerdatabase:
build:
context: .
dockerfile: ./Dockerfiles/postgresql.dockerfile
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
env_file: .env_docker
volumes:
db-data:
.env_docker and .env have the same parameters (just name changing).
Here is my dockerfiles:
Backend
FROM node:14.1
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]
Database
FROM postgres:alpine
COPY ./wallnerdb.sql /docker-entrypoint-initdb.d/
I tried to change my hostname in connection url to postgres by using the name of the docker, my host IP address, localhost, but no results.
It's also the same .env (file in my node repo with db_name passwd etc) I do use in local to connect my backend to the db.
Since you are using NodeJS 14 in the Docker Container - make sure that you have the latest pg dependency installed:
https://github.com/brianc/node-postgres/issues/2180
Alternatively: Downgrade to Node 12.
Also make sure, that both the database and the "backend" are in the same network. Also: the backend should best "depend" on the database.
version: '3'
services:
wallnerbackend:
build:
context: ./backend/
dockerfile: ../Dockerfiles/server.dockerfile
ports:
- '8080:8080'
networks:
- default
depends_on:
- wallnerdatabase
wallnerdatabase:
build:
context: .
dockerfile: ./Dockerfiles/postgresql.dockerfile
ports:
- '5432:5432'
volumes:
- db-data:/var/lib/postgresql/data
env_file: .env_docker
networks:
- default
volumes:
db-data:
networks:
default:
This should not be necessary in you case - as pointed out in the comments - since Docker Compose already creates a default network
The container name "wallnerdatabase" is the host name of your database - if not configured otherwise.
I expect the issue to be in the database connection URL since you did not share it.
Containers in the same network in a docker-compose.yml can reach each other using the service name. In your case the service name of the database is wallnerdatabase so this is the hostname that you should use in the database connection URL.
The database connection URL that you should use in your backend service should be similar to this:
postgres://user:password#wallnerdatabase:5432/dbname
Also make sure that the backend code is calling the database using the hostname wallnerdatabase as it is defined in the docker-compose.yml file.
Here is the reference on Networking in Docker Compose.
You should access your DB using service name as hostname. Here is my working example - https://gitlab.com/gintsgints/vue-fullstack/-/blob/master/docker-compose.yml
I have a sample app which consists of three parts:
mongo database
node api (server side)
angular web app (client side)
the goal is to containerize those three parts and run the app.
so to reach there I've created docker-compose.yml file like below:
# docker-compose -f docker-compose.prod.yml build
# docker-compose -f docker-compose.prod.yml up -d
# docker-compose -f docker-compose.prod.yml down
version: '3'
services:
mongodb:
image: mongo
container_name: mongodb-instance-microservices
ports:
- "27020:27017"
networks:
- microservices-network
client:
container_name: client-instance-microservices
image: client-microservices
build:
context: ./client
dockerfile: prod.dockerfile
ports:
- "8080:80"
- "443:443"
depends_on:
- api
networks:
- microservices-network
api:
container_name: api-instance-microservices
image: api-microservices
build:
context: ./server
dockerfile: server.dockerfile
environment:
- NODE_ENV=production
ports:
- "3000:3000"
depends_on:
- mongodb
networks:
- microservices-network
networks:
microservices-network:
driver: bridge
in the server side i am running the main app.js which is trying to connect to the mongodb using this connection string:
mongodb://mongodb-instance-microservices:27020/TestDatabase
the problem is the server can not connect to the mongo db container.
i tried to expose the default port for mongo like below:
mongodb:
image: mongo
container_name: mongodb-instance-microservices
ports:
- "27017:27017"
networks:
- microservices-network
and update the connection string in the app.js file like this:
mongodb://mongodb-instance-microservices:27017/TestDatabase
and it's work fine.
the question is how to expose different port for mongo container and make it work fine?
When you connect between services using a Docker-internal network, you always connect to the internal port of the service. You don't explicitly need to publish ports (in Compose, with a ports: directive); if you do, the port you'd connect to is the one on the right.
Style-wise, also note that you don't need to manually declare a private network with default options that will only be used within this Docker Compose file (Compose will do something very similar to that for you), and you don't need to declare container_name: just for inter-container connectivity (Compose will add a network alias that matches the name of the service).