I deploy my application using docker/docker-compose on Mac.
version: '3'
services:
server-gao:
container_name: server-gao
image: iainttho/server-gao:latest
networks:
- home-gateway
ports:
- 8080:8080
client-gao:
container_name: client-gao
image: iainttho/client-gao:latest
networks:
- home-gateway
depends_on:
- "server-gao"
networks:
home-gateway: { driver: bridge }
This docker-compose will deploy 2 service and connect them using a network typed bridge.
Running docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
04f2a8216459 iainttho/client-gao:latest "tail -f /dev/null" 29 minutes ago Up 29 minutes client-gao
8a88cc372a44 iainttho/server-gao:latest "/server localhost 8…" 29 minutes ago Up 29 minutes 0.0.0.0:8080->8080/tcp server-gao
Running docker network inspect node-compose_home-gateway
[
{
"Name": "node-compose_home-gateway",
"Id": "26fcd2f3468f544203724daad68fe4d52930a24daf51035b08ae95002645cef7",
"Created": "2023-01-29T19:41:15.26816106Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "192.168.176.0/20",
"Gateway": "192.168.176.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"04f2a82164595cadaca3545956666484e878214d15fe158f387807c2f748e414": {
"Name": "client-gao",
"EndpointID": "47a97da37d6f29a4fb40e43e90e2ec243e096d0af85dba24cab4322b7378096b",
"MacAddress": "02:42:c0:a8:b0:03",
"IPv4Address": "192.168.176.3/20",
"IPv6Address": ""
},
"8a88cc372a44b9b7e4ecb389a4bd92afefee391073be976853d234086a2f548c": {
"Name": "server-gao",
"EndpointID": "88663bc13f1a10d784ff7adf0b15d37db3115384cdb1d1d6cd29aaa3a4274211",
"MacAddress": "02:42:c0:a8:b0:02",
"IPv4Address": "192.168.176.2/20",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "home-gateway",
"com.docker.compose.project": "node-compose",
"com.docker.compose.version": "2.15.1"
}
}
]
Inside server-gao
root#8a88cc372a44:/# netstat -ntlp | grep LISTEN
tcp 0 0 127.0.0.11:39409 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN 1/server
root#8a88cc372a44:/# curl localhost:8080
curl: (1) Received HTTP/0.9 when not allowed
the server receive the request and logged something, this means the localhost just works fine.
2023-01-29 21:17:31 async_accept :
2023-01-29 21:17:31 create Connection
2023-01-29 21:17:31 ConnectionManager::start connections_.size() = 0
2023-01-29 21:17:31 send 1675023451349 to client 0x55727c068060
2023-01-29 21:17:31 Error during read operation : End of file
2023-01-29 21:17:31 Error during write operation : Bad file descriptor
2023-01-29 21:17:31 message from client 0x55727c068060 := GET / HTTP/1.1
2023-01-29 21:17:31 Host: localhost:8080
2023-01-29 21:17:31 User-Agent: curl/7.81.0
2023-01-29 21:17:31 Accept: */*
2023-01-29 21:17:31
2023-01-29 21:17:31
2023-01-29 21:17:31 send hey to client 0x55727c068060
2023-01-29 21:17:31 ConnectionManager::stop
2023-01-29 21:17:31 send 1675023451349 to client 0x55727c068060
2023-01-29 21:17:31 ConnectionManager::stop
2023-01-29 21:17:31 destroy Connection
Inside client-gao
root#04f2a8216459:/# ping -c2 server-gao
PING server-gao (192.168.176.2) 56(84) bytes of data.
64 bytes from server-gao.node-compose_home-gateway (192.168.176.2): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from server-gao.node-compose_home-gateway (192.168.176.2): icmp_seq=2 ttl=64 time=0.072 ms
--- server-gao ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1041ms
rtt min/avg/max/mdev = 0.072/0.075/0.079/0.003 ms
Using ping to test the connection, it works.
But checking with curl, I got connection refused
root#04f2a8216459:/# curl server-gao:8080
curl: (7) Failed to connect to server-gao port 8080 after 1 ms: Connection refused
root#8a88cc372a44:/# ./client server-gao 8080
Trying 192.168.176.2:8080...
Connect error: Connection refused
Moreover, I cannot access the server-Gạo using localhost
user#Macbook:node-compose$ curl localhost:8080
curl: (52) Empty reply from server
I only tested on Mac 13.1 (22C65), Docker Desktop 4.16.2 (95914)
I tried to run each image using separate docker run command, network command, but I got the same issue.
I followed the tutorial on docker page
The connection should be established ?
Related
I want to use nginx-proxy in front of another nginx (my-nginx) instance and this is the most minimal problem setup I can come up with. I am on the same machine and have the following:
Setup
NGINX-Proxy docker-compose.yml
version: '3.8'
services:
nginx-proxy:
image: jwilder/nginx-proxy
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- nginx-proxy
networks:
nginx-proxy:
external: true
Network
docker network create nginx-proxy
Commands
These are the commands that I run to start the nginx-proxy and my-nginx
docker compose up -d
and (I made this as minimal as possible, actually this NGINX is part of a larger docker compose project, but the error connection refused remains)
docker run -p 888:80 --network nginx-proxy -e VIRTUAL_HOST=my.sub.domain.tld -e VIRTUAL_PORT=888 --name my-nginx nginx
Logs
docker ps shows me that both containers are working
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
744f4df7059d nginx "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:888->80/tcp, :::888->80/tcp my-nginx
e3c57213f2bc jwilder/nginx-proxy "/app/docker-entrypo…" 5 minutes ago Up 5 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp jwilder-nginx-proxy-1
And this docker network inspect nginx-proxy tells me that they are infact connected to the same network.
[
{
"Name": "nginx-proxy",
"Id": "f71dcf5c1125005f1527eaa6c47d77c4aeeafb763faefc17c42e10b73c23d52b",
"Created": "2022-11-08T18:36:31.022872372Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.208.0/20",
"Gateway": "192.168.208.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"744f4df7059d02aa0b805a769fbc8b6428c0f3ace165b89d4b3c93395d517e72": {
"Name": "my-nginx",
"EndpointID": "7252798a05774d3d07ce04524859820026f9bad93b0b72d0350033fad821d285",
"MacAddress": "02:42:c0:a8:d0:03",
"IPv4Address": "192.168.208.3/20",
"IPv6Address": ""
},
"e3c57213f2bcbe70e91c961492c4157d6fc1f4f1a5c6456969201b102d689442": {
"Name": "jwilder-nginx-proxy-1",
"EndpointID": "5e41bc5c60c6b3d697e70f32b443e9c5b2852ae6c6099ad21a5ef978981cf9be",
"MacAddress": "02:42:c0:a8:d0:02",
"IPv4Address": "192.168.208.2/20",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
Problem
When I exec into the nginx-proxy with
docker compose exec nginx-proxy bash
and I try to curl my-nginx with
curl my-nginx:888
I get:
curl: (7) Failed to connect to my-nginx port 888: Connection refused
What I tried:
use the default network instead of nginx-network
curl from host (does not work)
access via internet gives this error (the same issue as the above curl)
jwilder-nginx-proxy-1 | nginx.1 | 2022/11/09 10:02:39 [error] 38#38: *7 connect() failed (111: Connection refused) while connecting to upstream, client: 84.56.95.53, server: my.sub.domain.tld, request: "GET / HTTP/1.1", upstream: "http://192.168.208.3:888/", host: "my.sub.domain.tld"
jwilder-nginx-proxy-1 | nginx.1 | my.sub.domain.tld 84.56.95.53 - - [09/Nov/2022:10:02:39 +0000] "GET / HTTP/1.1" 502 157 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0" "192.168.208.3:888"
Any help is much appreciated!
I have an external network which is used by docker-compose as well as docker run. I can specify network alias in 'docker run' and it would resolve to the actual container ip, but the alias I define in docker compose doesn't resolve to actual ip. why is this? What should I do to get the alias in docker-compose resolve to actual IP?
step1: create an external network
docker network create --attachable -d overlay test-docker-network
step2: create a docker-compose which creates an alias
docker-compose.yml
version: '3.0'
services:
host1:
image: linuxserver/openssh-server
environment:
USER_PASSWORD: 'password'
USER_NAME: 'user'
PASSWORD_ACCESS: 'true'
SUDO_ACCESS: 'true'
ports:
- 2222:2222
networks:
default:
aliases:
- netcatalias
networks:
default:
external:
name: test-docker-network
step3: deploy stack
docker stack deploy -c docker-compose.yml netcat
step4: deploy 'docker run' container in same network
docker run --rm --name host2 --network-alias=myalias -ti --network test-docker-network debian:buster bash
step5: resolve both the aliases
root#de1f75728a7e:~/gitprojects/docker-network-troubleshoot# docker run --rm --name host2 --network-alias=myalias -ti --network test-docker-network debian:buster bash
root#ea765c15dae8:/# ping myalias
PING myalias (10.0.8.5) 56(84) bytes of data.
64 bytes from ea765c15dae8 (10.0.8.5): icmp_seq=1 ttl=255 time=0.022 ms
64 bytes from ea765c15dae8 (10.0.8.5): icmp_seq=2 ttl=255 time=0.042 ms
64 bytes from ea765c15dae8 (10.0.8.5): icmp_seq=3 ttl=255 time=0.034 ms
^C
--- myalias ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 49ms
rtt min/avg/max/mdev = 0.022/0.032/0.042/0.010 ms
root#ea765c15dae8:/# ping netcatalias
PING netcatalias (10.0.8.2) 56(84) bytes of data.
64 bytes from ip-10-0-8-2.ec2.internal (10.0.8.2): icmp_seq=1 ttl=255 time=0.069 ms
64 bytes from ip-10-0-8-2.ec2.internal (10.0.8.2): icmp_seq=2 ttl=255 time=0.068 ms
64 bytes from ip-10-0-8-2.ec2.internal (10.0.8.2): icmp_seq=3 ttl=255 time=0.067 ms
^C
--- netcatalias ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 19ms
rtt min/avg/max/mdev = 0.067/0.068/0.069/0.000 ms
root#ea765c15dae8:/#
step 6: get actual ip from 'network inspect'
root#de1f75728a7e:~/gitprojects/docker-network-troubleshoot# docker network inspect test-docker-network
[
{
"Name": "test-docker-network",
"Id": "3ev3r0eo2rg81pyb2yovlmmg3",
"Created": "2020-01-18T03:09:58.748025872Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.8.0/24",
"Gateway": "10.0.8.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"2ba6c329d157b4a03480f978645e558bb6b46d9d5c7af3d152d943aae75c696a": {
"Name": "netcat_host1.1.180sln82qyxp03rk8o5od5p9a",
"EndpointID": "cf2eaf42b10083296696c3cad8e43fe392ed2374cd65fd8aa8c048a134171bd2",
"MacAddress": "02:42:0a:00:08:03",
"IPv4Address": "10.0.8.3/24",
"IPv6Address": ""
},
"ea765c15dae8c1cf6f6945447897a126fdf03ae1e42d2811c95d94a9d9112f39": {
"Name": "host2",
"EndpointID": "67ca483fd4bd231db74a39ba8f782a95c102fc04937ef9e245bfc14100f61d11",
"MacAddress": "02:42:0a:00:08:05",
"IPv4Address": "10.0.8.5/24",
"IPv6Address": ""
},
"lb-test-docker-network": {
"Name": "test-docker-network-endpoint",
"EndpointID": "0754c146c555fdf0e2d683c8ead3e0670196e201148c411f35899df226d77cc4",
"MacAddress": "02:42:0a:00:08:04",
"IPv4Address": "10.0.8.4/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4106"
},
"Labels": {},
"Peers": [
{
"Name": "08bdcafe53fb",
"IP": "10.0.0.30"
}
]
}
]
Issue:
we can see that the 'docker run' alias 'myalias' correctly resolves to (10.0.8.5) from 'docker network inspect'. But 'netcatalias' resolves to (10.0.8.2). But it should actually resolved to "10.0.8.3". Why is this happening. How can resolve netcatalias to "10.0.8.3"?
It's the ip of a virtual service load balancer that sits in front of services and distributes traffic to replicas.
If you change service routing mode to dnsrr instead vip (virtual-ip), then docker dns service will resolve names to container ips in round-robin mode.
I feel like this is simple, but I can't figure it out. I have two services, consul and traefik up in a single node swarm on the same host.
> docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
3g1obv9l7a9q consul_consul replicated 1/1 progrium/consul:latest
ogdnlfe1v8qx proxy_proxy global 1/1 traefik:alpine *:80->80/tcp, *:443->443/tcp
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
090f1ed90972 progrium/consul:latest "/bin/start -server …" 12 minutes ago Up 12 minutes 53/tcp, 53/udp, 8300-8302/tcp, 8400/tcp, 8500/tcp, 8301-8302/udp consul_consul.1.o0j8kijns4lag6odmwkvikexv
20f03023d511 traefik:alpine "/entrypoint.sh -c /…" 12 minutes ago Up 12 minutes 80/tcp
Both containers have access to the "consul" overlay network, which was created as such.
> docker network create --driver overlay --attachable consul
ypdmdyx2ulqt8l8glejfn2t25
Traefik is complaining that it can't reach consul.
time="2019-03-18T18:58:08Z" level=error msg="Load config error: Get http://consul:8500/v1/kv/traefik?consistent=&recurse=&wait=30000ms: dial tcp 10.0.2.2:8500: connect: connection refused, retrying in 7.492175404s"
I can go into the traefik container and confirm that I can't reach consul through the overlay network, although it is pingable.
> docker exec -it 20f03023d511 ash
/ # nslookup consul
Name: consul
Address 1: 10.0.2.2
/ # curl consul:8500
curl: (7) Failed to connect to consul port 8500: Connection refused
# ping consul
PING consul (10.0.2.2): 56 data bytes
64 bytes from 10.0.2.2: seq=0 ttl=64 time=0.085 ms
However, if I look a little deeper, I find that they are connected, just that the overlay network isn't transmitting traffic to the actual destination for some reason. If I go directly to the actual consul ip, it works.
/ # nslookup tasks.consul
Name: tasks.consul
Address 1: 10.0.2.3 0327c8e1bdd7.consul
/ # curl tasks.consul:8500
Moved Permanently.
I could workaround this, technically there will only ever be one copy of consul running, but I'd like to know why the data isn't routing in the first place before I get deeper into it. I can't think of anything else to try. Here is various information related to this setup.
> docker --version
Docker version 18.09.2, build 6247962
> docker network ls
NETWORK ID NAME DRIVER SCOPE
cee3cdfe1194 bridge bridge local
ypdmdyx2ulqt consul overlay swarm
5469e4538c2d docker_gwbridge bridge local
5fd928ea1e31 host host local
9v22k03pg9sl ingress overlay swarm
> docker network inspect consul
[
{
"Name": "consul",
"Id": "ypdmdyx2ulqt8l8glejfn2t25",
"Created": "2019-03-18T14:44:27.213690506-04:00",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.2.0/24",
"Gateway": "10.0.2.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"0327c8e1bdd7ebb5a7871d16cf12df03240996f9e590509984783715a4c09193": {
"Name": "consul_consul.1.8v4bshotrco8fv3sclwx61106",
"EndpointID": "ae9d5ef1d19b67e297ebf40f6db410c33e4e3c0266c56e539e696be3ed4c81a5",
"MacAddress": "02:42:0a:00:02:03",
"IPv4Address": "10.0.2.3/24",
"IPv6Address": ""
},
"c21f5dfa93a2f43b747aedc64a343d94d6c1c2e6558d81bd4a52e2ba4b5fa90f": {
"Name": "proxy_proxy.sb6oindhmfukq4gcne6ynb2o2.4zvco02we58i3ulbyrsw1b2ok",
"EndpointID": "7596a208e0b05ba688f318814e24a2a1a3401765ed53ca421bf61c73e65c235a",
"MacAddress": "02:42:0a:00:02:06",
"IPv4Address": "10.0.2.6/24",
"IPv6Address": ""
},
"lb-consul": {
"Name": "consul-endpoint",
"EndpointID": "23e74716ef54f3fb6537b305176b790b4bc4132dda55f20588d7ce4ca71d7372",
"MacAddress": "02:42:0a:00:02:04",
"IPv4Address": "10.0.2.4/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4099"
},
"Labels": {},
"Peers": [
{
"Name": "e11b9bd30b31",
"IP": "10.8.0.1"
}
]
}
]
> cat consul/docker-compose.yml
version: '3.1'
services:
consul:
image: progrium/consul
command: -server -bootstrap
networks:
- consul
volumes:
- consul:/data
deploy:
labels:
- "traefik.enable=false"
networks:
consul:
external: true
> cat proxy/docker-compose.yml
version: '3.3'
services:
proxy:
image: traefik:alpine
command: -c /traefik.toml
networks:
# We need an external proxy network and the consul network
# - proxy
- consul
ports:
# Send HTTP and HTTPS traffic to the proxy service
- 80:80
- 443:443
configs:
- traefik.toml
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
# Deploy the service to all nodes that match our constraints
mode: global
placement:
constraints:
- "node.role==manager"
- "node.labels.proxy==true"
labels:
# Traefik uses labels to configure routing to your services
# Change the domain to your own
- "traefik.frontend.rule=Host:proxy.mcwebsite.net"
# Route traffic to the web interface hosted on port 8080 in the container
- "traefik.port=8080"
# Name the backend (not required here)
- "traefik.backend=traefik"
# Manually set entrypoints (not required here)
- "traefik.frontend.entryPoints=http,https"
configs:
# Traefik configuration file
traefik.toml:
file: ./traefik.toml
# This service will be using two external networks
networks:
# proxy:
# external: true
consul:
external: true
There were two optional kernel configs CONFIG_IP_VS_PROTO_TCP and CONFIG_IP_VS_PROTO_UDP disabled in my kernel which, you guessed it, enable tcp and udp load balancing.
I wish I'd checked that about four hours sooner than I did.
I am building a micro-service based web app with Flask and Docker. Currently, I have 2 services running by docker-compose under the same default network.
mysql
product_api
docker-compose.yml file is --
version: '3'
services:
mysql:
image: mysql
environment:
MYSQL_USER: "mysqluser"
MYSQL_PASSWORD: "mysqlpassword"
MYSQL_ROOT_PASSWORD: "root"
MYSQL_DATABASE: "gadgetfreeiot"
container_name: mysql
ports:
- 3306:3306
restart: always
entrypoint: ['docker-entrypoint.sh', '--default-authentication-plugin=mysql_native_password']
product_api:
build: ./${SERVICE_ROOT:-src/services/product/api}
image: product_api:v1
container_name: product_api
volumes:
- ./${SERVICE_ROOT:-src/services/product/api}:${PROJECT_ROOT:-/usr/projects/gadgetfreeiot}/${SERVICE_ROOT:-src/services/product/api}
ports:
- 5000:5000
depends_on:
- mysql
environment:
username: "mysqluser"
password: "mysqlpassword"
host: "mysql"
port: "3306"
database: "gadgetfreeiot"
command: ["./wait-for-mysql.sh", "--", "python", "./run.py"]
docker ps output gives me --
johir#ubuntu:gadgetfreeiot$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e10329e26e5c product_api:v1 "./wait-for-mysql.sh…" 18 minutes ago Up 18 minutes 0.0.0.0:5000->5000/tcp product_api
7fed5a136123 mysql "docker-entrypoint.s…" 18 minutes ago Up 18 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
Both services are running under gadgetfreeiot_default network. docker inspect gadgetfreeiot_default shows that both are under the same network --
johir#ubuntu:gadgetfreeiot$ docker inspect gadgetfreeiot_default
[
{
"Name": "gadgetfreeiot_default",
"Id": "67e09ae3a33c0ff4203eefe4fee6ba421d3f68564c6e32c7d1cd04e866ac6850",
"Created": "2018-10-18T14:56:05.86215576+03:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "192.168.0.0/20",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"14ffb8eaa0c17de0122de142dbcf7aa5455b41b47eadb197e8be200c2375fbb3": {
"Name": "mysql",
"EndpointID": "38ed4140ed728271194ee82f12b3d937c53166f6159ab4e6fcf2d8087039ed06",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/20",
"IPv6Address": ""
},
"e013059b510e42933d33f7c3fb7e141a19a6c78a0e34d031e5fce5e104aa8697": {
"Name": "product_api",
"EndpointID": "fdbe0ed92d0e53d6fc1040a50b1898e2bb87b34384f80b98e638a3a89a57c4e1",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/20",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "gadgetfreeiot",
"com.docker.compose.version": "1.22.0"
}
}
]
Now I am trying to access the product_api as well as mysql services from my host OS. In the meantime, I am also trying to access from one container to another (from product_api to mysql and from mysql to product_api). mysql is accessible from all 3 that is my host OS, product_api and mysql itself by --
mysql -h172.19.0.2 -P3306 -umysqluser -p
product_api is also able to access by --
mysql -hmysql -P3306 -umysqluser -p
Luckily I am able to access curl http://localhost:5000 shows from product_api --
johir#ubuntu:gadgetfreeiot$ docker exec -it product_api bash
root#e013059b510e:/usr/projects/gadgetfreeiot/src/services/product/api# curl http://localhost:5000
{
"message": "Endpoint not found",
"status": "failed"
}
Where curl http://172.19.0.3:5000 shows --
curl: (7) Failed to connect to 172.19.0.3 port 5000: Connection refused
That means product_api is up & running and only accessible by localhost or 127.0.0.1 from inside the product_api container not by IP or by service name from outside product_api container that is neither from my host OS nor from mysql container.
Finally, I checked -- active networks among 3 by netstat -tln --
# product_api container
root#e10329e26e5c:/usr/projects/gadgetfreeiot/src/services/product/api# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.11:40071 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN
# mysql container
root#7fed5a136123:/# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.11:35507 0.0.0.0:* LISTEN
tcp6 0 0 :::33060 :::* LISTEN
tcp6 0 0 :::3306 :::* LISTEN
# host OS
johir#ubuntu:gadgetfreeiot$ netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
tcp6 0 0 ::1:631 :::* LISTEN
tcp6 0 0 :::5000 :::* LISTEN
tcp6 0 0 :::3306 :::* LISTEN
Note:
port 5000 is not open by tcp6 in product_api container. On the other hand port 3306 is open by tcp6 on mysql container.
Question: Why I am unable to access product_api service from my host OS or even from mysql (in constraint, why tcp6 is not exposing port 5000 for product_api service)?
The short answer is, you aren't unable to access, as you showed with curl http://localhost:5000. It just seems to be a bit confusing who (host vs containers) can access which IPs and resolve which hostnames.
In your docker-compose.yml you mapped the ports 3306 and 5000 to your respective containers. So docker added a port forward from any interface on your host (w/o the interfaces of the docker networks) to your containers (have a look at the output of sudo iptables-save | grep 5000 if you are interested in how it's done under the hood, it will look something like this:
-A DOCKER -d 192.168.0.2/20 ! -i br-e013059b510e -o br-e013059b510e -p tcp -m tcp --dport 5000 -j ACCEPT
Access
So from your host, you can reach your service via
curl http://localhost:5000
From another computer (assuming firewall settings allow) via
curl http://your.hostname:5000
From a container on the same docker network
curl http://product_api:5000 # or
curl http://product_api.gadgetfreeiot_default:5000 # or
curl http://192.168.0.3:5000
To have both container on the same docker network, adjust your docker-compose.yml like this:
services:
mysql:
[...]
ports:
- 3306:3306
networks:
- gadgetfreeiot
[...]
product_api:
ports:
- 5000:5000
networks:
- gadgetfreeiot
[...]
networks:
gadgetfreeiot:
DNS
Container hostnames like product_api are not resolvable on the host. They are however inside your containers. Inside a container you have an extra docker DNS server at 127.0.0.11 which can resolve what your host can resove, plus docker hostnames like product_api.gadgetfreeiot_default. Try
nslookup product_api.gadgetfreeiot_default
on your host and from inside the container
docker exec -it mysql bash
Check https://docs.docker.com/network/ for more info on that.
With regards to your note: netstat doesn't show you which port is "open", i.e. allowed by the firewall, but which port is bound to by a program. Whether a program binds to a port on an interface on IPv4, v6 or both, is up to the program. This is not related to docker networking.
I created a bridge network names app and connect to two containers as you can see below:
[
{
"Name": "app",
"Id": "54fc6dc62ce366d9a019f556a7efd78dfb60676542e6cc4a494678f7faf6a63a",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{}
]
},
"Containers": {
"0280af19da941b4a83101bf9a6d4a51e0a41436374f2e403ac1e1a7169d75b57": {
"EndpointID": "be4b0587262ea402a8e83c1db6e71fbb7347773dce89869c575d3ace85cdaab5",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"759b09fe9b5d154eb2b0676547e21a576b31c917087a206ed46bea9acced2017": {
"EndpointID": "78611933ff99b34306944044ed7ec988c16dc05d5b42953547300c7a11cd4b64",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
The first container is redis db container and the second is sinatra webapp based container. I run the webapp container like this:
sudo docker run -p 4567 \--net=app --name webapp -t -i \-v /home/developer/sinatra/webapp:/opt/webapp kostonstyle/sinatra \/bin/bash
and inside console from webapp, I can ping to the redis db server.
root#759b09fe9b5d:/opt/webapp/bin# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.074 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.047 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.046 ms
How can I connect to redis db in console? I've try
root#759b09fe9b5d:/opt/webapp/bin# redis-cli -h remote.172.18.0.2
but it says me:
Could not connect to Redis at remote.172.18.0.2:6379: Name or service not known
What am I doing wrong?
Seems like it's a typo. Try redis-cli -h 172.18.0.2 without remote.
Use redis-cli --help for detailed information.