resolve docker network alias from multiple networks - docker

Consider following scenario. I have 2 containers on 2 different networks with the same alias app.
$ docker network create net1
$ docker network create net2
$ docker run --name app1 -d --rm --network net1 --network-alias app traefik/whoami
$ docker run --name app2 -d --rm --network net2 --network-alias app traefik/whoami
Now, I am running a third container that is connected to both networks and query the DNS resolver for the alias app.
$ docker run --name dig --rm -d tutum/dnsutils sleep infinity
$ docker network connect net1 dig
$ docker network connect net2 dig
$ docker exec dig bash -c 'for _ in {1..5}; do dig +short app; done'
172.26.0.2
172.26.0.2
172.26.0.2
172.26.0.2
172.26.0.2
I did expect to get DNS round-robin from this kind of setup. Meaning, dig should get 2 A records back. Since, is connected to both networks and can resolve the apps by their names.
$ docker exec dig dig +short app1 app2
172.26.0.2
172.27.0.2
The above output shows that when using the alias for the query, only app1 is resolved. It seems like because it was the network the dig container was connected to first.
Is there a way to solve this, or at least specify in which network I am looking for the alias? And is the above behaviour deterministic?

Related

Redis docker, cannot connect to redis-cli

I am trying to run redis with persistence storage. I followed official docker page of redis fo installation.
I pulled the image using -
docker pull redis
I started redis with persistence storage using -
docker run --name some-redis -d redis redis-server --appendonly yes
And I am tring to connect to redis instance with redis cli with -
docker run -it --network some-network --rm redis redis-cli -h some-redis
It gives me following error -
docker: Error response from daemon: network some-network not found.
I am following the documentation to the point, why is this not working?
Both answers give interesting information but lack the main thing.
In docker, containers may connect to some networks.
By default if you don't specify any network when you run a container, it will use the default bridge network : inside that network any container can communicate with any other but only via their ip addresses.
With the default bridge network
You cannot communicate between containers of that network via container name.
So here docker run -it --network some-network --rm redis redis-cli -h some-redis, the some-redis part is not a resolvable hostname.
To overcome that, you have to refer the container by its ip address.
Inspect the container to know that :
docker container inspect some-redis | grep -i ipaddress
You should get something like : "IPAddress": "172.17...."
Now specify the ip address as -h parameter and it should be fine :
docker run -it --network some-network --rm redis redis-cli -h 172.17...
That is really not a net/reusable/portable way to make two containers to communicate each other. That is more suitable to experiment things.
With a custom bridge network
You can communicate between containers of that network via container name.
Create your network :
docker network create redis-network
Run the redis server and connect it to that network :
docker run --name some-redis -d --network redis-network redis redis-server --appendonly yes
Run the redis client and connect it to that network :
docker run -it --rm --network redis-network redis redis-cli -h some-redis
Now the client can connect to the server instance via -h some-redis.
First create the network
docker network create some-network
then use it in all your containers that have to use the network.
docker run --network some-network
When you have finished remove the network.
docker network rm some-network
First ,you this command run as redis-server
docker run --name some-redis -d redis redis-server --appendonly yes
Next,you want run redis-cli to connect redis-server
should be attach redis-server container and run redis-cli
docker exec -it some-redis redis-cli -h
Of course, if you want to access through the network like a redis page, you need to attach the network of the cli's container to the redis-server container to share the network
docker run --rm -it --net=container:some-redis redis redis-cli -h

Expected exposed port on Redis container isn't reachable, even after binding the port

