Multiple docker containers, IP addresses, VM, OSX - linux

I am running docker on OSX via boot2docker. I am using docker remotely, via the API.
I create several images of a web server. Docker assigns different IP address to each container, like 172.17.0.61. Each web server is running on port 8080.
Inside VM, I can ping the server on this address.
How can I map these different container IP addresses (from VM) to the same one in VM, but on different port? E.G.
<local.ip>:9001 -> 172.17.0.61:8080
<local.ip>:9002 -> 172.17.0.62:8080
where local.ip may be either ip from boot2docker or anything else.
Possible solution is to define port bindings when creating container and bind each container to a different port. However, I would like to avoid that, since this config becomes part of the container, and only exist because running on OSX. If I do all this above on linux, we would not have this issue.
How to map inner containers to different ports?

Publishing ports is the right solution. You have the same problem whether you're running remotely or locally, just the IP address changes.
For example, say I start the following web servers:
$ docker run -d -p 8000:80 nginx
$ docker run -d -p 8001:80 nginx
From inside the VM (run boot2docker ssh), I can then run curl localhost:8000 or curl localhost:8001 to reach the website. This is the normal way of working with Docker on Linux. From the Mac command line, it becomes curl $(boot2docker ip):8000 because of the VM, but we've not done anything different with regards to starting the web servers because of boot2docker.

Related

Two docker container (nginx and a web app) not working together (linux)

