How do I run 2 environments of SkyDns/Skydock simultaneously? - docker

Ref: https://github.com/crosbymichael/skydock
https://github.com/crosbymichael/skydns
First I fired up those two instances.
docker run -d -p 8080:8080 -p 172.17.42.1:53:53/udp --name skydns crosbymichael/skydns -nameserver 8.8.8.8:53 -domain docker
docker run -d -v /var/run/docker.sock:/docker.sock --name skydock crosbymichael/skydock -ttl 30 -environment dev -s /docker.sock -domain docker -name skydns
And this setup is working as expected.
Now I want to spawn another production environment. This time I only fired another skydock container with the env production as follows.
docker run -d -v /var/run/docker.sock:/docker.sock --name skydock-prod crosbymichael/skydock -ttl 30 -environment prod -s /docker.sock -domain docker -name skydns
Querying the api doesn't show the production skydoc.
curl $(docker-ip):8080/skydns/services/
And now I am wondering on how to setup the production version of skydock.
Do I have to run in separate docker-host?
If I fire up in the same docker host, in which DNS url entry will the new containers be available?
Do I have to pass some flags/variables when I fire new containers to be available in the production env?

I don't about the way to make 2 or more skydock instances listen to the same docker.sock (within single host machine). I think conceptually it is not right. Docker containers know nothing about your logical enviroments (production, staging, ...)
I got a multihost setup with skydns and skydock. I run skydns on a separate host. Each of two other servers run single instance of skydock, which registers all docker containers ips in centralised SkyDNS, so that all containers are visible by dns name across different physical hosts.
All of that is working on top of Flannel network overlay https://github.com/coreos/flannel (which requires etcd)

Related

Docker container communication restrictions

My setup is based on running two Docker containers, one with an API and the other with a DB.
This methodology makes it possible that both containers have an exposed port to web services.
But what I want is that the DB container (toolname-db) can only be exposed to the API container (toolname-api). This makes sure that the DB is not not exposed to web services directly.
How do I have to alter my setup in order to make sure what I want is possible?
Currently I use the following commands:
sudo docker build -t toolname .
sudo docker run -d -p 3333:3333 --name=toolname-db mdillon/postgis
sudo docker run -it -p 4444:4444 --name=toolname-api --network=host -d toolname
A container will only be reachable from outside Docker space if it has published ports. So you need to remove the -p option from your database container.
For the two containers to be able to talk to each other they need to be on the same network. Docker's default here is for compatibility with what's now a very old networking setup, so you need to manually create a network, though it doesn't need any special setting.
Finally, you don't need --net host. That disables all of Docker's networking setup; port mappings with -p are disabled, and you can't communicate with containers that don't themselves have ports published. (I usually see it recommended as a hack to work around hard-coded localhost connection strings.)
That leaves your final setup as:
sudo docker build -t toolname .
sudo docker network create tool
sudo docker run -d --net=tool --name=toolname-db mdillon/postgis
sudo docker run -d --net=tool -p 4444:4444 --name=toolname-api toolname
As #BentCoder suggests in a comment, it's very common to use Docker Compose to run multiple containers together. If you do, it creates a network for you which can save you a step.

What goes in "some-network" placeholder in dockerized redis cli?

I'm looking at documentation here, and see the following line:
$ docker run -it --network some-network --rm redis redis-cli -h some-redis
What should go in the --network some-network field? My docker run command in the field before did default port mapping of docker run -d -p 6379:6379, etc.
I'm starting my redis server with default docker network configuration, and see this is in use:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abcfa8a32de9 redis "docker-entrypoint.s…" 19 minutes ago Up 19 minutes 0.0.0.0:6379->6379/tcp some-redis
However, using the default bridge network produces:
$ docker run -it --network bridge --rm redis redis-cli -h some-redis
Could not connect to Redis at some-redis:6379: Name or service not known
Ignore the --network bridge command and use:
docker exec -it some-redis redis-cli
Docker includes support for networking containers through the use of network drivers. By default, Docker provides two network drivers for you, the bridge and the overlay drivers. You can also write a network driver plugin so that you can create your own drivers but that is an advanced task.
Read more here.
https://docs.docker.com/engine/tutorials/networkingcontainers/
https://docs.docker.com/v17.09/engine/userguide/networking/
You need to run
docker network create some-network
It doesn't matter what name some-network is, just so long as the Redis server, your special CLI container, and any clients talking to the server all use the same name. (If you're using Docker Compose this happens for you automatically and the network will be named something like directoryname_default; use docker network ls to find it.)
If your Redis server is already running, you can use docker network connect to attach the existing container to the new network. This is one of the few settings you're able to change after you've created a container.
If you're just trying to run a client to talk to this Redis, you don't need Docker for this at all. You can install the Redis client tools locally and run redis-cli, pointing at your host's IP address and the first port in the docker run -p option. The Redis wire protocol is simple enough that you can also use primitive tools like nc or telnet as well.