I'm having a rather awful issue with running a Redis container. For some reason, even though I have attempted to bind the port and what have you, it won't expose the Redis port it claims to expose (6379). Obviously, I've checked this by scanning the open ports on the IP assigned to the Redis container (172.17.0.3) and it returned no open ports whatsoever. How might I resolve this issue?
Docker Redis Page (for reference to where I pulled the image from): https://hub.docker.com/_/redis/
The command variations I have tried:
docker run --name ausbot-ranksync-redis -p 127.0.0.1:6379:6379 -d redis
docker run --name ausbot-ranksync-redis -p 6379:6379 -d redis
docker run --name ausbot-ranksync-redis -d redis
docker run --name ausbot-ranksync-redis --expose=6379 -d redis
https://gyazo.com/991eb379f66eaa434ad44c5d92721b55 (The last container I scan is a MariaDB container)
The command variations I have tried:
docker run --name ausbot-ranksync-redis -p 127.0.0.1:6379:6379 -d redis
docker run --name ausbot-ranksync-redis -p 6379:6379 -d redis
Those two should work and make the port available on your host.
Obviously, I've checked this by scanning the open ports on the IP assigned to the Redis container (172.17.0.3) and it returned no open ports whatsoever. How might I resolve this issue?
You shouldn't be checking the ports directly on the container from outside of docker. If you want to access the container from the host or outside, you publish the port (as done above), and then access the port on the host IP (or 127.0.0.1 on the host in your first example).
For docker networking, you need to run your application listening on all interfaces (not localhost/loopback). The official redis image already does this, and you can verify with:
docker run --rm --net container:ausbot-ranksync-redis nicolaka/netshoot netstat -lnt
or
docker run --rm --net container:ausbot-ranksync-redis nicolaka/netshoot ss -lnt
To access the container from outside of docker, you need to publish the port (docker run -p ... or ports in the docker-compose.yml). Then you connect to the host IP and the published port.
To access the container from inside of docker, you create a shared network, run your containers there, and access using docker's DNS and the container port (publish and expose are not needed for this):
docker network create app
docker run --name ausbot-ranksync-redis --net app -d redis
docker run --name redis-cli --rm --net app redis redis-cli -h ausbot-ranksync-redis ping

How to connect to server on Docker from host machine?

Ok, I am pretty new to Docker world. So this might be a very basic question.
I have a container running in Docker, which is running RabbitMQ. Let's say the name of this container is "Rabbit-container".
RabbitMQ container was started with this command:
docker run -d -t -i --name rmq -p 5672:5672 rabbitmq:3-management
Python script command with 2 args:
python ~/Documents/myscripts/migrate_data.py amqp://rabbit:5672/ ~/Documents/queue/
Now, I am running a Python script from my host machine, which is creating some messages. I want to send these messages to my "Rabbit-container". Hence I want to connect to this container from my host machine (Mac OSX).
Is this even possible? If yes, how?
Please let me know if more details are needed.
So, I solved it by simply mapping the RMQ listening port to host OS:
docker run -d -t -i --name rmq -p 15672:15672 -p 5672:5672 rabbitmq:3-management
I previously had only -p 15672:15672 in my command. This is mapping the Admin UI from Docker container to my host OS. I added -p 5672:5672, which mapped RabbitMQ listening port from Docker container to host OS.
If you're running this container in your local OSX system then you should find your default docker-machine ip address by running:
docker-machine ip default
Then you can change your python script to point to that address and mapped port on <your_docker_machine_ip>:5672.
That happens because docker runs in a virtualization engine on OSX and Windows, so when you map a port to the host, you're actually mapping it to the virtual machine.
You'd need to run the container with port 5672 exposed, perhaps 15672 as well if you want WebUI, and 5671 if you use SSL, or any other port for which you add tcp listener in rabbitmq.
It would be also easier if you had a specific IP and a host name for the rabbitmq container. To do this, you'd need to create your own docker network
docker network create --subnet=172.18.0.0/16 mynet123
After that start the container like so
docker run -d --net mynet123--ip 172.18.0.11 --hostname rmq1 --name rmq_container_name -p 15673:15672 rabbitmq:3-management
note that with rabbitmq:3-management image the port 5672 is (well, was when I used it) already exposed so no need to do that. --name is for container name, and --hostname obviously for host name.
So now, from your host you can connect to rmq1 rabbitmq server.
You said that you have never used docker-machine before, so i assume you are using the Docker Beta for Mac (you should see the docker-icon in the menu bar at the top).
Your docker run command for rabbit is correct. If you now want to connect to rabbit, you have two options:
Wrap your python script in a new container and link it to rabbit:
docker run -it --rm --name migration --link rmq:rabbit -v ~/Documents/myscripts:/app -w /app python:3 python migrate_data.py
Note that we have to link rmq:rabbit, because you name your container rmq but use rabbit in the script.
Execute your python script on your host machine and use localhost:5672
python ~/Documents/myscripts/migrate_data.py amqp://localhost:5672/ ~/Documents/queue/

Need Explanation for the docker documentation on the swarm

