More Docker containers on same port - docker

I'm studying Docker Desktop, and I have a question.
I have created two ASP.NET Core applications that are listening on the same port. I would like to have them respond by name (i.e.: http://app1.local/ and http://app2.local/). Is it possible with Docker?
Thanks

You can only have one process listening on a given port, so to achieve what you want, you can have a reverse proxy listening on the port and direct traffic to the applications behind, based on the host name in the request.
Some options for reverse proxies are Nginx, Traefik or the Ocelot library for .NET.

Related

Docker host multiple containers with different ip address but on same port

I have three tomcat containers running on different bridge networks with different subnet and gateway
For example:
container1 172.16.0.1 bridge1
container2 192.168.0.1 bridge2
container3 192.168.10.1 bridge3
These containers are running on different ports like 8081, 8082, 8083
Is there any way to run all three containers in same 8081?
If it is possible, how can I do it in docker.
You need to set-up a reverse proxy. As the name suggests, this is a proxy that works in an opposite way from the standard proxy. While standard proxy gets requests from internal network and serves them from external networks (internet), the reverse proxy gets requests from external network and serves them by fetching information from internal network.
There are multiple applications that can serve as a reverse proxy, but the most used are:
NginX
Apache
HAProxy mainly as a load-balancer
Envoy
Traefik
Majority of the reveres proxies can run as another container on your docker. Some of this tools are easy to start since there is ample amount of tutorials.
The reverse proxy is more than just exposing single port and forwarding traffic to back-end ports. The reverse proxy can manage and distribute the load (load balancing), can change the URI that is arriving from the client to a URI that the back-end understands (URL rewriting), can change the response form the back-end (content rewriting), etc.
Reverse HTTP/HTTP traffic
What you need to do to set a reverse proxy, assuming you have HTTP services, in your example is foloowing:
Decide which tool to use. As a beginner, I suggest NginX
Create a configuration file for the proxy which will take the requests from the port 80 and distribute to ports 8081, 8082, 8083. Since the containers are on different network, you will need to decide if you want to forward the traffic to their IP addresses (which I don't recommend since IP can change), or to publish the ports on the host and use the host IP. Another alternative is to run all of them on the same network.
Depending on the case, you need to setup the X-Forwarding-* flags and/or URL rewriting and content rewriting.
Run the container and publish the port 80 as 8080 (if you expose the containers on host, your 8081 will be already taken).
Reverse TCP/UDP traffic
If you have non-HTTP services (raw TCP or UDP services), then you can use HAProxy. Steps are same apart from the configuration step #2. The configuration is different due to non-HTTP nature of the traffic and you can find example in this SO

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.

How to host more than 65536 services, each requiring a distinct port?

I want to host web services (say a simple nodejs api service)
There is a limitation on the number of services that I can host on a single host, since the number of ports available on a host is only 65536.
I can think of having a virtual sub-network that is visible only within the host and then have a proxy server that sits on the host and routes the APIs to the appropriate web-service.
Is it possible to do this with dockers - where each service is deployed in a container, a proxy server routing the APIs to the appropriate container?
Is there any off the shelf solution for this (preferably free of cost).
First of all, I doubt you can run 65536 processes per host, unless it's huge. Anyway, I would not recommend that because of availability and performance. Too many processes will be competing for the same resources, leading to a lot of context switches. That said, it's doable.
If your services are HTTP you can use a reverse proxy, like nginx or traefik. If not, you can use HAProxy for TCP services. Traefik is a better option because it performs service discovery, so you won't need to configure the endpoints manually.
In this setup the networking should be bridge, which is the default in Docker. Every container will have its own IP address, so you won't have any problem regarding port exhaustion.

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).

Bluemix docker scalable group for non HTTP requests

Can scalable group option on Bluemix container infrastructure work with protocols other than HTTP?
I created a simple TCP server, deployed in a single container on Bluemix and works fine. If I try to deploy it as a scalable group I can only assign HTTP port and it does not respond any more.
Is this a current limitation?
Thank you very much
If you are running a Cloud Foundry app you can only get port 80,433. However if you run a container you can bind to any port you want.
containers environment on Bluemix actually supports a limited list of TCP (not UDP) ports, and 9080 is contained in this list, so your server should work.
If you need any different port from the ones contained in this list you could always ask for the port being opened for your instance, through Bluemix support.

Resources