Dynamic upstreams are possible in Nginx (normal, sans Plus) but with tricks and limitations.
You give up on upstream directive and use plain proxy_pass.
It gives round robin load balancing and failover, but no extra feature of the directive like weights, failure modes, timeout, etc.
Your upstream hostname must be passed to proxy_pass by a variable and you must provide a resolver.
It forces Nginx to re-resolve the hostname (against Docker networks' DNS).
You lose location/proxy_pass behaviour related to trailing slash.
In the case of reverse-proxying to bare / like in the question, it does not matter. Otherwise you have to manually rewrite the path (see the references below).
Let's see how it works.
docker-compose.yml
version: '2.2'
services:
reverse-proxy:
image: nginx:1.15-alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- 8080:8080
app:
# A container that exposes an API to show its IP address
image: containous/whoami
scale: 4
Traefik relies on Docker API directly and may be a simpler and more configurable option. Let's see it in action.
docker-compose.yml
version: '2.2'
services:
reverse-proxy:
image: traefik
# Enables the web UI and tells Traefik to listen to docker
command: --api --docker
ports:
- 8080:80
- 8081:8080 # Traefik's web UI, enabled by --api
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
app:
image: containous/whoami
scale: 4
labels:
- "traefik.frontend.rule=Host:localhost"
The docker-compose --scale command allows you to scale your Docker Compose services by specifying the number of replicas (instances) for each service. This command makes it easy to scale services up or down on demand.
docker-compose up --scale SERVICE=NUM_REPLICAS
To both services, we can simply run
docker-compose up --build --scale server=3 --scale computations=3
If we run this, we can see something like this
We have 3 instances of computations and 3 instances of the server
You can see how we are now running 3 instances of each service that we scale.
Load Balancing Strategy
By default, Traefik uses the Round Robin load balancing strategy, but you can change this by adding the appropriate label to your service. For example, to use the Weighted Round Robin strategy, you would add:
But without changing anything. Traefik will automatically discover the new instances of your computations and serverservice and load balance incoming requests.
Now that we have everything we need, let's use the following command to see if everything works out properly or not. If everything works properly, then nginx should act as a reverse proxy and load balancer.
docker compose up --scale api=3
docker compose up --scale api=3 is a command that is used to start a set of containers defined in a Docker Compose file and scale an API service in the Compose file to run three instances of that service.
The hostname that is displayed, is actually the container ID. Since we have 3 containers let's check if the load balancer is working properly or not. For context, the round-robin algorithm is used in this demo.
Here is the container ID.
Here we can see that every time we request for API server we see that a new container is responding.
Voilà, there you go that's how you scale docker containers with nginx. Big thanks to trulymittal<3
version: '2.3'
# Note: `services.app.scale` available only version 2.x
# In version 3.x scale option will produce error:
# "Unsupported config option for services.app: 'scale'"
# You can use `docker-compose up --scale app=3`
# instead of `scale` field for version 3.x compose files
services:
app:
build: .
image: "scale-app-example"
scale: 3
nginx:
image: nginx:stable-alpine
ports:
- 8000:80
depends_on:
- app
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./var/log/nginx:/var/log/nginx