Docker static ip connection timeout from outside - docker

I am trying to assign my APP with a static IP. I think I have assigned the IP, but I cannot reach the IP from outside either curl or the browser.
docker-compose.yaml
version: '3.8'
services:
client:
container_name: client
build: ./frontend
ports:
- 3000:3000
working_dir: /app
volumes:
- ./frontend:/app/
- /app/node_modules
networks:
app_net:
ipv4_address: 172.16.238.10
hostname: client
command: npm run dev
networks:
app_net:
driver: bridge
ipam:
driver: default
config:
- subnet: "172.16.238.0/24"
Terminal message when I run it:
client | > frontend#0.0.0 dev
client | > vite
client |
client |
client | VITE v3.2.2 ready in 710 ms
client |
client | ➜ Local: http://localhost:3000/
client | ➜ Network: http://172.16.238.10:3000/
I can reach http://localhost:3000/ on the browser just fine. But whenever I try to reach http://172.16.238.10:3000/, I get a timeout. Something this on the browser:
This site can’t be reached
172.16.238.10 took too long to respond.
ERR_CONNECTION_TIMED_OUT
I can curl to the IP I assigned inside the docker container, but I cannot do it from outside. Is it possible to expose the IP to the outside?

If you manage to assign another IP address (172.16.238.10) to the host, the container can continue having a dynamic IP address. You can map the port 3000 only to the IP address 172.16.238.10.
Then you can connect to 172.16.238.10:3000 as so:
version: '3.8'
services:
client:
container_name: client
build: ./frontend
ports:
- 172.16.238.10:3000:3000
working_dir: /app
volumes:
- ./frontend:/app/
- /app/node_modules
networks:
- app_net
hostname: client
command: npm run dev
networks:
app_net:
driver: bridge

You probably want to look at using a macvlan network instead of bridged.

As a general rule, you can't access the container-private IP addresses at all. It happens to be possible on native Linux, not using Docker Desktop or another VM-based setup, and only if you're on the same machine as the container, but given all of these constraints it's usually better to not try it.
The standard way to access a container from outside is to declare ports: for it, and to use the host's DNS name or IP address and the published port number. Don't declare any IP-related setup in your Compose file at all.
Assuming your Dockerfile is correctly constructed, you should be able to reduce that Compose file to just
version: '3.8'
services:
client:
build: ./frontend
ports:
- 3000:3000
and calling http://host.example.com:3000/ using your host's DNS name, or http://localhost:3000 if you're on the same host, will forward to port 3000 in the container. None of the other Compose options are necessary.

Related

Expose docker-compose windows containers to windows host network

I'im fairly new to docker and docker compose.
I have a simple scenario, based on three applications (app1, app2, app3) that I want to connect to my host's network. The purpose is having an internet connection also inside the container.
Here is my docker-compose file:
version: '3.9'
services:
app1container:
image: app1img
build: ./app1
networks:
network_comp:
ipv4_address: 192.168.1.1
extra_hosts:
anotherpc: 192.168.1.44
ports:
- 80:80
- 8080:8080
app2container:
depends_on:
- "app1container"
image: app2img
build: ./app2
networks:
network_comp:
ipv4_address: 192.168.1.2
ports:
- 3100:3100
app3container:
depends_on:
- "app1container"
image: app3img
build: ./app3
networks:
network_comp:
ipv4_address: 192.168.1.3
ports:
- 9080:9080
networks:
network_comp:
driver: ""
ipam:
driver: ""
config:
- subnet: 192.168.0.0/24
gateway: 192.168.1.254
I already read the docker-compose documentation, which says that there is no a bridge driver for Windows OS. Is there anyway a solution to this issue?
You shouldn't usually need to do any special setup for this to work. When your Compose service has ports:, that makes a port available on the host's IP address. The essential rules for this are:
The service inside the container must listen on the special 0.0.0.0 "all interfaces" address (not 127.0.0.1 "this container only"), on some (usually fixed) port.
The container must be started with Compose ports: (or docker run -p). You choose the first port number, the second port number must match the port inside the container.
The service can be reached via the host's IP address on the first port number (or, if you're using the older Docker Toolbox setup, on the docker-machine ip address).
http://host.example.com:12345 (from other hosts)
|
v
ports: ['12345:8080'] (in the `docker-compose.yml`)
|
v
./my_server -bind 0.0.0.0:8080 (the main container command)
You can remove all of the manual networks: configuration in this file. In particular, it's problematic if you try to specify the Docker network to have the same IP address range as the host network, since these are two separate networks. Compose automatically provides a network named default that should work for most practical applications.

