Get host-address of other containers - docker-compose

I have a specific issue related to Docker compose.
I am currently using docker compose version: 3.8
I have a gateway build in nodejs
I need to get the container address of other application available in the gateway as environment variable.
I looked into various documents but none of them are working.
version: "3.8"
services:
user_service:
build:
context: ./user-service
environment:
NODE_PORT: 4000
authentication_service:
build:
context: ./authentication_service
environment:
NODE_PORT: 3001
gateway:
build: ./public-gateway
environment:
- NODE_PORT=2000
- USER_SERVICE=user_service
depends_on:
- user_service
- authentication_service
links:
- user_service:user_service
restart: always
Above is the docker compose file.
But in the gateway code i am not able to get the host address of USER_SERVICE.
I also read that links are deprecated in version 3.8 and host address are automatically available in all the application within the same network.
I printed process.env in nodejs application but i all i see is USER_SERVICE: user_service
I would really appreciate it if someone can pint me in the correct direction.
I would like to see the host address of the USER_SERVICE when i print process.env.USER_SERVICE in the nodejs application
Updated docker compose file which is working
version: "3.8"
services:
user_service:
build:
context: ./user-service
environment:
NODE_PORT: 4000
authentication_service:
build:
context: ./authentication_service
environment:
NODE_PORT: 3001
gateway:
build: ./public-gateway
environment:
- NODE_PORT=2000
- USER_SERVICE=http://user_service:4000/user/service
depends_on:
- user_service
- authentication_service
restart: always
Note: During run time of docker
USER_SERVICE=http://user_service:4000/user/service
user_service will be replaced by ip address. Even if you print the environment variable[USER_SERVICE] it would show http://user_service:4000/user/service.
user_service This would be resolved by the DNS.

Related

DOCKER_Cannot run multiple services by docker-compose

I'm set up docker compose for my project with 2 services: spring-boot and postgresql. I created Dockerfile and docker-compose,yml as below:
Dockerfile :
FROM openjdk:8-jdk-alpine
MAINTAINER linhan.com
COPY target/LinhAn-0.0.1-SNAPSHOT.jar linhan-server-1.0.0.jar
ENTRYPOINT ["java","-jar","/linhan-server-1.0.0.jar"]
docker-compose.yml:
version: '2'
services:
spring_boot:
image: 'linhan'
build: .
container_name: api
ports:
- "8080:8080"
depends_on:
- postgres
environment:
- SPRING_DATASOURCE_URL=jdbc:jdbc:postgresql://localhost:5432/test_db
- SPRING_DATASOURCE_USERNAME=user
- SPRING_DATASOURCE_PASSWORD=123456
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
postgres:
image: 'postgres:13.1-alpine'
container_name: db
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=123456
Then, when I type docker-compose up in terminal, postgres ran only, spring boot still not.
I searched google for solution but seems no hope. Please help me, thanks a lot!!!!!
I think you need to change the SPRING_DATASOURCE_URL to reference your service name instead of localhost. The service name is resolved automatically to your service since all services are part of the default_network by default in docker-compose.
- SPRING_DATASOURCE_URL=jdbc:jdbc:postgresql://postgres:5432/test_db
Also, for clarity I would suggest you add the port to your docker-compose postgres service, so it is clear which port is being used, even if it is the default:
postgres:
image: 'postgres:13.1-alpine'
container_name: db
ports:
- "5432"
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=123456
Also, another suggestion would be to try and use a healthcheck to see if your database service becomes available instead of a simple depends_on. The short version will mark the dependency fulfilled as soon as the container is Running, regardless of the availability of the database.
Either that, or you can add application logic to retry database connection in case of failure.

How to resolve docker name resolution failure?

Below is my docker compose file:
version: '3.7'
# Run tests in much the same way as circleci
# docker-compose -f docker-compose.test.yml up
# TODO check aws versions
services:
db:
# image: circleci/postgres:11-alpine
image: kotify/postgres-non-durable:11.2
env_file: .env-test
container_name: limetonic_db
ports:
- 5433:5432
redis:
image: circleci/redis:6.2.1-alpine
selenium:
image: selenium/standalone-chrome:89.0
container_name: limetonic_selenium
shm_size: '2gb'
environment:
TZ: "Australia/Sydney"
ports:
- 4444:4444
test:
build:
context: .
dockerfile: Dockerfile
env_file: .env-test
depends_on:
- redis
- db
- selenium
command: bash -c "make ci.test"
The db, redis, selenium containers have DNS as 127.0.0.11 while test has 8.8.8.8. Now I am spinning a django server at test:8000 but it does not come up with name resolution failure which I understand is coming from 8.8.8.8 DNS.
I have read many questions on SO but none of the solutions work. I have modified DOCKER_OPTS and changes dnsmasq etc. Now this problem occurs in stock ubuntu installation and any changes made does not work.
It does not matter what DNS is in docker test container it won't resolve test.
Note that db, selenium and redis can ping each other but obviously test cannot.
My systemd-resolv has DNS as 4.2.2.2 and 8.8.8.8 that is why test is not resolving. I understand that docker does not take 127.0.0.11 as DNS. However, if that is the case how other images can resolve with the local DNS? And even if I set DNS of test container to 127.0.0.11 it still does not resolve test?

