Docker Port Detection - docker

I have a docker container that listens on a socket, lets say its udp port 20000. (this is iot udp data coming in)
This app can (and should) be loadbalanced.
I publish it to my docker host and expose the port. Docker assigns some random port on the docker host.
I need to add this container to the pool on my loadbalancer, which sits outside of the docker network.
How do I automate this? Any time a new instance of this container starts I need to add it to the pool. When it dies I need to remove it from the pool.

The pattern which worked for me is to use 2 pieces:
Registrator, which detects containers as they go on-line and register them in a kind of service registry (e.g. Consul).
Load-balancer that is aware (watches) of services registered and changing its configuration accordingly. In my particular case it was HAProxy supported by Consul Template, which did a great job in automating all this stuff.
In general, this pattern can vary in details, but usually it will be something like that.

Related

Is it possible to switch port binding between docker containers without downtime?

Scenario:
There is a container running with image version 1.0 and exposed port 8080 on localhost 80. The new version of the image is available, and there is a need to switch those versions. No, any orchestration tool is running ( Kubernetes, OpenShift etc...).
Is it possible to start a container with version 1.1 make it run without a problem
Please, keep in mind that I don't want to keep it simple, no replication, etc.
Simply docker container with the binded port to localhost.
Questions:
1. Is it possible to switch exposing of port between containers without downtime?
2. If not, is there is any mechanism implemented with docker (free edition) to do such switch?
Without downtime, you'd need a second replica of the service up an running, and a proxy in front of that service that's listening to user requests and routing from one to the other. Both Swarm Mode and Kubernetes provide this capability with similar tools, the port being exposed is indirectly connected to the app via either an application reverse proxy, or some iptables rules and ipvs entries in the kernel.
Out of the box, recent versions of docker include support for Swarm Mode with nothing additional to install. You can run a simple docker swarm init to start a single node swarm cluster in less than a second. And then instead of docker-compose up you switch to docker stack deploy -c docker-compose.yml $stack_name to manage your projects with almost the same compose file. For swarm mode, you'll want to be on version 3 of the compose file syntax.
For a v3 syntax compose file in swarm mode that has no outage on an update, you'll want healthcheck's defined in your image to monitor the application and report back when it's ready to receive requests. Then you'll want a deploy section of the compose file to either have multiple replicas for HA, or at least configure a single replica to have a "start-first" policy to ensure the new service is up before stopping the old one. See the compose docs for settings to adjust: https://docs.docker.com/compose/compose-file/#update_config
For an application based reverse proxy in docker, I really do like traefik, but more to allow me to run multiple http based container services with a single port opened. This allows me to mapping requests based off the hostname/path/http header to the right container, while at the same time giving features to migrate between different versions with weighting of which backend to use so you can do more than a simple round-robin load balancing during an upgrade.
There is no mechanism native to Docker that would allow you replace one container with another with no interruption. On the other hand, the duration of the interruption can probably be measured in milliseconds; whether or not this is really an issue for you depends entirely on your application.
You can get the behavior you want by introducing a dynamic reverse proxy such as Traefik into your configuration. The proxy binds to host ports and handles requests from remote systems, then distributes those requests to one or more backend containers.
You can create and remove backend containers as you please, and as long as at least one is running your application will be available. For your specific use case, this means that you can start the new version of your application first, then retire the old one, all without any interruption in service.

Talk to server on docker container with no exposed ports

I have some docker containers talking together through docker bridge networks. They cannot be accessed from outside (I was said) as they are launched from a script with a default command which does not include 'expose' nor '-p' option. I cannot change that script.
I would like to connect to one of this containers which runs a server and listens for requests on port 8080. I tried connecting that bridge to a newly created docker bridge network, but i did not succede.
Now I am thinking of creating a new container and letting it talk to the server one (through bridge networks). As it is a new contaienr I can use the 'expose' or '-p' options, so it would be able to talk to the host machine.
Is it a good idea? How can I forward every request made to that container to the server one and get responses back to the host machine then?
Thanks
Within the default docker network, all ports are exposed. So you only need a container that exposes a port to the host machine and is in the same network as the other containers you have already created.
This is a relatively normal pattern. You can use a reverse proxy like nginx to achieve something like this.
There are some containers that automate this process:
https://github.com/jwilder/nginx-proxy
If you have no control over the other containers though, you will need to write the proxy config by hand.
If the container to which you are trying to connect is an http server, you may be able to use a ready-made container image that can work as an http forwarder (e.g., nginx - it is relatively easy to configure it as an http forwarder).
If you need plain tcp forwarding, you could make a container running 'socat' (socat can work as a tcp forwarder).
NOTE: in either case, you will be exposing a listener that wasn't meant to be on a public address. Do take measures not to allow unauthorized connections.