I finished this documentation:
https://docs.docker.com/swarm/install-w-machine/
It works fine.
Now I tried to setup this EC2 instances by following this documentation:
https://docs.docker.com/swarm/install-manual/
I am in Step 4. Set up a discovery backend
I cannot understand the steps what I need to do further.
I created 5 nodes in EC2: manager0, manager1, consul0, node0, node1. Now I need to know how to setup service discovery with swarm.
In that document they ask us to connect manager0 and consul0 then ifconfig, then they given as etc0 instance. I don't know where this is coming from.
Ultimately I need to know where (in which node?) to run this command:
$ docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap
Any suggestion for me How to clear this step?
Consul will run on the consul0 server you created. So basically you first need to be able to run docker on worker0 and worker1 remotely, this is step 3. A better way of doing this is editing the daemon directly with the command:
sudo echo 'DOCKER_OPTS="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"' > /etc/default/docker`
Then restart docker. Afterwards you will find that you can run docker remotely from master0, master1 or any other instance behind your firewall with docker commands that start with:
docker -H $WORKER0_IPADDRESS:2375
For example if your workers ip address was 1.2.3.4 this would run the docker ps command remotely:
docker -H 1.2.3.4:2375 ps
This is what swarm runs on. Then start up your consul server with the command you want to run, you got that one right and thats it you wont do anything else with the consul0 server except use its IP address when you run your swarm commands.
So if $CONSUL0 represented the IP address of your consul server this is how you would set up the rest of swarm. If you ran each of them on the local machine of each node:
On consul0:
docker run -d -p 8500:8500 --restart=unless-stopped --name=consul progrium/consul -server -bootstrap
On master0 and master1:
docker run --name=master -d -p 4000:4000 swarm manage -H :4000 --replication --advertise $(hostname -i):4000 consul://$CONSUL0:8500
On worker0 and worker1:
docker run -d --name=worker swarm join --advertise=$(hostname -i):2375 consul://$CONSUL0:8500/

docker: connect to database container via dockerhost

I am trying to connect from an application container to a database container in two situations, one succeeds, one doesn't.
There are two containers on my dockerhost:
mysql container with port 3306 connected to 3356 on dockerhost
application container
At work, dockerhost has IP-address 10.0.2.15, at home, dockerhost has IP-address 192.168.8.11 (hostname -I).
In both situations, I want to connect to the database container from the app container with host 10.0.2.15/192.168.8.11 and port 3356.
When I do this at work (Windows network, Vagrant/Virtualbox dockerhost), this is no problem. I can 'telnet 10.0.2.15 3356' from the app container and connect to the db container.
When I do this at home (Ubuntu), it is impossible to connect. The only way is to use the docker ip address of the db container (172.17.0.2) with port 3306. However, I can ping 192.168.8.11.
The scripts to start the containers are identical; I do not use --add-host, so the dockerhost IP-address is not in /etc/hosts.
Any suggestions?
Ok, use docker to run 3 database instances
docker run --name mysqldb1 -e MYSQL_ROOT_PASSWORD=changeme -d mysql
docker run --name mysqldb2 -e MYSQL_ROOT_PASSWORD=changeme -d mysql
docker run --name mysqldb3 -e MYSQL_ROOT_PASSWORD=changeme -d mysql
Each one will have a different IP address on my host machine:
$ for i in mysqldb1 mysqldb2 mysqldb3
> do
> docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $i
> done
172.17.0.2
172.17.0.3
172.17.0.4
Repeat this on your machine and you'll very likely have different IP addresses.
So how is this problem fixed.
The older approach (deprecated in docker 1.9) is to use links. The following commands will shows how environment variables are set within your linked application container (the one using the database)
$ docker run -it --rm --link mysqldb1:mysql mysql env
..
MYSQL_PORT_3306_TCP_ADDR=172.17.0.2
$ docker run -it --rm --link mysqldb2:mysql mysql env
..
MYSQL_PORT_3306_TCP_ADDR=172.17.0.3
$ docker run -it --rm --link mysqldb3:mysql mysql env
..
MYSQL_PORT_3306_TCP_ADDR=172.17.0.4
And the following demonstrates how links are also created:
$ docker run -it --rm --link mysqldb1:mysql mysql grep mysql /etc/hosts
172.17.0.2 mysql 2a12644351a0 mysqldb1
$ docker run -it --rm --link mysqldb2:mysql mysql grep mysql /etc/hosts
172.17.0.3 mysql 89140cbf68c7 mysqldb2
$ docker run -it --rm --link mysqldb3:mysql mysql grep mysql /etc/hosts
172.17.0.4 mysql 27535e8848ef mysqldb3
So you can just refer to the other container using the "mysql" hostname or the "MYSQL_PORT_3306_TCP_ADDR" environment variable.
In Docker 1.9 there is a more powerful networking feature that enables containers to be linked across hosts.
http://docs.docker.com/engine/userguide/networking/dockernetworks/
you can use my container acting as a NAT gateway to dockerhost without any manually setup https://github.com/qoomon/docker-host

Resources