Make an API call from one container to another

I have a node application , a next.js app for front end ,Redis and Postgres as databases . I have dockerized Next.js and node.js in different containers .
Docker-compose.yaml is as follows
version: '3'
services:
redis-server:
image: 'redis'
restart: always
postgres-server:
image: 'postgres:latest'
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=postgres
ports:
- "5433:5432"
volumes:
- ./docker/postgres/data/data/pg_hba.conf:/var/lib/postgresql/app_data/pg_hba.conf
- ./src/db/sql/CREATE_TABLES.sql:/docker-entrypoint-initdb.d/CREATE_TABLES.sql
- ./src/db/sql/INSERT_TO_TABLES.sql:/docker-entrypoint-initdb.d/INSERT_TO_TABLES.sql
- ./src/db/sql/CREATE_FUNCTIONS.sql:/docker-entrypoint-initdb.d/CREATE_FUNCTIONS.sql
node-app:
build: .
ports:
- "4200:4200"
client:
build:
context: ./client
dockerfile: Dockerfile
container_name: client
restart: always
volumes:
- ./:/app
- /app/node_modules
- /app/.next
ports:
- 3000:3000
When using SSR , I cannot make a request to localhost:4200 .Now, I get that it is because they are in different containers and if the request is not from client side , then the client container is being checked for server at port 4200. Now , I am not sure how to simply refer to the container using the container name or something to make an API request for the SSR data (like fetch('node-app/users'))
docker-compose sets up a network for all the services in a compose file. To reach another container in the network, you use the name of that container as a hostname, and it will resolve to the right ip.
So in your case doing fetch('http://node-app:4200/users') should do the trick.

How can i link mongodb with other services in docker-compose?

i got a problem.
I made a docker-compose that runs mongo and node.
The problem is there is no way i use mongo from the container, i cannot start my node server.
Here there is my docker-compose :
version: '3'
services:
database:
build: ./Database
container_name: "dashboard_database"
ports:
- "27017:27017"
backend:
build: ./Backend
container_name: "dashboard_backend"
ports:
- "8080:8080"
depends_on:
- database
links:
- database
But when i start mongo without the container my node can reach it, i don't know why ...
Any idea ?
Thanks !
Dont define ports in the DB service. But afterwards only application will be able to access DB. Most probably it will work then. If you still want to access it from your PC then you should define a network. Try this
version: '3'
services:
database:
build: ./Database
container_name: "dashboard_database"
backend:
build: ./Backend
container_name: "dashboard_backend"
ports:
- "8080:8080"
depends_on:
- database
links:
- database
And for creating network
version: '3'
networks:
back-tier:
services:
database:
build: ./Database
container_name: "dashboard_database"
networks:
- back-tier
ports:
- "27017:27017"
backend:
build: ./Backend
container_name: "dashboard_backend"
networks:
- back-tier
ports:
- "8080:8080"
depends_on:
- database
All services in docker-compose are within the docker-compose created network, and can be addressed by their service names from other services. In your case the service names are database and backend, so for instance the database can be accessed by the backend with something like tcp://database:27017. You don't need to link them anymore.
https://runnable.com/docker/docker-compose-networking
Be aware depends_on only waits until the process has been started and does not wait for the process to be ready to accept connections.
https://docs.docker.com/compose/compose-file/#depends_on
https://docs.docker.com/compose/startup-order
The port mappings are only necessary if you want to make a service accessible from the local machine. In your examplte the backend service is accessible via localhost:8080.
If you want an external container to access a docker-compose service tne localhost:8080 wont work because localhost in the container isn't the same localhost as on your local machine where docker containers are running. You can create manually a docker network and connect the container and docker-compose services to it. See docker-compose-networking link and take a look at section Pre-existing Networks.
Does that help you?

How to add new port to one of docker-compose services without restarting all of them?

I have 'docker-compose.yml' file like below (skipped only volumes. environment and network). I would like to add new port to 'logstash' service without restarting all 3 services. I did 'docker-compose build logstash --no-cache' but it didn't add the port
docker#ubuntu-elastic:~/docker-elk$ cat docker-compose.yml
version: '2'
services:
elasticsearch:
build:
context: elasticsearch/
ports:
- "9200:9200"
- "9300:9300"
logstash:
build:
context: logstash/
ports:
- "11514:11514/udp"
- "8514:8514/udp"
depends_on:
- elasticsearch
kibana:
build:
context: kibana/
ports:
- "5601:5601"
depends_on:
- elasticsearch
This will do the trick:
docker-compose up -d logstash
If you do not change the other sections, this should also only update logstash:
docker-compose up -d
To make sure that only logstash gets updated, even if the other sections where updated too, use the first command.