Im using a container with api gateway in port 80, and I'm needing communicate the api gateway between another containers (all these one using dockerfile and docker-compose). How can I do these others conteiners not expose the port to localhost but communicate internally with the api gateway?
My docker-compose:
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- ./:/usr/src/app
- /usr/src/app/node_modules
ports:
- "3000:3000"
Solution:
Changed docker-compose file to:
version: '3.5'
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- ./:/usr/src/app
- /usr/src/app/node_modules
expose:
- "3000"
image: api-name-service
container_name: api-name-service
networks:
- api-network
networks:
api-network:
name: api-network-service
When the services is in the same network, this services can communicate with service name, like "http://api-name-service:3000".
You want to use expose instead of ports:
https://docs.docker.com/compose/compose-file/compose-file-v2/#expose
For example:
services:
app1:
expose:
- "3000"
app2:
...
assuming some API on port 3000 in app1, then app2 would be able to access http://app1:3000/api
Use docker network. Here is a very good tutorial on the docker website on how to use networking b/w containers: https://docs.docker.com/network/network-tutorial-standalone/
Related
I have a simple, proof of concept system that has 2 APIs: one act as the gateway and the other is a microservice. I have created docker containers for both and run them together using a docker compose file.
Everything work well, except I am not sure how to restrict the microservice from being called directly.
Here is my compose file:
version: '3.4'
services:
apigateway:
image: apigateway
container_name: api-gateway
build:
context: .
dockerfile: api_gateway/Dockerfile
ports:
- 7500:7500
networks:
- api-local
apiadmin:
image: apiadmin
container_name: api-admin
build:
context: .
dockerfile: api_admin/Dockerfile
ports:
- 7501:7501
networks:
- api-local
networks:
api-local:
external: true
I can call localhost:7500/some_url and I get back a response. I can also call localhost:7501/some_url and I also get a response. However, I want to prevent clients from calling the 7501 microservice directly. I want all traffic to go through the gateway only.
I can filter the IP in the microservice and reject the connection if not from the gateway IP, but I was wondering if there better approach.
You could try not to expose the microservice port to the host in your docker-compose file, it should be still reachable within the docker network and accessible to the gateway:
version: '3.4'
services:
apigateway:
image: apigateway
container_name: api-gateway
build:
context: .
dockerfile: api_gateway/Dockerfile
ports:
- 7500:7500
networks:
- api-local
apiadmin:
image: apiadmin
container_name: api-admin
build:
context: .
dockerfile: api_admin/Dockerfile
networks:
- api-local
networks:
api-local:
external: true
Please, note I removed the port mapping for the apiadmin service.
I am trying to make a web server cluster using docker compose. I want to identify each container with a custom unique hostname. My docker-compose.yaml looks like below but I am only able to get container id as hostname
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
command: "/app/main"
expose:
- "8080"
deploy:
replicas: 3
nginx:
image: nginx:latest
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- app
ports:
- "4000:4000"
I have two containers defined in a docker-compose yaml file that need to talk to each other, but they can't.
version: "3.9"
networks:
localdev:
driver: 'bridge'
services:
master-db:
image: mysql:8.0
container_name: master-db
hostname: master-db
command: --default-authentication-plugin=mysql_native_password
restart: always
ports:
- "4000:3306"
networks:
- localdev
page-store:
hostname: page-store
build:
context: .
dockerfile: Dockerfile.page_store
container_name: page-store
ports:
- "2020:2020"
networks:
- localdev
links:
- master-db
In the page-store Python Flask microservice, I try to access the MySQL database by using its hostname of master-db, but the name cannot resolve.
You should be able to connect each other using respective service names. master-db and page-store removing hostname
As per Official guide you may have to define master-db,page-store in container's /etc/hosts, if you want to use hostname: page-store etc.
Please refer this SO thread.
Also using --links may not be the best option.
I have two docker containers running - one has a websocket and the other is an nginx container. Setup using docker-compose.yml as follows:
version: "3.5"
websocket:
build:
context: .
dockerfile: Dockerfile
ports:
- "6000:7000"
nginx:
image: nginx:alpine
restart: always
ports:
- "120:80"
In my index.html in the nginx container, I currently have to set socketUrl: "http://192.168.X.X:6000",i.e. the local IP address for the websocket container.
Is there a way of setting up nginx so that socketUrl: "http://websocket:7000"? Either using nginx or traefik?
If I run on different machines I have to manually edit the socketUrl for the new machine. I'd like the setup to be standard across machines so that I can access the websocket via html at http://192.168.X.X:120
Use links to access the other container via hostname:
version: "3.5"
services:
websocket:
build:
context: .
dockerfile: Dockerfile
container_name: websocket
ports:
- "6000:7000"
nginx:
image: dperson/nginx
container_name: nginx
ports:
- "120:80"
environment:
- STREAM=0.0.0.0:80;websocket:7000
links:
- websocket
if this doesn't work, force them to be on the same network:
version: "3.5"
services:
websocket:
build:
context: .
dockerfile: Dockerfile
container_name: websocket
ports:
- "6000:7000"
networks:
- default
nginx:
image: dperson/nginx
container_name: nginx
ports:
- "120:80"
environment:
- STREAM=0.0.0.0:80;websocket:7000
links:
- websocket
networks:
- default
networks:
default:
in docker-compose.yml,
What is the difference between in following ports notations?
ports:
- "5000:5000"
resp:
ports:
- "8080"
or no ports at all.
For example in following docker-compose.yml, the mongodb service must be exposing a port to communicate with node service, but no port is specified
services:
node:
build:
context: .
dockerfile: node.dockerfile
ports:
- "3000:3000"
networks:
- nodeapp-network
depends_on:
- mongodb
mongodb:
image: mongo
networks:
- nodeapp-network
networks:
nodeapp-network:
driver: bridge
source: https://github.com/DanWahlin/NodeExpressMongoDBDockerApp
However in these docker-compose.yml, there are ports awlays specified with either 27017:27017 or 8080 notation.
services:
nginx:
container_name: nginx
image: ${DOCKER_ACCT}/nginx
build:
context: .
dockerfile: .docker/nginx.${APP_ENV}.dockerfile
links:
- node1:node1
- node2:node2
- node3:node3
ports:
- "80:80"
- "443:443"
networks:
- codewithdan-network
node1:
container_name: node-codewithdan-1
image: ${DOCKER_ACCT}/node-codewithdan
build:
context: .
dockerfile: .docker/node-codewithdan.${APP_ENV}.dockerfile
ports:
- "8080"
volumes:
- .:/var/www/codewithdan
working_dir: /var/www/codewithdan
env_file:
- ./.docker/env/app.${APP_ENV}.env
depends_on:
- mongo
- redis
networks:
- codewithdan-network
node2:
container_name: node-codewithdan-2
image: ${DOCKER_ACCT}/node-codewithdan
build:
context: .
dockerfile: .docker/node-codewithdan.${APP_ENV}.dockerfile
ports:
- "8080"
volumes:
- .:/var/www/codewithdan
working_dir: /var/www/codewithdan
env_file:
- ./.docker/env/app.${APP_ENV}.env
depends_on:
- mongo
- redis
networks:
- codewithdan-network
node3:
container_name: node-codewithdan-3
image: ${DOCKER_ACCT}/node-codewithdan
build:
context: .
dockerfile: .docker/node-codewithdan.${APP_ENV}.dockerfile
ports:
- "8080"
volumes:
- .:/var/www/codewithdan
working_dir: /var/www/codewithdan
env_file:
- ./.docker/env/app.${APP_ENV}.env
depends_on:
- mongo
- redis
networks:
- codewithdan-network
mongo:
container_name: mongo
image: ${DOCKER_ACCT}/mongo
build:
context: .
dockerfile: .docker/mongo.dockerfile
ports:
- "27017:27017"
env_file:
- ./.docker/env/mongo.${APP_ENV}.env
networks:
- codewithdan-network
redis:
container_name: redis
image: ${DOCKER_ACCT}/redis
build:
context: .
dockerfile: .docker/redis.${APP_ENV}.dockerfile
ports:
- "6379"
networks:
- codewithdan-network
networks:
codewithdan-network:
driver: bridge
source: https://github.com/DanWahlin/CodeWithDanDockerServices
Can you explain the difference?
Typical Docker containers run a long-running server listening on some TCP port. Other containers on the same Docker network can reach that container using the container’s name (docker run --name, container_name: directive) as a DNS name and the port the server is running on. In Docker Compose, Compose creates a Docker network per Compose YAML file, and also makes services available under their key in the YAML file. This works even if no ports: are specified.
So, for instance, if your docker-compose.yml file says
services:
mongo:
image: mongo
others:
env:
MONGODB_HOST: mongo
MONGODB_PORT: 27017
then the MongoDB container will be reachable on that host name and (default) port, even though it doesn’t explicitly have a ports:.
If you do declare a ports: then the container will be reachable from outside Docker space. If you only have one port it’s the port number of the server, and Docker picks the host port; this isn’t useful in most cases (but it’s guaranteed to not hit a port conflict). If you have two ports they’re the host port and internal service port. You can also specify a host IP address to bind(2) to.
Presence or absence of ports: doesn’t affect inter-dontainer communication. Always use the container’s name (or Docker-compose.yml service name) and the “internal” port number the server is listening on.
Either specify both ports (HOST:CONTAINER), or just the container port (an ephemeral host port is chosen). So in your case 8080 is container port
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
From here
The ephemeral port range is configured by /proc/sys/net/ipv4/ip_local_port_range kernel parameter, typically ranging from 32768 to 61000.
Either way, you should be able to peek at what Docker has accomplished in your network stack by examining your NAT tables. from here
In docker compose by default no ports will be created in case they collide with already opened ports