Sending Http request from one docker container to another - docker

I am running multiple docker containers. I want to invoke a graphql Hasura api running on a docker container from a node js application running on another container. I am unable to use same url - (http:///v1/graphql) that I use to access the Hasura api for accessing from node js application.
I tried http://localhost/v1/graphql but that is not also working.
The following is the docker compose file for Hasura graphql
version: '3.6'
services:
postgres:
image: postgis/postgis:12-master
restart: always
volumes:
- db_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: <postgrespassword>
pgadmin:
image: dpage/pgadmin4
restart: always
depends_on:
- postgres
ports:
- 5050:80
## you can change pgAdmin default username/password with below environment variables
environment:
PGADMIN_DEFAULT_EMAIL: <email>
PGADMIN_DEFAULT_PASSWORD: <pass>
graphql-engine:
image: hasura/graphql-engine:v1.3.0-beta.3
depends_on:
- "postgres"
restart: always
environment:
# database url to connect
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword#postgres:5432/postgres
# enable the console served by server
HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set "false" to disable console
## uncomment next line to set an admin secret key
HASURA_GRAPHQL_ADMIN_SECRET: <secret>
HASURA_GRAPHQL_UNAUTHORIZED_ROLE: anonymous
HASURA_GRAPHQL_JWT_SECRET: '{ some secret }'
command:
- graphql-engine
- serve
caddy:
image: abiosoft/caddy:0.11.0
depends_on:
- "graphql-engine"
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/Caddyfile
- caddy_certs:/root/.caddy
volumes:
db_data:
caddy_certs:
The caddy file has the following configuration:
# replace :80 with your domain name to get automatic https via LetsEncrypt
:80 {
proxy / graphql-engine:8080 {
websocket
}
}
What is the api end point I should be using from another docker container (not present in this docker-compose) to access the hasura api? From browser I use http://#ipaddress /v1/graphql.
What is the configuration of caddy actually do here?

Related

docker(-compose): access wikijs container only through nginx-proxy-manager; 502 Bad Gateway

I'm running a server that I want to setup to provide several webservices. One service is WikiJS.
I want the service to only be accessible through nginx-proxy-manager via a subdomain, but not directly accessing the IP (and port) of the server.
My try was:
version: "3"
services:
nginxproxymanager:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
# These ports are in format <host-port>:<container-port>
- '80:80' # Public HTTP Port
- '443:443' # Public HTTPS Port
- '8181:81' # Admin Web Port
# Add any other Stream port you want to expose
# - '21:21' # FTP
# Uncomment the next line if you uncomment anything in the section
# environment:
# Uncomment this if you want to change the location of
# the SQLite DB file within the container
# DB_SQLITE_FILE: "/data/database.sqlite"
# Uncomment this if IPv6 is not enabled on your host
# DISABLE_IPV6: 'true'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- reverseproxy-nw
db:
image: postgres:11-alpine
environment:
POSTGRES_DB: wiki
POSTGRES_PASSWORD: ###DBPW
POSTGRES_USER: wikijs
logging:
driver: "none"
restart: unless-stopped
volumes:
- db-data:/var/lib/postgresql/data
networks:
- reverseproxy-nw
wiki:
image: requarks/wiki:2
depends_on:
- db
environment:
DB_TYPE: postgres
DB_HOST: db
DB_PORT: 5432
DB_USER: wikijs
DB_PASS: ###DBPW
DB_NAME: wiki
restart: unless-stopped
ports:
- "3001:3000"
networks:
- reverseproxy-nw
volumes:
db-data:
networks:
reverseproxy-nw:
external: true
In nginx-proxy-manager I then tried to use "wikijs" as the forwarding host.
The service is accessible if I try: http://publicip:3001, however not via the assigned subdomain in nginx-proxy-manager. I only get a 502 which usually means, that nginx-proxy-manager cannot access the given service.
What do I have to change to make the service available unter the domain but not from http://publicip:3001 ?
Thanks in advance.
Ok, I finally found out what my conceptual problem was:
I needed to create a network bridge for the two containers. Basically it was as basic as specifying the driver of the network:
networks:
reverseproxy-nw:
driver: bridge
Like this the wikijs-container is only available through nginx as I want it to be.

Can't access pgadmin4 from nginx-proxy-manager

I have setup multiple containers on my server and I want to access them through a more friendly url; So I've also setup nginx-proxy-manager. Every other container is accessible except for pgadmin4.
Other containers like Grafana or Prometheus are accessible from the nginx-proxy-manager, but pgadmin4 can only be accessed by hitting the IP:PORT directly. By typing pgadmin.keivanipchihagh.ir I'll get: Bad gateway Error code 502 (do visit the website for more info on the error)
My pgadmin4 docker-compose.yml:
version: '3.5'
services:
# pgadmin4
pgadmin:
container_name: ${PGDAMIN_CONTAINER_NAME:-pgadmin}
image: dpage/pgadmin4:6.13
restart: unless-stopped
user: "$UID:$GID"
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_EMAIL}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD}
PGADMIN_CONFIG_SERVER_MODE: 'True'
volumes:
- ./pgadmin-data:/var/lib/pgadmin
ports:
- "${PGADMIN_PORT:-5050}:80"
networks:
- epd
networks:
epd:
external: true
Also my nginx-proxy-manager config (just like any other container I've setup already):
Any Ideas?

How to allow a docker container to communicate with another container over localhost

I have a unique situation where I need to be able to access a container over a custom local domain (example.test), which I've added to my /etc/hosts file which points to 127.0.0.1. The library I'm using for OIDC uses this domain for redirecting the browser and if it is an internal docker hostname, obviously the browser will not resolve.
I've tried pointing it to example.test, but it says it cannot connect. I've also tried looking up the private ip of the docker network, and that just times out.
Add the network_mode: host to the service definition of the calling application in the docker-compose.yml file. This allows calls to localhost to be routed to the server's localhost and not the container's localhost.
E.g.
docker-compose.yml
version: '3.7'
services:
mongodb:
image: mongo:latest
restart: always
logging:
driver: local
environment:
MONGO_INITDB_ROOT_USERNAME: ${DB_ADMIN_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${DB_ADMIN_PASSWORD}
ports:
- 27017:27017
volumes:
- mongodb_data:/data/db
callingapp:
image: <some-img>
restart: always
logging:
driver: local
env_file:
- callingApp.env
ports:
- ${CALLING_APP_PORT}:${CALLING_APP_PORT}
depends_on:
- mongodb
network_mode: host // << Add this line
app:
image: <another-img>
restart: always
logging:
driver: local
depends_on:
- mongodb
env_file:
- app.env
ports:
- ${APP_PORT}:${APP_PORT}
volumes:
mongodb_data:

Can not send post request to nuxeo server over docker container

I can send post request to Nuxeo server using http://localhost:8080 base address from local. When I add docker support to my app, my app can not send post request to nuxeo server using http://nuxeo_container_name:80 base address. It returns badRequest. How can I solve it? Nuxeo server and app are in the same docker network.
This is my docker-compose for nuxeo server. I use nuxeo_app_server in my app as nuxeo container name.
version: "3.5"
networks:
nuxnet:
name: network
services:
nginx:
container_name: nuxeo_app_server
build: nginx
ports:
# For localhost use, the exposed nginx port
# must match the localhost:port below in NUXEO_URL
- "8080:80"
#- "443:443"
cap_add:
- NET_BIND_SERVICE
links:
- nuxeo1
# - nuxeo2
environment:
USE_STAGING: 1
# default is 4096, but gcloud requires 2048
KEYSIZE: 2048
DOMAIN_LIST: /etc/nginx/conf.d/domains.txt
devices:
- "/dev/urandom:/dev/random"
sysctls:
- net.core.somaxconn=511
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- certs:/etc/ssl/acme
networks:
- nuxnet
restart: always
nuxeo1:
image: nuxeo
hostname: nuxeo1
links:
- redis
- es
- db
env_file:
- ./nuxeo/setup.env
environment:
# Each nuxeo container must have a unique cluster id
NUXEO_CLUSTER_ID: 1
# URL that a user would use to access nuxeo UI or API
# For localhost urls, the port must match the exposted nginx port above
NUXEO_URL: http://localhost:8080/nuxeo
# JAVA memory tuning -Xms, -Xmx
JVM_MS: 1024m
JVM_MX: 2048m
devices:
- "/dev/urandom:/dev/random"
volumes:
- ./nuxeo/init:/docker-entrypoint-initnuxeo.d:ro
- app-data:/var/lib/nuxeo
- app-logs:/var/log/nuxeo
networks:
- nuxnet
restart: always
redis:
# note: based on alpine:3.6
# see https://hub.docker.com/_/redis/
image: redis:3.2-alpine
volumes:
- redis-data:/data
networks:
- nuxnet
restart: always
es:
image: elasticsearch:2.4-alpine
volumes:
- es-data:/usr/share/elasticsearch/data
- es-plugins:/usr/share/elasticsearch/plugins
- es-config:/usr/share/elasticsearch/config
- ./elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
environment:
# settings below add -Xms400m -Xmx1g
ES_MIN_MEM: 500m
EX_MAX_MEM: 1g
security_opt:
- seccomp:unconfined
networks:
- nuxnet
restart: always
db:
image: postgres:9.6-alpine
# note mem tuning suggestions in the following two links
# https://doc.nuxeo.com/nxdoc/postgresql/
# https://doc.nuxeo.com/nxdoc/postgresql/#adapt-your-configuration-to-your-hardware
environment:
POSTGRES_USER: nuxeo
POSTGRES_PASSWORD: nuxeo
POSTGRES_DB: nuxeo
POSTGRES_INITDB_ARGS: "-E UTF8"
PGDATA: /var/lib/postgresql/data
volumes:
- db-store:/var/lib/postgresql/data
- ./postgresql/postgresql.conf:/etc/postgresql.conf:ro
command: postgres -c config_file=/etc/postgresql.conf
networks:
- nuxnet
restart: always
volumes:
# to view current data, run bin/view-data.sh
certs:
app-logs: # all server logs, can be shared between instances
app-data: # contains app data and packages (store cache), can be shared between instances
db-store: # postgres database
es-data:
es-plugins:
es-config:
redis-data:
I succeed to make REST request between two containers using container name and default port.
Did you try with URL : http://nuxeo1:8080 ?

Docker compose containers communication

I have 7 docker containers namely
es_search
postgres_db
fusionauth
mysql_db
auth
backend
ui
The communication between containers should be like below
fusionauth should be able to contact es_search, postgres_db
backend should be able to contact auth, mysql_db
auth should be able to contact fusionauth, backend
ui should be able to contact backend, auth
Existing docker-compose
version: '3.1'
services:
postgres_db:
container_name: postgres_db
image: postgres:9.6
environment:
PGDATA: /var/lib/postgresql/data/pgdata
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
ports:
- ${POSTGRES_PORT}:5432
networks:
- postgres_db
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data_test
es_search:
image: docker.elastic.co/elasticsearch/elasticsearch:6.3.1
container_name: es_search
environment:
- cluster.name=fusionauth
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=${ES_JAVA_OPTS}"
ports:
- ${ES1_PORT}:9200
- ${ES_PORT}:9300
networks:
- es_search
restart: unless-stopped
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- es_data:/usr/share/elasticsearch/data
fusionauth:
image: fusionauth/fusionauth-app:latest
container_name: fusionauth
depends_on:
- postgres_db
- es_search
environment:
DATABASE_URL: jdbc:postgresql://postgres_db:5432/fusionauth
DATABASE_ROOT_USER: ${POSTGRES_USER}
DATABASE_ROOT_PASSWORD: ${POSTGRES_PASSWORD}
DATABASE_USER: ${DATABASE_USER}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
FUSIONAUTH_MEMORY: ${FUSIONAUTH_MEMORY}
FUSIONAUTH_SEARCH_SERVERS: http://es_search:9200
FUSIONAUTH_URL: http://fusionauth:9010
networks:
- postgres_db
- es_search
restart: unless-stopped
ports:
- ${FUSIONAUTH_PORT}:9011
volumes:
- fa_config:/usr/local/fusionauth/config
db:
container_name: db
image: mysql:5.7
volumes:
- /etc/nudjur/mysql_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_USER=${MYSQL_USER}
ports:
- ${MYSQL_PORT}:3306
command: --default-authentication-plugin=mysql_native_password
restart: on-failure
backend:
container_name: backend
links:
- db:${MYSQL_HOST}
depends_on:
- db
image: ${BACKEND_IMAGE}
volumes:
- ${ENV_FILE}:/backend/.env
ports:
- ${BACKEND_PORT}:${BACKEND_PORT}
command: >
bash -c "set -a && source .env && set +a"
restart: unless-stopped
UI:
container_name: UI
image: ${UI_IMAGE}
volumes:
- ${ENV_FILE}:/nudjur/.env
ports:
- ${UI_PORT}:${UI_PORT}
command: >
bash -c "PORT=${UI_PORT} npm start"
restart: unless-stopped
auth:
container_name: auth
network_mode: host
image: ${AUTH_IMAGE}
volumes:
- ${ENV_FILE}:/auth/.env
ports:
- ${AUTH_PORT}:${AUTH_PORT}
command: >
bash -c "set -a && source .env && set +a && python3 ./auth_bridge.py --log-level DEBUG run -p ${AUTH_PORT}"
restart: unless-stopped
networks:
postgres_db:
driver: bridge
es_search:
driver: bridge
volumes:
db_data:
es_data:
fa_config:
I am confused about how to establish communication between them.
Can someone help me with this?
I understand you want to restrict communications so that containers can only communicate with other services such as:
fusionauth should be able to contact es_search, postgres_db
backend should be able to contact auth, mysql_db
auth should be able to contact fusionauth, backend
ui should be able to contact backend, auth
You can use networks as you already partially do in your example to enable communication such as:
services on the same network can reach each other using the service name or alias - i.e. es_search can be reached by other services on the same network via http://es_search:9200
services on different network are isolated and cannot communicate with each other
You can then define your networks such as:
services:
postgres_db:
networks:
- postgres_db
es_search:
networks:
- es_search
# fusionauth should be able to contact es_search, postgres_db
fusionauth:
networks:
- fusionauth
- postgres_db
- es_search
db:
networks:
- mysql_db
# backend should be able to contact auth, mysql_db
backend:
networks:
- backend
- auth
- mysql_db
# ui should be able to contact backend, auth
UI:
networks:
- backend
- auth
# auth should be able to contact fusionauth, backend
auth:
networks:
- auth
- fusionauth
- backend
networks:
fusionauth:
backend:
auth:
postgres_db:
es_search:
mysql_db:
Where all services (except ui) have their own network, and another service must be on this service's network to communicate with it.
Note: I did not use link as it is a legacy and may be removed in future releases as stated by docs.
Delete every single last networks: and container_name: option from the docker-compose.yml file. network_mode: host as you have on the auth container is incompatible with Docker network communication, and seems to usually get presented as a workaround for port-publishing issues; delete that too. You probably want the name ui: to be in lower case as well.
When you do this, Docker Compose will create a single network named default and attach all of the containers it creates to that network. They will all be reachable by their service names. Networking in Compose in the Docker documentation describes this in more detail.
Your fusionauth container has the right basic setup. Trimming out some options:
fusionauth:
image: fusionauth/fusionauth-app:latest
depends_on:
- postgres_db
- es_search
environment:
# vvv These host names are other Compose service names
# vvv and default Compose networking makes them reachable
DATABASE_URL: jdbc:postgresql://postgres_db:5432/fusionauth
DATABASE_ET: CETERA
FUSIONAUTH_SEARCH_SERVERS: http://es_search:9200
FUSIONAUTH_URL: http://fusionauth:9010
restart: unless-stopped
ports:
- ${FUSIONAUTH_PORT}:9011
volumes:
- fa_config:/usr/local/fusionauth/config
# no networks: or container_name:
If the ui container presents something like a React or Angular front-end, remember that application runs in a browser and not in Docker, and so it will have to reach back to the physical system's DNS name or IP address and published ports:. It's common to introduce an nginx reverse proxy into this setup to serve both the UI code and the REST interface it needs to communicate with.
In principle you can set this up with multiple networks for more restrictive communications as the other answers have done. That could prevent ui from contacting postgres_db. I'd be a little surprised to see an environment where that level of control is required, and also where Compose is an appropriate deployment solution.
Also unnecessary, and frequently appearing in other questions like this, are hostname: (only sets containers' own notions of their own host names), links: (only relevant for pre-network Docker), and expose: (similarly).
from your docker-compose.yml.
postgres_db:
..
networks:
- postgres_db_net
fusionauth:
..
environment:
DATABASE_URL: jdbc:postgresql://postgres_db:5432/fusionauth
networks:
- postgres_db_net
The services postgres_db and fusionauth are attached to the network postgres_db-net which enables them to communicate with each other
communication happens by using the service-name which also works as hostname inside the container. the service fusionauth knows of the database by it's name postgres_db in the DATABASE_URL

Resources