Nowadays, nearly every project we build or encounter utilizes Dockerized containers. However, scaling these containers when traffic spikes is a challenge that not everyone understands.
You might be familiar with Kubernetes or Docker Swarm as tools for container orchestration. While adopting Kubernetes is one thing, testing Kubernetes (K8s) locally presents unique challenges for developers. Nevertheless, gaining at least a foundational understanding of Kubernetes, pods, and how K8s can replace Docker Compose is crucial. I'll cover Kubernetes in a separate post, simplifying its implementation and providing guidance on how to use it effectively without unnecessary overhead.
What About Scaling Docker Without Kubernetes?
Let's focus on what can be achieved without Kubernetes. How do we scale Docker effectively?
Assuming you are already familiar with Docker's architecture and functionality.
In simple terms, you can scale a Docker service with a single command:
docker service scale api=10
But What About Handling Incoming Requests?
Once you scale the service, you might have questions like:
- How do you handle incoming requests?
- How are requests routed to different containers?
- What happens if one service instance gets overloaded with traffic?
The Solution: Load Balancer as a Service
We can introduce a load balancer to manage traffic and distribute requests across scaled services using a round-robin or similar strategy.
Here’s how to configure it using Docker Compose with NGINX as the load balancer.
Docker Compose Configuration
version: "3.9"
services:
api:
# Container name is omitted for scalability; Docker assigns dynamic names.
build: .
# No ports are mapped here as Docker manages ports internally for scaled services.
nginx:
image: nginx:latest
volumes:
- ./conf.d:/etc/nginx/conf.d
depends_on:
- api
ports:
- 3000:3000
How NGINX Works in This Setup
The nginx service will handle traffic routing through its configuration file. Here's an example:
NGINX Configuration (conf.d/default.conf)
server {
listen 3000;
location / {
proxy_pass http://api:3000;
}
}
This configuration proxies all incoming traffic on port 3000 to the api service. Since we've scaled the api service to multiple instances, NGINX will distribute the traffic across them.
Key Considerations:
Dynamic Port Mapping:
We didn't expose ports for the api service in the docker-compose.yml file. This is intentional because scaled services share the same container port internally, and Docker handles dynamic port assignment. NGINX, mapped to a single external port, manages routing to the internal services.Round-Robin Traffic Distribution:
By default, NGINX distributes traffic in a round-robin manner. This ensures no single instance gets overwhelmed.
And there you have it! You've successfully scaled your API service while ensuring balanced traffic distribution using NGINX as a load balancer. With this setup, scaling Docker services without Kubernetes becomes simple and efficient.
Cheers! Happy Coding
Top comments (0)