Scaling with Docker Compose and Configuring Load Balancer

Recently I was creating a load balancer for my web api with nginx. Since I was using docker to test in my local machine, I used the scale arguement to scale my Web API container.

nt.authservice.service:ports:-"8101-8105:80"

Scaling using

docker-compose -f server\nt.microservice\docker-compose.yml -f server\nt.microservice\docker-compose.override.yml up --scale nt.authservice.service=5 -d

This however resulted in following error.

Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:8101 -> 0.0.0.0:0: listen tcp 0.0.0.0:8101: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.

My nginx configuration at this point was as the following.

events{

}
http{
upstream authservice {
	server host.docker.internal:8101;
	server host.docker.internal:8102;
	server host.docker.internal:8103;
	server host.docker.internal:8104;
	server host.docker.internal:8105;
}
server {
	listen 80;
	server_name authservice;
	location / 	{
		proxy_pass http://authservice;
	}}

}

Notice that I had explicitly given the ports for upstream sources, based on my configuration in the docker compose. However, as noted earlier, the docker compose failed to scale the containers (some of them are created, while rest not) as required, which would mean my loadbalancer would be attempting to connect to server, which doesn’t exist.

Fixing Scaling

To fix the scaling issue, I noticed that I needn’t expose my scaled container instances to the host. Hence I replaced the ports with expose.

nt.authservice.service:expose:-"80"

Fix Nginx Load Balancer Configuration

This would mean, I would also have to make some changes to my nginx configuration, since I no longer control the ports. This can be solved by addressing the scaled containers with container name instead of host.docker.internal. My modified configuration for nginx looked as following.

events{

}
http{
upstream authservice {
	server nt.authservice.service:80;
}
server {
	listen 80;
	server_name authservice;
	location / 	{
		proxy_pass http://authservice;
	}}

}


With that in place, I am now all set to scale my web api and have the load balancer support it.

Leave a comment