I have container for two NodeJS services and one Nginx for reverse-proxy.
I have make NGINX on port 80 so it's publicly available via localhost on my browser
I also use reverse-proxy to proxy_pass to each responsible service.
location /api/v1/service1/ {
proxy_pass http://service1:3000/;
}
location /api/v1/service2/ {
proxy_pass http://service2:3000/;
}
In my service 1, there is an axios module that wants to call to service 2 by making a request to localhost/api/v1/service2
But, it says that connection is refused. I doubt if the localhost in service 1 refer to its container, not the docker host.
version: '3'
services:
service1:
build: './service1'
networks:
- backend
service2:
build: './service2'
networks:
- backend
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- backend
networks:
backend:
driver: bridge
Even after using network, it still says ECONNREFUSED.
Please help.
Try adding the depends_on in your docker-compose file for the nginx, like below:
version: '3'
services:
service1:
build: './service1'
expose:
- "3000"
networks:
- backend
service2:
build: './service2'
expose:
- "3000"
networks:
- backend
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- backend
depends_on:
- service1
- service2
networks:
backend:
driver: bridge
This would make sure that both services are running first before the nginx container attempts to connect to them. Perhaps the connection is refused because the nginx container keeps crashing due to it not finding the two services running when it executes its conf file and connect to the backends.
Related
I came across a docker-compose.yml which has following port configuration:
wsgi:
ports:
- 9090 // ?? Is it by default mapped to host port 80 ??
nodejs
image: nodejs:myapp
ports:
- 9999:9999
environment:
BACKEND_API_URL: http://aa.bb.cc.dd:9854/api/
haproxy
ports:
- 9854:80
I am trying to understand how the port wiring is happening here.
nodejs UI app settings needs to specify backend port which is 9854 here. This port is exposed by haproxy setting and is mapped to port 80. I know that wsgi is a django backend app. From its entrypoint.sh (in PS below) and port specification in above docker-compose.yml, I get that django listens to port 9090. But I am unable to get how this port 9090 maps to port 80 (which is then exposed by haproxy at 9854, which in turn is specified in BACKEND_API_URL by nodejs settings).
PS:
Django wsgi app has following in \wsgi\entrypoint.sh:
nohup gunicorn myapp.wsgi --bind "0.0.0.0:9090"
And nodejs react app has following in its server.js file:
const port = process.env.PORT || 9999;
My whole docker compose file:
version: "3.8"
services:
postgres:
image: postgres:11
volumes:
- my_app_postgres_volume:/var/lib/postgresql/data
- type: tmpfs
target: /dev/shm
tmpfs:
size: 536870912 # 512MB
environment:
POSTGRES_DB: my_app_db
POSTGRES_USER: my_app
POSTGRES_PASSWORD: my_app123
networks:
- my_app_network
redis:
image: redis:6.2.4
volumes:
- my_app_redis_volume:/data
networks:
- my_app_network
wsgi:
image: wsgi:my_app3_stats
volumes:
- /my_app/frontend/static/
- ./wsgi/my_app:/my_app
- /my_app/frontend/clientApp/node_modules
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
- postgres
- redis
ports:
- 9090
environment:
C_FORCE_ROOT: 'true'
SERVICE_PORTS: 9090
networks:
- my_app_network
deploy:
replicas: 1
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
max_attempts: 3
window: 120s
nodejs:
image: nodejs:my_app3_stats
volumes:
- ./nodejs/frontend:/frontend
- /frontend/node_modules
depends_on:
- wsgi
ports:
- 9999:9999
environment:
BACKEND_API_URL: http://aa.bb.cc.dd:9854/api/
networks:
- my_app_network
nginx:
image: isiq/nginx-brotli:1.21.0
volumes:
- ./nginx:/etc/nginx/conf.d:ro
- ./wsgi/my_app:/my_app:ro
- my_app_nginx_volume:/var/log/nginx/
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
networks:
- my_app_network
haproxy:
image: haproxy:2.3.9
volumes:
- ./haproxy:/usr/local/etc/haproxy/:ro
- /var/run/docker.sock:/var/run/docker.sock
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
- wsgi
- nodejs
- nginx
ports:
- 9854:80
networks:
- my_app_network
deploy:
placement:
constraints: [node.role == manager]
volumes:
my_app_postgres_volume:
my_app_redis_volume:
my_app_nginx_volume:
networks:
my_app_network:
driver: overlay
On your host, there are three ports visible:
http://aa.bb.cc.dd:9854 forwards to port 80 on the haproxy container.
http://aa.bb.cc.dd:9999 forwards to port 9999 on the nodejs container.
The port shown by docker-compose port wsgi 9090 forwards to port 9090 on the wsgi container.
You don't discuss the HAProxy configuration at all, but it is presumably configured to listen on port 80, and that may be the missing bit of configuration you're looking for.
Between these three containers (so not visible to your front-end application), assuming you don't have any networks: blocks in the Compose file, there are three obvious URLs: http://haproxy:80 (or just http://haproxy), http://nodejs:9999, and http://wsgi:9090 connect to their respective containers. Note that these use the "normal" ports for their service, and not the remapped port for haproxy or the randomly-chosen port for wsgi.
I'm guessing the HAProxy container is configured to do some sort of path-based routing to one or the other of the other containers. If you have this setup, you might be able to configure your React application to not include a host name in the URL at all (BACKEND_API_URL: /api/), which will make it easier to deploy. You do not need the ports: for connections between containers, and if you don't want a caller to be able to reach the back-end services without going via the proxy, you can delete their ports: blocks.
Trying to learn to deploy angular app to azure web app using multi-container, the frontend loads fine but cant connect to the backend node container, I want to add the url of the node backend to my angular frontend but i cant figure out what it is. I've tried https://rojesh.azure.io:3000, https://rojesh.azurewebsites.net:3000, http://server:3000 and more but nothing seems to work. Website Hostname: https://rojesh.azurewebsites.net and the acr name is rojesh.azurecr.io which has 3 images. This is my config file for compose in azure:
version: '3.3'
services:
db:
image: rojesh.azurecr.io/db:latest
ports:
- "27017:27017"
restart: always
networks:
- app-network
server:
image: rojesh.azurecr.io/server:latest
depends_on:
- db
ports:
- "3000:3000"
restart: always
networks:
- app-network
app:
depends_on:
- server
image: rojesh.azurecr.io/app:latest
environment:
NGINX_HOST: rojesh.azurewebsites.net
NGINX_PORT: 80
ports:
- "80:80"
restart: always
networks:
- app-network
networks:
app-network:
driver: bridge
The app works fine locally using docker compose which is:
version: '3.9'
services:
docker-app:
build:
context: app
dockerfile: Dockerfile.dev
ports:
- '4200:4200'
volumes:
- ./app/src:/app/src
docker-server:
build:
context: server
dockerfile: Dockerfile
environment:
PORT: 3000
MONGODB_URI: mongodb://mongo:27017/rojesh
JWT_SECRET: secret
ports:
- 3000:3000
depends_on:
- mongo
volumes:
- ./server:/server
mongo:
container_name: mongo-server
image: mongo:latest
ports:
- 27017:27017
Thanks # ajkuma-msft. Azure App Service only exposes ports 80 and 443. Yes, incoming requests from client would just be over 443/80 which should be mapped to the exposed port of the container.
App Service will attempt to detect which port to bind to your container. If you want to bind to your container the WEBSITES_PORT app setting and configure it with a value of the port.
Web App for Containers currently allows you to expose only one port to the outside world. The container can only listen for HTTP requests on a single port.
From Docker compose configuration stand-point : Ports other than 80 and 8080 are ignored.
Refer Docker Compose options lists shows supported and unsupported Docker Compose configuration options.
Refer here
My client isn't able to send requests to backend because it can't resolve the host. I'm trying to pass down the container connection info via an environment variable and use it in the client to connect. However, it is unable to do the requests at all. Any help? Nginx works fine for the frontend part but doesn't work for proxying the backend.
docker-compose.yml
version: '3.2'
services:
server:
restart: always
build:
dockerfile: Dockerfile
context: ./nginx
depends_on:
- backend
- frontend
- database
ports:
- '5000:80'
database:
image: postgres:latest
container_name: database
ports:
- "5432:5432"
restart: always
hostname: database
expose:
- 5432
backend:
build:
context: ./backend
dockerfile: ./Dockerfile
image: kalendae_backend:latest
hostname: backend
container_name: backend
ports:
- "5051:5051"
environment:
- WAIT_HOSTS=database:5432
- DATABASE_HOST=database
- DATABASE_PORT=5432
- PORT=5051
links:
- database
expose:
- 5051
frontend:
build:
context: ./frontend
dockerfile: ./Dockerfile
image: kalendae_frontend:latest
ports:
- "5050:5050"
hostname: frontend
container_name: frontend
environment:
- WAIT_HOSTS=backend:5051
- REACT_APP_BACKEND_HOST=backend
- REACT_APP_BACKEND_PORT=5051
links:
- backend
expose:
- 5050
Nginx config
upstream frontend {
server frontend:5050;
}
upstream backend {
server backend:5051;
}
upstream server {
server server:5000;
}
server {
listen 80;
location / {
proxy_pass http://frontend;
}
location backend {
proxy_pass http://backend;
}
location /backend {
proxy_pass http://backend;
}
}
i'm kinda new to docker so sorry if my terminology is a little wrong. I'm in the process of getting my app to run in docker. Everything is starting up and running correctly but i'm unable to set the ip address that the services are running on. I need to do so since i'm making api calls that previously referenced a static variable in my js code. The spark service especially is important for me to have a knowable ip, as of now its randomly assigned.
docker-compose.yml
version: '3.0' # specify docker-compose version
services:
vue:
build: client
ports:
- "80:80" # specify port mapping
spark:
build: accubrew-spark
ports:
- "8080:8080"
express:
build: server
ports:
- "3000:3000"
links:
- database
database:
image: mongo
ports:
- "27017:27017"```
When you're running containers using docker-compose it creates a user-defined network for you and docker provides an embedded DNS servers, each container will have a record resolvable only within the containers of the network.
This makes it easy for you to know how to contact each service by just calling them by the name you specified on your docker-compose.yml.
You can try this:
version: '3.0' # specify docker-compose version
services:
vue:
build: client
ports:
- "80:80" # specify port mapping
spark:
build: accubrew-spark
ports:
- "8080:8080"
networks:
my_net:
ipv4_address: 172.26.0.3
express:
build: server
ports:
- "3000:3000"
links:
- database
database:
image: mongo
ports:
- "27017:27017"
networks:
my_net:
ipam:
driver: default
config:
- subnet: 172.26.0.0/16
But yours spark port is localhost:8080, if you need to expose other port with the ip 172.26.0.0, you can do - "7077" or with the localhost: -"7077:7077" this is an example with the port 7077 expose:
version: '3.0' # specify docker-compose version
services:
vue:
build: client
ports:
- "80:80" # specify port mapping
spark:
build: accubrew-spark
ports:
- "8080:8080"
- "7077"
networks:
my_net:
ipv4_address: 172.26.0.3
express:
build: server
ports:
- "3000:3000"
links:
- database
database:
image: mongo
ports:
- "27017:27017"
networks:
my_net:
ipam:
driver: default
config:
- subnet: 172.26.0.0/16
I have a microservice based node app. I am using docker, docker-compose and traefik for service discovery.
I have 2 microservices at this moment:
the server app: running at node-app.localhost:8000
the search microservice running at search-microservice.localhost:8002
The issue I can't make a request from one microservice to another.
Here are my docker compose config:
# all variables used in this file are defined in the .env file
version: "2.2"
services:
node-app-0:
container_name: node-app
restart: always
build: ./backend/server
links:
- ${DB_HOST}
depends_on:
- ${DB_HOST}
ports:
- "8000:3000"
labels:
- "traefik.port=80"
- "traefik.frontend.rule=Host:node-app.localhost"
reverse-proxy:
image: traefik # The official Traefik docker image
command: --api --docker # Enables the web UI and tells Traefik to listen to docker
ports:
- "80:80" # The HTTP port
- "8080:8080" # The Web UI (enabled by --api)
volumes:
- /var/run/docker.sock:/var/run/docker.sock
search-microservice:
container_name: ${CONTAINER_NAME_SEARCH}
restart: always
build: ./backend/search-service
links:
- ${DB_HOST}
depends_on:
- ${DB_HOST}
ports:
- "8002:3000"
labels:
- "traefik.port=80"
- "traefik.frontend.rule=Host:search-microservice.localhost"
volumes:
node-ts-app-volume:
external: true
Both the node-app and the search-microservice expose the port 3000.
Why can't I call http://search-microservice.localhost:8002 from the node app ? calling it from the browser works though.
Because node-app is a container and to access other containers it has to use service name and internal port.
In your case it is search-microservice:3000.
To access host PC and exposed ports, you have to use host.docker.internal name for all services and external port.
If you want to access other services from in a different container with their hostnames, you can use the "extra_hosts" parameter in your docker-compose.yml file. Also, you have to use the "ipv4_address" parameter under the network parameter for each all services.
For example;
services:
node-app-1:
container_name: node-app
networks:
apps:
ipv4_address: 10.1.3.1
extra_hosts:
"search-microservice.localhost:10.1.3.2"
node-app-2:
container_name: search-microservice
networks:
apps:
ipv4_address: 10.1.3.2
extra_hosts:
"node-app.localhost:10.1.3.1"
Extra hosts in docker-compose