docker-compose connection between containers

I have 3 containers with my bot, server and db. after docker-compose up, server and db are working. telegram bot does get-request and takes this error:
Get "http://localhost:8080/user/": dial tcp 127.0.0.1:8080: connect: connection refused
docker-compose.yml
version: "3"
services:
db:
image: postgres
container_name: todo_postgres
restart: always
ports:
- "5432:5432"
environment:
# TODO: Change it to environment variables
POSTGRES_USER: user
POSTGRES_DB: somedb
POSTGRES_PASSWORD: pass
server:
depends_on:
- db
build: .
restart: always
ports:
- 8080:8080
environment:
DB_NAME: somedb
DB_USERNAME: user
DB_PASSWORD: pass
bot:
depends_on:
- server
build:
./src/telegram_bot
environment:
BOT_TOKEN: TOKEN
restart: always
links:
- server
When using compose, try using the containers hostname.. in the case your bot should try to connect to
server:8080
Compose will handle the name resolution to the IP you need
What you try is to access localhost within your container (service) bot.
Maybe this answer will help you to solve the problem. It sound similar to your problem.
But I want to provide you another solution to your problem:
In case it's not needed to access the containers form outside (from your host), one appraoch would be making use of the expose functionality and a docker network.
See docs.docker.com: network.
The expose functionality allows to access your other containers within your network
See docs.docker.com: expose
Expose ports without publishing them to the host machine - they’ll only be accessible to linked services. Only the internal port can be specified.
Example
What is this example doing?
A couple of steps that are not mandatory
Set a static ip within your docker container
These Steps are not needed and can be omitted. However, I like to do this, since you have now a better control over the network. You can access the containers by their hostname (which is the container name or service name) as well.
The steps that are needed are the following:
This exposes port 8080, but do not publish it.
expose:
- 8080
The network which allows static ip configuration
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
A complete file could look similar to this:
version: "3.8"
services:
first-service:
image: <your-image>
networks:
vpcbr:
ipv4_address: 10.5.0.2
expose:
- 8080
second-service:
image: <your-image>
networks:
vpcbr:
ipv4_address: 10.5.0.3
depends_on:
- first-service
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
Your bot container is up before your server & db containers.
When you use depends_on it's not accually waiting them to finish setup themeselves.
You should try some tricky algorithem for waiting the other container finish setup.
I remmember that when I used Nginx proxy I used something called wait-for-it.sh

docker containers with mac-vlan network show wrong ip after being restarted?

Hi everyone i have create a network with mac-vlan type in docker because i wanted my containers to be on the same LAN as host.Now the strange thing which i have noticed is that when i stop and then restart a container with docker start command the container gets started but the IP assigned to it is the one that was assigned before the container was shutdown. doesn't IP change when containers are restarted furthermore the container is now not reachable because the IP its showing as its own has now been reassigned to another machine on the network from what i have read that the container is assigned the same IP as before but if the container couldn't get the IP it fails to start but my container is starting just fine. What am i missing here? on ubuntu version 17.10 docker version 17.11.0-ce Api version 1.34 (both client and server)
You should not use static IP's in docker unless you are working with something that allows routing from outside to the inside container, like in you're case 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.
That being said, you can achieve the above using docker-compose like below :
services:
mysql:
container_name: backend-database
image: mysql:latest
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
ports:
- "3306:3306"
networks:
mynetwork:
ipv4_address: 10.5.0.5
apache-tomcat:
container_name: apache-tomcat
build: tomcat/.
ports:
- "8080:8080"
- "8009:8009"
networks:
mynetwork:
ipv4_address: 10.5.0.6
depends_on:
- mysql
networks:
mynetwork:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
gateway: 10.5.0.1

How to access docker container using localhost address