Docker swarm mode, internally running several services with unique domain names but each on port 80

I'm trying to setup a microservice deployment (deployment file at https://github.com/mojlighetsministeriet/groups/blob/master/docker-compose.example.yml) with several services that will use HTTP (hopefully HTTPS later on) to communicate internally without being exposed outside the network. I later on will add a proxy service that will expose specific features. I want to do this specifically with docker swarm mode and I like the possibility to define the deployment in a docker-compose.yml so I can initiate with:
$ docker stack deploy my-platform -c docker-compose.example.yml
I want the API urls internally to be like GET http://identity-provider/public-key and GET http://groups/b0c44674-58e0-4a8a-87e0-e1de35088964 . I have done this with Kubernetes setups before and that works great but now I want to get this working with docker swarm mode.
The DNS parts works without any problems, but docker swarm mode won't allow me to have each service listening on port 80 (will later be 443). It keeps complaining about port conflicts even though each service has it's unique domain name like identity-provider or groups and so on.
Should I use a specific network driver to get this working? I currently use overlay.
Using domain names without random ports would make calling in between the services much more simple to remember than e.g. http://identity-provider:1234 and http://groups:1235, the ports only adds complexity to the setup.
I'm fine with using any super cutting edge version of docker-ce if that helps somehow.
This should be possible right?
Docker Swarm routes incoming requests based on the published port, you can't have two applications with the same port number in a single Swarm.

How to programmatically specify the IP and port of a dependent docker container created by Marathon?

I am learning Micro-services architecture by writing a small web app. The app has the following components, each of which will be hosted by a docker container.
In my API Gateway which is written in NodeJS, there is some place I will call:
request('http://service_b_ip_addr:port/get_service_b', callback);
However, both service_b_ip_addr and port are not known until Marathon has the Service B's docker container created.
With some Service Discovery mechanism, such as mesos-dns or marathon-lb, I guess that I could just change service_b_ip_addr to something like service_b.marathon.com.
But I've no idea how should I put the port in my program.
Thanks in advance for your help.
PS:
I am using BRIDGED network mode given that multiple instances of a Service could locate on the same Mesos slave. So port is a NATted random number.
Take a look at this answer.
If you use marathon-lb then there is no need to pass a port because it's a proxy and it will know where service is just by name.
If you use mesos-dns you should make a SRV request to get ip and port. In node you can do it with dns.resolveSrv(hostname, callback) but your DNS must be exposed on defaul (53) port and supports SRV request (mesos-dns supports it).

Docker Expose ports dynamically

Is it possible to expose docker ports dynamically, once a container is launched?
If not, what is the best practice to achieve something like this?
The use-case would be like:
I need to expose Java JMX Port momentarily to configure some application, and then close those ports (from the container), without actually closing the JMX Service, or modifying the Java application.
Thanks
With Weave network for Docker any port your application might open would be accessible from inside the network with no external intervention, unlike the aforementioned ambassador patter. However, those would be only accessible from the subnet the application is on. You the ports you statically expose will remain NATed by Docker too and would be externally accessible, but ephemeral once would be internal-only.
Never found a way to open ports dynamically.
Would it help to open a static port and start/stop a tunnel inside the container that forwards to the JMX Port.
socat or ssh comes to mind, e.g.
ssh -L<static-sourceport>:<targetserver>:<jmx-targetport> localhost
That's an interesting use case. I'm assuming you mean "publish docker ports dynamically". If so, you could look into something like the grand ambassador pattern, where you'd do something like:
Start your java/jmx container with only a static exposed port (nothing published to the host).
Bring up your ambassador container which publishes your jmx port temporarily.
When you're done, remove your ambassador.

Resources