Docker Compose: A Mini Orchestration Tool for Local Development
Scaling Docker Compose Services
Docker Compose is a mini orchestration tool that provides a way to orchestrate multi-container applications. An interesting feature it offers is the ability to scale services. Let's take an example: imagine you're running an application that uses PHP and you've anticipated higher traffic. Instead of running a single PHP container, you want to run 5 of them behind an NGINX web server. Docker Compose lets you do this with a simple command: docker compose alpha scale php=5. By executing this, you'd have a total of 5 PHP containers up and running. And because NGINX is linked to this PHP service, it can load-balance between these PHP instances.
However, a challenge arises when you consider scaling services like NGINX in this setup. If you recall, the NGINX service maps its internal port 80 to the host's port 8000. This is a 1-to-1 mapping. So if you tried to scale NGINX, the newly spawned container would also attempt to bind to the host's port 8000, resulting in a conflict. This is because a host port can only be bound to by one service at a time. As a result, in Docker Compose, scaling a service that uses port mapping directly to the host can introduce issues.
Now, keeping this in mind, let's discuss the following Docker Compose setup:
services:
db:
image: mysql:9.6.0
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: mypassword
MYSQL_DATABASE: wordpress
MYSQL_USER: user
MYSQL_PASSWORD: mypassword
wordpress:
depends_on:
- db
image: wordpress:6.9.0-apache
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: user
WORDPRESS_DB_PASSWORD: mypassword
volumes:
db_data:
In this setup, we're running a WordPress service that depends on a MySQL database. If you wanted to scale the WordPress service, you'd face the same challenge as discussed earlier with NGINX. The WordPress service is mapping its internal port 80 to the host's port 8000.
The solution to this problem is as simple as using a range of ports on the host instead of a single port. Instead of "8000:80", we can use "8000-8002:80". This way, when we scale the WordPress service to 3 instances, Docker Compose will map:
- The first instance to port 8000.
- The second instance to port 8001.
- The third instance to port 8002.
To explore this further, create a new folder and a new docker-compose.yml file with the updated port mapping:
mkdir -p $HOME/wordpress-scaled && cd $HOME/wordpress-scaled
cat << EOF > $HOME/wordpress-scaled/docker-compose.yml
services:
db:
image: mysql:9.6.0
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: mypassword
MYSQL_DATABASE: wordpress
MYSQL_USER: user
MYSQL_PASSWORD: mypassword
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
wordpress:
image: wordpress:6.9.0-apache
ports:
# Use a range of ports on the host to map to port 80 in the container
- "8000-8002:80"
restart: always
environment:
WORDPRESS_DB_HOSTPainless Docker - 2nd Edition
A Comprehensive Guide to Mastering Docker and its EcosystemEnroll now to unlock all content and receive all future updates for free.
Hurry! This limited time offer ends in:
To redeem this offer, copy the coupon code below and apply it at checkout:
