Docker-compose dial tcp error with dynamic ip : port - docker

I am trying to re-route request from gateway to a target service , and in case I am using static port binding everything works fine. But it is not flexible , so I want to run containers with dynamic ip and port in the network , to be able to run multiple instances.
I changed docker-compose.yml from
-ports:
"8082:8082"
to
-ports:
"8082"
And got an error
Get "http://c0000203.addr.dc1.consul.:60949/api/v1/users": dial tcp 192.0.2.3:60949: connect: connection refused
I am using consul as a service discovery , and registartor for registering containers
Base docker-compose file:
version: '3.7'
services:
postgres:
image: postgres:13
restart: 'always'
environment:
- POSTGRES_DB=user-db
- POSTGRES_PASSWORD=password
- POSTGRES_USER=user
ports:
- "5432"
networks:
- vpcbr
consul:
image: consul:latest
restart: 'always'
environment:
CONSUL_LOCAL_CONFIG: |
{
"recursors": [
"8.8.8.8",
"8.8.4.4"
],
"dns_config": {
"recursor_strategy": "random"
},
"ports": {
"dns": 53
}
}
networks:
vpcbr:
ipv4_address: 192.0.2.10
ports:
- '8500:8500'
- '53/tcp'
- '53/udp'
registrator:
image: gliderlabs/registrator:latest
command: "consul://consul:8500"
container_name: registrator
depends_on:
- consul
volumes:
- /var/run/docker.sock:/tmp/docker.sock
networks:
vpcbr:
ipv4_address: 192.0.2.20
krakend_gateway:
image: devopsfaith/krakend:2
command: [ "run", "-d", "-c", "/krakend.json" ]
dns: 192.0.2.10
volumes:
- ./krakend-gateway/krakend.json:/krakend.json
ports:
- "1234:1234"
- "8080:8080"
- "8090:8090"
networks:
vpcbr:
ipv4_address: 192.0.2.23
user-ms:
build: user-ms/
platform: linux/arm64
restart: 'always'
depends_on: [consul, krakend_gateway]
networks:
- vpcbr
ports:
- "8082"
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 192.0.2.0/24
Service which is sending request is Krakend , target service is user-ms , which should accept this request , everything is work when I am changing user-ms port binding to "8082:8082"
Will be glad if someone could help me , thanks

Use Registrator's -internal CLI flag to configure to register services with the internal IP addresses of the Docker container, not the external host IP.
Per https://gliderlabs.github.io/registrator/latest/user/run/#registrator-options
-internal Use exposed ports instead of published ports.
If the -internal option is used, Registrator will register the docker0 internal IP and port instead of the host mapped ones.
The modified container definition will then be as follows.
# docker-compose.yaml
...
registrator:
image: gliderlabs/registrator:latest
command: "consul://consul:8500 -internal"
container_name: registrator
depends_on:
- consul
volumes:
- /var/run/docker.sock:/tmp/docker.sock
networks:
vpcbr:
ipv4_address: 192.0.2.20
...

Related

Docker Compose - Changing the network mode to "host" results in error: Error response from daemon: failed to add interface veth701c890 to sandbox

Following this question, I edited my gateway container to use the host network mode:
services:
gateway:
...
network_mode: "host"
and then the docker compose up -d gives me this:
Error response from daemon: failed to add interface veth701c890 to
sandbox: error setting interface "veth701c890" IP to 172.26.0.11/16:
cannot program address 172.26.0.11/16 in sandbox interface because it
conflicts with existing route {Ifindex: 4 Dst: 172.26.0.0/16 Src:
172.26.0.1 Gw: Flags: [] Table: 254
I restarted the docker and even the server. No luck.
The docker-compose.yml looks like this (only the gateway container has published ports):
version: '3.4'
services:
gateway:
image: <ms-yarp>
environment:
- ASPNETCORE_URLS=https://+:443;http://+:80
ports:
- "80:80"
- "443:443"
volumes:
- ./tls/:/tls/
networks:
- mynet
restart: on-failure
orders:
image: <registry>/orders
environment:
- ASPNETCORE_URLS=http://+:80
networks:
- mynet
restart: on-failure
users:
image: <registry>/users
environment:
- ASPNETCORE_URLS=http://+:80
networks:
- mynet
restart: on-failure
smssender:
image: <registry>/smssender
environment:
- ASPNETCORE_URLS=http://+:80
networks:
- mynet
restart: on-failure
logger:
image: <registry>/logger
environment:
- ASPNETCORE_URLS=http://+:80
networks:
- mynet
restart: on-failure
notifications:
image: <registry>/notifications
environment:
- ASPNETCORE_URLS=http://+:80
networks:
- mynet
restart: on-failure
cacheserver:
image: <registry>/redis
networks:
- mynet
restart: on-failure
...
networks:
mynet:
You can't combine host networking with any other Docker networking option. At least some versions of Compose have given warnings if you combine network_mode: host with other networks: or ports: options.
The other thing host networking means in this particular setup is that the one container that's using it is "outside Docker" for purposes of connecting to other containers. It works exactly the same way a non-container process would. That means the other containers need to publish ports: to be reachable from the gateway, and in turn the gateway configuration needs to use localhost and the published port numbers to reach the other containers.
version: '3.8'
services:
gateway:
image: <ms-yarp>
network_mode: host
orders:
image: <registry>/orders
ports:
- '8001:80'
networks:
- mynet
{
"ReverseProxy": {
"Clusters": {
"cluster": {
"Destinations": {
"orders": {
"Address": "http://localhost:8001"
}
}
}
}
}
}
Something like this:
(doesn't work with Docker Desktop on windows WSL2, at least I couldn't even run the nginx example that is here in the docs)
version: '3.4'
services:
gateway:
image: <ms-yarp>
environment:
- ASPNETCORE_URLS=https://+:443;http://+:80
network_mode: host
volumes:
- ./tls/:/tls/
restart: on-failure
orders:
image: <registry>/orders
environment:
- ASPNETCORE_URLS=http://+:80
ports:
- 8080:80
networks:
- mynet
restart: on-failure
users:
image: <registry>/users
environment:
- ASPNETCORE_URLS=http://+:80
ports:
- 8081:80
networks:
- mynet
restart: on-failure
smssender:
image: <registry>/smssender
environment:
- ASPNETCORE_URLS=http://+:80
ports:
- 8082:80
networks:
- mynet
restart: on-failure
logger:
image: <registry>/logger
environment:
- ASPNETCORE_URLS=http://+:80
ports:
- 8082:80
networks:
- mynet
restart: on-failure
notifications:
image: <registry>/notifications
environment:
- ASPNETCORE_URLS=http://+:80
ports:
- 8083:80
networks:
- mynet
restart: on-failure
cacheserver:
image: <registry>/redis
restart: on-failure
networks:
- mynet
Also in your gateway service configuration you will need to change the
http://orders:80 to http://localhost:8080
http://users:80 to http://localhost:8081
and so on
Also restrict ports on the docker host of 8080 to 8083 to be accessible only from localhost and not from the internet.
You could even put all the containers (except the gateway) to a different docker host that is accessible only from the docker host where the gateway container is running and change the config in gateway from http://orders:80 to http://otherdockerhost:80 and so on.
But for this docker compose will not be viable you will need to "manually" create the containers with docker run commands (or have 2 separate compose project one for the gateway and one for the rest of the services) so this is where more serious container orchestration tools are required like kubernetes (you could try docker swarm or nomad or any other container orchestrator, but these are not so popular so if you are new to both kubernetes and docker swarm or all the other you are better off with starting with kubernetes, you will reap the benefits in the long run for both this project and your personal carrier too)

Securing Redis in docker with docker-compose

I have a docker-compose.yaml file as below and I want to make sure that port 6379 on the server is not exposed to the internet (just to the first container "web" mentioned).
If I just remove the "expose" link from the "redis:" section, will that keep my redis working internally but block it from being accessed from outside?
version: '2'
services:
web:
image: myimage/version1:1.4.5
restart: always
ports:
- 8082:3000
container_name: web
networks:
- web
- default
expose:
- '3000'
labels:
- 'traefik.docker.network=web'
- 'traefik.enable=true'
- 'traefik.basic.frontend.rule=Host:abcd.com'
- 'traefik.basic.port=3000'
- 'traefik.basic.protocol=http'
depends_on:
- redis
redis:
image: redis:4.0.5-alpine
restart: always
ports:
- 6379:6379
expose:
- 6379
command: ["redis-server", "--appendonly", "yes"]
hostname: redis
networks:
- web
volumes:
- redis-data:/data
networks:
web:
external: true
volumes:
redis-data:
Expose makes the port accessible only to linked services which is what you want. You should remove the redis ports so the port will not be bound to the host.

Share Docker container through local network and access to it from an another host

I try to share a container through my local network, to access this container from an another machine on the same network. I have follow tihs tutorial (section "With macvlan devices") and I succeeded to share a simple web container and access from an another host.
But the container that I want to share is a little more sophisticated, because he comminicate with other containers on the host through an internal network on the host.
I try to bind my existing container created in my docker-compose but I can't access to it. Can you help me, or tell me where I'm wrong if so please ?
This is my docker-compose :
version: "2"
services:
baseimage:
container_name: baseimage
image: base
build:
context: ./
dockerfile: Dockerfile.base
web:
container_name: web
image: web
env_file:
- .env
context: ./
dockerfile: Dockerfile.web
extra_hosts:
- dev.api.exemple.com:127.0.0.1
- dev.admin.exemple.com:127.0.0.1
- dev.www.exemple.com:127.0.0.1
ports:
- 80:80
- 443:443
volumes:
- ./code:/ass
- /var/run/docker.sock:/var/run/docker.sock
tty: true
dns:
- 8.8.8.8
- 8.8.4.4
links:
- mysql
- redis
- elasticsearch
- baseimage
networks:
devbox:
ipv4_address: 172.20.0.2
cron:
container_name: cron
image: cron
build:
context: ./
dockerfile: Dockerfile.cron
volumes:
- ./code:/ass
tty: true
dns:
- 8.8.8.8
- 8.8.4.4
links:
- web:dev.api.exemple.com
- mysql
- redis
- elasticsearch
- baseimage
networks:
devbox:
ipv4_address: 172.20.0.3
mysql:
container_name: mysql
image: mysql:5.6
ports:
- 3306:3306
networks:
devbox:
ipv4_address: 172.20.0.4
redis:
container_name: redis
image: redis:3.2.4
ports:
- 6379:6379
networks:
devbox:
ipv4_address: 172.20.0.5
elasticsearch:
container_name: elastic
image: elasticsearch:2.3.4
environment:
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- ./es_data:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
devbox:
ipv4_address: 172.20.0.6
chromedriver:
container_name: chromedriver
image: robcherry/docker-chromedriver:latest
privileged: true
ports:
- 4444:4444
environment:
- CHROMEDRIVER_WHITELISTED_IPS='172.20.0.2'
- CHROMEDRIVER_URL_BASE='wd/hub'
- CHROMEDRIVER_EXTRA_ARGS='--ignore-certificate-errors'
networks:
devbox:
ipv4_address: 172.20.0.7
links:
- web:dev.www.exemple.com
networks:
devbox:
driver: bridge
driver_opts:
com.docker.network.enable_ipv6: "false"
ipam:
driver: default
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
Create an external network assign the external network and devbox network to web. Web would then be publicly accessible via the external network public ip address and communicate with the internal services using the devbox network.
Will post working example asap

Docker bind host to container

I have two containers nginx and php how to configure docker-compose so when I make wget http://example.com from inside php container this host should point to nginx container
Map your nginx port to host port.
If you host has name example.com and nginx runs on 8080 port, set up your docker-compose like
nginx:
image: nginx
hostname: nginx
ports:
- "8080:80"
In this case request to http://example.com will be really executed as http://nginx:8080.
I've specified static ips for my containers in docker-compose.yml and added extra_host:
services:
nginx:
image: nginx
ports:
- "8200:80"
- "8201:443"
volumes:
- .:/var/www/html
networks:
test:
ipv4_address: 10.5.0.5
php:
build: ./docker/php
volumes:
- .:/var/www/html
environment:
APP_ENV: "dev"
networks:
test:
ipv4_address: 10.5.0.6
extra_hosts:
- "example.com:10.5.0.5"
networks:
test:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16

Provide static IP to docker containers via docker-compose

I'm trying to provide static IP address to containers. I understand that I have to create a custom network. I create it and the bridge interface is up on the host machine (Ubuntu 16.x). The containers get IP from this subnet but not the static I provided.
Here is my docker-compose.yml:
version: '2'
services:
mysql:
container_name: mysql
image: mysql:latest
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
ports:
- "3306:3306"
networks:
- vpcbr
apigw-tomcat:
container_name: apigw-tomcat
build: tomcat/.
ports:
- "8080:8080"
- "8009:8009"
networks:
- vpcbr
depends_on:
- mysql
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
gateway: 10.5.0.1
aux_addresses:
mysql: 10.5.0.5
apigw-tomcat: 10.5.0.6
The containers get 10.5.0.2 and 10.5.0.3, instead of 5 and 6.
Note that I don't recommend a fixed IP for containers in Docker unless you're doing something that allows routing from outside to the inside of your container network (e.g. macvlan). DNS is already there for service discovery inside of the container network and supports container scaling. And outside the container network, you should use exposed ports on the host. With that disclaimer, here's the compose file you want:
version: '2'
services:
mysql:
container_name: mysql
image: mysql:latest
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
ports:
- "3306:3306"
networks:
vpcbr:
ipv4_address: 10.5.0.5
apigw-tomcat:
container_name: apigw-tomcat
build: tomcat/.
ports:
- "8080:8080"
- "8009:8009"
networks:
vpcbr:
ipv4_address: 10.5.0.6
depends_on:
- mysql
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
gateway: 10.5.0.1
I was facing some difficulties with an environment variable that is with custom name (not with container name /port convention for KAPACITOR_BASE_URL and KAPACITOR_ALERTS_ENDPOINT). If we give service name in this case it wouldn't resolve the ip as
KAPACITOR_BASE_URL: http://kapacitor:9092
In above http://[**kapacitor**]:9092 would not resolve to http://172.20.0.2:9092
I resolved the static IPs issues using subnetting configurations.
version: "3.3"
networks:
frontend:
ipam:
config:
- subnet: 172.20.0.0/24
services:
db:
image: postgres:9.4.4
networks:
frontend:
ipv4_address: 172.20.0.5
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:latest
networks:
frontend:
ipv4_address: 172.20.0.6
ports:
- "6379"
influxdb:
image: influxdb:latest
ports:
- "8086:8086"
- "8083:8083"
volumes:
- ../influxdb/influxdb.conf:/etc/influxdb/influxdb.conf
- ../influxdb/inxdb:/var/lib/influxdb
networks:
frontend:
ipv4_address: 172.20.0.4
environment:
INFLUXDB_HTTP_AUTH_ENABLED: "false"
INFLUXDB_ADMIN_ENABLED: "true"
INFLUXDB_USERNAME: "db_username"
INFLUXDB_PASSWORD: "12345678"
INFLUXDB_DB: db_customers
kapacitor:
image: kapacitor:latest
ports:
- "9092:9092"
networks:
frontend:
ipv4_address: 172.20.0.2
depends_on:
- influxdb
volumes:
- ../kapacitor/kapacitor.conf:/etc/kapacitor/kapacitor.conf
- ../kapacitor/kapdb:/var/lib/kapacitor
environment:
KAPACITOR_INFLUXDB_0_URLS_0: http://influxdb:8086
web:
build: .
environment:
RAILS_ENV: $RAILS_ENV
command: bundle exec rails s -b 0.0.0.0
ports:
- "3000:3000"
networks:
frontend:
ipv4_address: 172.20.0.3
links:
- db
- kapacitor
depends_on:
- db
volumes:
- .:/var/app/current
environment:
DATABASE_URL: postgres://postgres#db
DATABASE_USERNAME: postgres
DATABASE_PASSWORD: postgres
INFLUX_URL: http://influxdb:8086
INFLUX_USER: db_username
INFLUX_PWD: 12345678
KAPACITOR_BASE_URL: http://172.20.0.2:9092
KAPACITOR_ALERTS_ENDPOINT: http://172.20.0.3:3000
volumes:
postgres_data:
If you are never seeing the static IP address set, perhaps it could be because you are using "docker compose up". Try using "docker-compose up".
When I use "docker-compose up" (with the hyphen) I now see the static IPs assigned.
networks:
hfnet:
driver: bridge
ipam:
driver: default
config:
- subnet: 192.168.55.0/24
gateway: 192.168.55.1
services:
web:
image: 'mycompany/webserver:latest'
hostname: www
domainname: mycompany.com
stdin_open: true # docker run -i
tty: true # docker run -t
networks:
hfnet:
ipv4_address: 192.168.55.10
ports:
- '80:80'
- '443:443'
volumes:
- '../honeyfund:/var/www/html'
I wasted a lot of time to figure that one out. :(
I realized, that the more convenient and meaningful way is to give the container a container-name.
You can use the name in the same docker network as source.
This helped me because the docker-containers had changing IPs and by this I can communicate with another container with a static name that I can use in config-files.

Resources