I built both containers using a Dockerfile (for each). I have the NGINX container pointing (proxy_pass http://localhost:8080) to the port that the web app is exposed (via -p 8080:80). I am able to get it to work when I just install NGINX in the linux machine, but when I use a dockerized NGINX, I just get the default NGINX index.html. Do I have to build both containers using Docker-Compose.yml file (as oppose to Dockerfile) when I want the containers working together? Sorry, if I didn't put any code, but at this point, I'm just wanting to know if I'm taking the correct approach (using Dockerfile or Docker-Compose).
The Nginx proxy needs access to the host (!) network for this to work, e.g.:
docker container run ... --net=host ... nginx
Without it, localhost refers to the proxy (localhost) which likely has nothing on :8080 and certainly not your web app.
Alternatively, if the proxy's container (!), can resolve|access the host then processes in the container can refer to host-accessible ports using the host's DNS name or IP.
Docker Compose (conventionally) solves this by putting the containers onto a new virtual network. The difference then would be that, rather than mapping everything onto host ports, each container (called a service) gets a unique name and a container called proxy could refer to a container called web on port 8080 as http://web:8080.
You may achieve similar results with Docker only by creating a network and then running containers on it, e.g:
docker network create ${NETWORK}
docker container run ... --net=${NETWORK} --name=proxy ...
...

Calling or communicating with docker container on one machine from other application not in docker container and in another machine

I have my docker container in one machine running say Machine A. I have another machine B which consists of a flask server. I would like to call/communicate with the docker container in machine A from my flask server in Machine B. I am not running my flask server inside any docker container. I am actually very new to docker so I am not sure whether we are able to achieve it or not.
I am not sure what you want to do with your docker container from the flask server, but I am assuming that it would be an API or some service running in the docker container which you want to use in the flask server. You can do so by using the IP of machine A on which docker container is running, also, you will need to bind your docker container's port to the host machine's ( machine A) port. So that whenever you try to reach the host machine on that specific port, you will be calling the containers port instead.
If you want to execute a command in the running container then there are 2 ways to do so, first, you can SSH to the container, second you can SSH to the host machine and then use docker exec. But since you are trying to communicate from a flask server, I think that this might not be the case.
You can just directly visit the http service in container from other machine.
E.g.
Container on machineA was this:
docker run -idt -p 9000:80 nginx
Then, you machineB's flask application, you can just use:
requests.get("http://your_machine_a_ip:9000")
to get what you need.
Just remember, for container, you need to expose http port to host, so other machine could visit it.

What does localhost means inside a Docker container?

Say, if I use this command inside a docker container.
/opt/lampp/bin/mysql -h localhost -u root -pThePassword
What would the localhost here refer to? The host machine's IP or the docker container's own IP?
From inside a container, localhost always refers to the current container. It never refers to another container, and it never refers to anything else running on your physical system that's not in the same container. It's not usually useful to make outbound connections to localhost or configure localhost as your database host.
From a shell on your host system, localhost could refer to daemons running on your system outside Docker, or to ports you've published with docker run -p options.
From a different system, localhost refers to the system it's called from.
In terms of IP addresses, localhost is always 127.0.0.1, and that IP address is special and is always localhost and behaves the same way as above.
If you want to make a connection to a container...
...from another container, the best way is to make sure they're on the same Docker network (you started them from the same Docker Compose YAML file; you did a docker network create and then did docker run --net ... on the same network) and use Docker's internal DNS service to refer to them by the container's --name or its name in the Docker Compose YAML file and the port number inside the container. Even if the target has a published port with a docker run -p option or Docker Compose ports: setting, use the second (container-internal) port number.
...from outside Docker space, make sure you started the container with a docker run -p or Docker Compose ports: option, and connect to the host's IP address or DNS name using the first port number from that option.
...from a terminal window or browser on the same physical host, not in a container, in this case and in this case only, localhost will work consistently.
Except:
If you started a container with --net host, localhost refers to the physical host, and you're in the "terminal window on the same physical host" scenario.
If you've gone out of your way to have multiple servers in the same container, you can use localhost to communicate between them.
If you're running in Kubernetes, and you have multiple containers in the same pod, you can use localhost to communicate between them. Between pods, you should set up a service in front of each pod/deployment, and use DNS names of the form service-name.namespace-name.svc.cluster.local.
Definitely, It will be your container, if you are running command in container.
/opt/lampp/bin/mysql -h localhost -u root -pThePassword
If you run this command inside container then it will try to connect mysql running inside container.

Can't get docker to accept request over the internet

So, I'm trying to get Jenkins working inside of docker as an exercise to get experience using docker. I have a small linux server, running Ubuntu 14.04 in my house (computer I wasn't using for anything else), and have no issues getting the container to start up, and connect to Jenkins over my local network.
My issue comes in when I try to connect to it from outside of my local network. I have port 8080 forwarded to the serve with the container, and if I run a port checker it says the port is open. However, when I actually try and go to my-ip:8080, I will either get nothing if I started the container just with -p 8080:8080 or "Error: Invalid request or server failed. HTTP_Proxy" if I run it with -p 0.0.0.0:8080:8080.
I wanted to make sure it wasn't jenkins, so I tried getting just a simple hello world flask application to work, and had the exact same issue. Any recommendations? Do I need to add anything extra inside Ubuntu to get it to allow outside connections to go to my containers?
EDIT: I'm also just using the official Jenkins image from docker hub.
If you are running this:
docker run -p 8080:8080 jenkins
Then to connect to jenkins you will have to connect to (in essence you are doing port forwarding):
http://127.0.0.1:8080 or http://localhost:8080
If you are just running this:
docker run jenkins
You can connect to jenkins using the container's IP
http://<containers-ip>:8080
The Dockerfile when the Jenkins container is built already exposes port 8080
The Docker Site has a great amount of information on container networks.
https://docs.docker.com/articles/networking
"By default Docker containers can make connections to the outside world, but the outside world cannot connect to containers."
You will need to provide special options when invoking docker run in order for containers to accept incoming connections.
Use the -P or --publish-all=true|false for containers to accept incoming connections.
The below should allow you to access it from another network:
docker run -P -p 8080:8080 jenkins
if you can connect to Jenkins over local network from a machine different than the one docker is running on but not from outside your local network, then the problem is not docker. In this case the problem is what ever machine who is receiving outside connection (normally your router, modem or ...) does not know to which machine the outside request should be forwarded.
You have to make sure you are forwarding the proper port on your external IP to proper port on the machine which is running Docker. This can be normally done on your internet modem/router.

Web service under Docker connection issue

I'm having some troubles running Apache under Docker, and I wanted to ask for some directions. My current setup is the following : I have Docker 0.8 installed on an Ubuntu 12.04 server.
I want to run an Apache server under Docker, and bind it to a specific ip on the host, my intention being to run multiple Apache servers under Docker on the same hardware node each with it's one interface.
Now, I've been able to start the Apache server inside Docker, and have it run like a daemon (-D FOREGROUND, or under supervisord), and I've even been able to bind it to 0.0.0.0:$PORT and access it from the outside. But when I created multiple interfaces on the hardware node let's say 10.10.10.1, and 10.10.10.2, and tried to bind to -p 10.10.10.1:80:80, I'm not able to access 10.10.10.1:80 from the outside.
A little info about the network setup: I have my eth0 interface which has trunking out of which I create multiple vlans on which I want to put Docker instances (probably with a bridge on the eth0.$VLAN_NO, when I want to put more on the same vlan).
So basically, to reiterate, i have started a Docker container bound with -p 10.10.10.1:80:80, with an Apache inside Docker on port 80 and I can't access it (although binded on 0.0.0.0:80:80 works).

Resources