Docker - exposing IP addresses to DNS server - docker

Looking at the iptables of my docker host i get something like this:
sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:http-alt
I was able to assign a durable IP address like this:
sudo ip addr add 10.0.0.99/8 dev eth0
docker run -d -p 10.0.0.99:8888:8080 tomcat:8
but that address is only available on this machine, as in I need to ssh into it and ping it from this box.
Reading through this, it looks like i need to add a custom bridge:
Custom Docker Bridge
Is there a way to make the bridge hand fresh ips from the DHCP server? For example if my DHCP server assigned addresses from 10.1.1.x - I want to assign those addresses to Docker containers.
Would this involve a generic *nix way of pushing my iptable /etc/hosts ip addresses and dns names to a DNS server so other machines outside of the Docker cluster can ping those machines?
I have port forwarding working but need to do the same with the ip addresses as Zookeeper only tracks the internal Docker ip addresses and hostnames as I've defined them in my docker-compose.yml.

Related

Open docker port running on host network to outside traffic

How do I get my docker container running gunicorn / FastAPI server to respond to outside traffic?
This is how my container runs
docker run --detach --net host -v "/path/to/app/app":"/app" -it me/app:appfastapi_latest /start.sh
cat start.sh
#! /usr/bin/env sh
set -e
# Start Gunicorn
exec gunicorn -k "uvicorn.workers.UvicornWorker" -c /app/gunicorn_conf.py "main:app"
cat ./app/gunicorn_conf.py
...
host = "0.0.0.0"
port = "8000"
bind = f"{host}:{port}"
...
docker logs container_id
...
[2022-02-15 05:40:10 +0000] [1] [INFO] Listening at: http://127.0.0.1:8000 (1)
^^^ this was before a fix in the conf, now its
0.0.0.0:8000
...
Curl container from host
curl localhost:8000/hw {"message":"Hello World"}
This is how it should be. But when I do
curl domain:8000/hw
curl: (7) Failed to connect to domain port 8000: Connection refused
I do not know how to troubleshoot this. In the FastAPI main I have
ORIGINS = [
"http://127.0.0.1:8000",
"http://localhost:8000",
"http://domain:8000",
]
app = FastAPI(title="MY API", root_path=ROOT_PATH, docs_url="/")
app.add_middleware(
CORSMiddleware,
allow_origins=ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
and I have the firewall open (I believe)
sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 172.17.0.2 anywhere tcp dpt:mysql
ACCEPT tcp -- anywhere anywhere tcp dpt:8000
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain DOCKER (1 references) target prot opt source destination Chain DOCKER-ISOLATION-STAGE-1 (1 references) target prot opt source destination DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere RETURN all -- anywhere anywhere Chain DOCKER-ISOLATION-STAGE-2 (1 references) target prot opt source destination DROP all -- anywhere anywhere RETURN all -- anywhere anywhere
that I have opened for port 8000 with
sudo iptables -A INPUT -p tcp --dport 8000 -j ACCEPT
The system I am on is Debian9,
docker --version
Docker version 19.03.15, build 99e3ed8919
Listening at: http://127.0.0.1:8000
means that gunicorn listening localhost of docker container. Container's localhost is not accessible from external network. You should set 0.0.0.0:8000 to be able access from outside.
Yes, you tried to set
host = "0.0.0.0"
port = "8000"
But gunicorn config file doesn't have host and port parameters. You should use bind = '0.0.0.0:8000' instead.
And don't forget to publish port -p 8000:8000 when run container

cant reach docker container from outside host with port mapping

I am using a really simple docker-compose file from here:
https://github.com/brandonserna/flask-docker-compose
this is the docker compose file:
version: '3.5'
services:
flask-app-service:
build: ./app
volumes:
- ./app:/usr/src/app
- .:/user/src
ports:
- 5555:9999
However I can only reach the app from outside network when I am using port 80.
ports:
- 80:9999
When I am using for example port 8000. I cant reach the container from outside network.
From the local machine I can reach the app. (Tested with wget localhost:8000)
ports:
- 8000:9999
iptables -L gives me this:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (2 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.18.0.2 tcp dpt:9999
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:http
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target prot opt source destination
DROP all -- anywhere anywhere
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere
Not enough for comment so this is why:
From what it seems it could be either firewall rule in your host running the container or one between the host to your house.
To test which on between the two I'd try to use nmap with --reason and --tracerout options, since we have connectivity in another port it's unlikely that there is a complete block between your home and the container so the traceroute wouldn't give much info but just in case.
Also if you have root access to the host machine or just to the iptables service try to stop it to check if that's the root cause for the block.
also check with docker ps if the port is bound to the port on the machine, should look something like this:
0.0.0.0:port --> tcp\port
where instead of port you have the port number
If it doesn't maybe it's due to some problem with the docker-compose up command so try to run the service with a simple docker run command

Accessing Docker container from non-host device

Bear with me, I'm new to Docker...
I'm trying to get a Docker environment going on a Red Hat Linux server (7.6) and am having trouble accessing containers from a computer other than the host.
I got Docker installed no problem. Then, the first container I installed was Portainer and the Portainer Agent:
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
docker run -d -p 9001:9001 --name portainer_agent --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes portainer/agent
Seems peachy:
# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
973a685cfbe1 portainer/portainer "/portainer" 19 hours ago Up 2 minutes 0.0.0.0:8000->8000/tcp, 0.0.0.0:9000->9000/tcp portainer
602537dc21ec portainer/agent "./agent" 45 hours ago Up 19 hours 0.0.0.0:9001->9001/tcp portainer_agent
And using # curl http://localhost:9000 connects just fine. However, the connection gets dropped when attempting to connect from another computer on the same network (in a different subnet, if that matters). I can connect to the server just fine (I'm managing it via SSH, and even tested netcat on port 9002 for good measure).
The iptables, if this helps:
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (2 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:etlservicemgr
ACCEPT tcp -- anywhere 172.17.0.3 tcp dpt:cslistener
ACCEPT tcp -- anywhere 172.17.0.3 tcp dpt:irdmi
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target prot opt source destination
DROP all -- anywhere anywhere
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere
I've searched around a bit but keep finding conflicting answers (some suggesting that it should just work, and others suggesting that there's a lot more I've got left to learn and configure). I'm afraid that I'm fumbling in the dark. I gather that I need a route configured to forward host traffic to the container? Or an iptables rule? What exactly am I missing?
...Nevermind.
On a lark, I tried connecting to the server from a device that's on-premises; rather than my computer which is connected via VPN. The on-prem device connected fine.

Unable to reach container webserver from host localhost

Using Docker v 17.03.1-ce, on a linux mint machine, i'm unable to reach the container web server (container port 5000) with my browser (localhost port 9000) on the host.
Container launched with command :
sudo docker run -d -p 9000:5000 --name myContainer imageName
I started by checking that the server (flask) on my container was properly launched. It's launched.
I wanted to check that the server was working properly, so in the container, using curl, i sent a GET request on localhost, port 5000. The server returned the web page
So, the server is working, therefore the issue lies somewhere in the communication between container and host.
I checked iptables, but am not sure what to make of it:
sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-ISOLATION all -- anywhere anywhere
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (2 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:5000
Chain DOCKER-ISOLATION (1 references)
target prot opt source destination
DROP all -- anywhere anywhere
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
sudo iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE all -- 172.18.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:5000
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9000 to:172.17.0.2:5000
Expected result : using my browser, with url "localhost:9000", i can receive the homepage sent from the container, through port 5000.
edit: Adding docker logs and docker ps
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
59a20248c5b2 apptest "python3 src/jboos..." 12 hours ago Up 12 hours 0.0.0.0:9000->5000/tcp jboost
sudo docker logs jboost
* Serving Flask app "jboost_app" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 310-292-856
127.0.0.1 - - [03/Jul/2019 04:12:54] "GET / HTTP/1.1" 200 -
edit 2: adding results for curl localhost:9000 on host machine
So when connecting with my web browser, the connection doesn't work, but curl gives a more specific message:
curl localhost:9000
curl: (56) Recv failure: Connection reset by peer
I found the solution in this post : https://devops.stackexchange.com/questions/3380/dockerized-flask-connection-reset-by-peer
The Docker networking and port forwarding were working correctly. The problem was with my flask server. It seems that by default, the server is configured to only accept requests from local host.
When launching your flash server, with the "run" command, you must specify host='0.0.0.0' , so that any ip can be served.
if __name__ == "__main__":
app.run(host='0.0.0.0')

Container-to-container communication via a host mapped port

I am using Docker version 1.9.1 and docker-compose 1.5.2 with --x-networking (experimental networking).
I start a trivial node application with docker-compose up; this application maps port 8000 to port 9999 on the host.
From the host I can curl http://localhost:9999; or http://[host-ip]:9999; or any of the 172.x.0.1 addresses that the host has and they all work.
I start another application with docker-compose up. If I attempt to curl http://[host-ip]:9999, or any of the http://172.x.0.1 addresses the packet is dropped due to iptables entries -- in particular the entry that specifies DROP from the subnet of this container to the first container.
I understand that container-to-container communication may not be allowed but how can my second container talk to the first via the port mapped on the host?
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DROP all -- 172.17.0.0/16 172.19.0.0/16
DROP all -- 172.19.0.0/16 172.17.0.0/16
DROP all -- 172.18.0.0/16 172.19.0.0/16
DROP all -- 172.19.0.0/16 172.18.0.0/16
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
DROP all -- 172.17.0.0/16 172.18.0.0/16
DROP all -- 172.18.0.0/16 172.17.0.0/16
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (3 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.18.0.2 tcp dpt:8000
Container to container communication is allowed of course. You could forbid it with firewall rules etc...
What you actually need is to have these two containers in the same subnet. So you need to create a subnet with
docker network create --subnet=172.18.0.0/16 mySubNet
then run the containers with
docker run --net mynet123
And that is it. Additionally when running you could assign a static ip to container with --ip, assign a hostname with --hostname or add another host entry with --add-host.
EDIT: I see now your docker version so I have to say that what I wrote here works with docker 1.10.x
Subnet solution
You can either create a subnet for your containers, but to keep things clean you will need a subnet for each distributed application in order to isolate them. Not the easiest nor the simplest way of doing so while it works.
--link solution
Another solution is to link your containers. I suggest you to read this comment, so just I don't copy/paste its content ;)

Resources