How to know server's IP address where jenkins deploys and builds code

Our jenkins deploys/builds code in a docker container. Every time Jenkins deploys code, it does so in different instance of docker container. How do I know IP address of that container along with port id? Immediately after deployment I want to run my Build Validation test against the application residing in that docker container.
Any insight would be appreciated.
You need to specify -p in docker run and then use docker inspect to grab the port:
docker run -d -p 80 --name app crramirez/limesurvey
export THEPORT=`docker inspect --format='{{(index (index .NetworkSettings.Ports "80/tcp") 0).HostPort}}' app`
Then you call your application: wget http://localhost:${THEPORT}
All of this is necessary if you have many containers running concurrently. But if you only deploy one container at time. You only need to delete the previous container and do a docker run -d -p 80:80 call your application using your port wget http://localhost:80
Regards

Docker – fix service IP addresses [duplicate]

This question already has answers here:
Assign static IP to Docker container
(8 answers)
Closed 7 years ago.
I have a docker-compose setup with a bunch of backend services (postgres, redis, ...), a few apps (rails, node, ...) and an nginx on top of it.
The apps are connected to the databases using docker env variables (e.g. DOCKERCOMPOSEDEMO_POSTGRES_1_PORT_5432_TCP_ADDR), and the nginx is connected to the apps using the docker generated /etc/hosts: (e.g. upstream nodeapp1-upstream { server dockercomposedemo_node_app1_1:3000; })
The problem is that each time I restart some service it gets a new IP address, and thus everything on top of it can't connect to it any more, so restarting a rails app requires to restart nginx, and restarting a database requires to restart the apps and the nginx.
Am I doing somethings wrong, or is it the intended behaviour? Always restarting all that stuff doesn't look like a good solution.
Thank you
It is an intended behaviour, there are many ways how to avoid restart of dependent services, I'm using next approach:
I run most of my dockerized services tied to own static ips using the next approach:
I create ip aliases for all services on docker host
Then I run each service redirecting ports from this ip into container so each service have own static ip which could be used by external users and other containers.
Sample:
docker run --name dns --restart=always -d -p 172.16.177.20:53:53/udp dns
docker run --name registry --restart=always -d -p 172.16.177.12:80:5000 registry
docker run --name cache --restart=always -d -p 172.16.177.13:80:3142 -v /data/cache:/var/cache/apt-cacher-ng cache
docker run --name mirror --restart=always -d -p 172.16.177.19:80:80 -v /data/mirror:/usr/share/nginx/html:ro mirror
...

Multiple docker containers as web server on a single IP

I have multiple docker containers on a single machine. On each container is running a process and a web server that provides an API for the process.
My question is, how can I access the API from my browser when the default port is 80? To be able to access the web server inside docker container I do the following:
sudo docker run -p 80:80 -t -i <yourname>/<imagename>
This way I can do from my computers terminal:
curl http://hostIP:80/foobar
But how to handle this with multiple containers and multiple web servers?
You can either expose multiple ports, e.g.
docker run -p 8080:80 -t -i <yourname>/<imagename>
docker run -p 8081:80 -t -i <yourname1>/<imagename1>
or put a proxy ( nginx, apache, varnish, etc.) in front of your API containers.
Update:
The easiest way to do a proxy would be to link it to the API containers, e.g. having apache config
RewriteRule ^api1/(.*)$ http://api1/$1 [proxy]
RewriteRule ^api2/(.*)$ http://api2/$1 [proxy]
you may run your containers like this:
docker run --name api1 <yourname>/<imagename>
docker run --name api2 <yourname1>/<imagename1>
docker run --link api1:api1 --link api2:api2 -p 80:80 <my_proxy_container>
This might be somewhat cumbersome though if you need to restart the api containers as the proxy container would have to be restarted either (links are fairly static at docker yet). If this becomes a problem, you might look at approaches like fig or autoupdated proxy configuration : http://jasonwilder.com/blog/2014/03/25/automated-nginx-reverse-proxy-for-docker/ . The later link also shows proxying with nginx.
Update II:
In a more modern versions of docker it is possible to use user defined network instead of the links shown above to overcome some of the inconveniences of the deprecated link mechanism.
Only a single process is allowed to be bound to a port at a time. So running multiple containers means each will be exposed on a different port number. Docker can do this automatically for you by using the "-P" attribute.
sudo docker run -P -t -i <yourname>/<imagename>
You can use the "docker port" and "docker inspect" commands to see the actual port number allocated to each container.

Resources