I am trying to access a docker container from another container using localhost address.
The compose file is pretty simple. Both containers ports are exposed.
There are no problems when building.
In my host machine I can successfully execute curl http://localhost:8124/ and get a response.
But inside the django_container when trying the same command I get Connection refused error.
I tried adding them in the same network, still result didn't change.
Well if I try to execute with the internal ip of that container like curl 'http://172.27.0.2:8123/' I get the response.
Is this the default behavior? How can I reach clickhouse_container using localhost?
version: '3'
services:
django:
container_name: django_container
build: ./django
ports:
- "8007:8000"
links:
- clickhouse:clickhouse
volumes:
- ./django:/usr/src/run
command: bash /usr/src/run/run.sh
clickhouse:
container_name: clickhouse_container
build: ./clickhouse
ports:
- "9001:9000"
- "8124:8123"
- "9010:9009"
So with this line here - "8124:8123" you're mapping the port of clickhouse container to localhost 8124. Which allows you to access clickhouse from localhost at port 8124.
If you want to hit clickhouse container from within the dockerhost network you have to use the hostname for the container. This is what I like to do:
version: '3'
services:
django:
hostname: djano
container_name: django
build: ./django
ports:
- "8007:8000"
links:
- clickhouse:clickhouse
volumes:
- ./django:/usr/src/run
command: bash /usr/src/run/run.sh
clickhouse:
hostname: clickhouse
container_name: clickhouse
build: ./clickhouse
ports:
- "9001:9000"
- "8124:8123"
- "9010:9009"
If you make the changes like I have made above you should be able to access clickhouse from within the django container like this curl http://clickhouse:8123.
As in #Billy Ferguson's answer, you can visit using localhost in host machine just because: you define a port mapping to route localhost:8124 to clickhouse:8123.
But when from other container(django), you can't. But if you insist, there is a ugly workaround: share host's network namespace with network_mode, but with this the django container will just share all network of host.
services:
django:
hostname: djano
container_name: django
build: ./django
ports:
- "8007:8000"
links:
- clickhouse:clickhouse
volumes:
- ./django:/usr/src/run
command: bash /usr/src/run/run.sh
network_mode: "host"
It depends of config.xml settings. If in config.xml <listen_host> 0.0.0.0</listen_host> you can use clickhouse-client -h your_ip --port 9001

Docker-compose port forwarding

I have a website hosted on shared hosting on production. The website connects to the database via localhost in the code. In my docker-compose I have a php:5.6-apache and mysql:5.6 instance.
Is there any way to tell docker-compose to have port 3306 on the web container port forwarded to 3306 on the db container, so that when the web container tries to connect to localhost on 3306 it gets sent to db on 3306 and also share port 80 on the web container to the outside world?
Current docker-compose.yml:
version: "3"
services:
web:
build: .
#image: php:5.6-apache
ports:
- "8080:80"
environment:
- "APP_LOG=php://stderr"
- "LOG_LEVEL=debug"
volumes:
- .:/var/www/html
network_mode: service:db # See https://stackoverflow.com/a/45458460/95195
# networks:
# - internal
working_dir: /var/www
db:
image: mysql:5.6
ports:
- "3306:3306"
environment:
- "MYSQL_XXXXX=*****"
volumes:
- ./provision/mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
# networks:
# - internal
networks:
internal:
driver: bridge
Current error:
ERROR: for web Cannot create container for service web: conflicting options: port publishing and the container type network mode
Yes it is possible. You need to use the network_mode option. See the below example
version: '2'
services:
db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- "80:80"
- "3306:3306"
app:
image: ubuntu:16.04
command: bash -c "apt update && apt install -y telnet && sleep 10 && telnet localhost 3306"
network_mode: service:db
outputs
app_1 | Trying 127.0.0.1...
app_1 | Connected to localhost.
app_1 | Escape character is '^]'.
app_1 | Connection closed by foreign host.
network_mode: service:db instructs docker to not assign the app services it own private network. Instead let it join the network of db service. So any port mapping that you need to do, needs to happen on the db service itself.
The way I usually use it is different, I create a base service which runs a infinite loop and the db and app service both are launched on base service network. All ports mapping need to happen at the base service.

Resources