Why Use Docker Compose?
While its possible to manually run individual containers for Nginx, PHP, and MySQL, managing them becomes tedious when configuration changes are needed. Without an orchestration tool, updating a setting requires stopping the container, removing it, and running a new docker run command with the updated parameters.
Docker Compose solves this by allowing you to define your entire multi-container application in a single YAML file. With one command, you can spin up the whole stack, and when you need to change configurations, you simply edit the file and redeploy.
Installing Docker Compose
Download the binary directly from the official repository:
sudo curl -L "https://github.com/docker/compose/releases/download/v2.26.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Apply execution permissions:
sudo chmod +x /usr/local/bin/docker-compose
Verify the installation:
docker-compose version
Preparing Host Directories
To persist data and configuration, we need to copy default configurations from temporary containers to the host machine.
Extracting PHP-FPM Assets
docker run -p 9001:9000 -d --name temp-php php:7.4-fpm
docker cp temp-php:/usr/share/nginx/html/. ./app/www
docker cp temp-php:/usr/local/etc/php/. ./config/php
docker stop temp-php && docker rm temp-php
Extracting Nginx Assets
docker run --name temp-nginx -p 8080:80 -d nginx
docker cp temp-nginx:/usr/share/nginx/html/. ./app/www
docker cp temp-nginx:/etc/nginx/conf.d/. ./config/nginx
docker cp temp-nginx:/var/log/nginx/. ./logs/nginx
docker stop temp-nginx && docker rm temp-nginx
Extracting MySQL Assets
docker run -itd --name temp-mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=secret mysql
docker cp temp-mysql:/var/lib/mysql/. ./data/mysql
docker cp temp-mysql:/etc/mysql/. ./config/mysql
docker stop temp-mysql && docker rm temp-mysql
Extracting phpMyAdmin Assets
docker run --name temp-pma -d -e PMA_HOST=localhost phpmyadmin
docker cp temp-pma:/etc/phpmyadmin/. ./config/pma
docker stop temp-pma && docker rm temp-pma
Writing the Docker Compose File
Create a directory for the project (e.g., mkdir lnmp-stack && cd lnmp-stack) and create a file named docker-compose.yaml.
version: '3.8'
services:
webserver:
image: nginx:latest
container_name: nginx-service
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./app/www:/usr/share/nginx/html
- ./config/nginx:/etc/nginx/conf.d
- ./logs/nginx:/var/log/nginx
depends_on:
- php-handler
php-handler:
image: php:7.4-fpm
container_name: php-service
restart: unless-stopped
volumes:
- ./app/www:/usr/share/nginx/html
- ./config/php:/usr/local/etc/php
environment:
- TZ=Asia/Shanghai
database:
image: mysql:latest
container_name: mysql-service
restart: unless-stopped
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD: secret
TZ: Asia/Shanghai
volumes:
- ./data/mysql:/var/lib/mysql
- ./config/mysql:/etc/mysql/conf.d
db-admin:
image: phpmyadmin:latest
container_name: pma-service
restart: unless-stopped
ports:
- "8081:80"
environment:
PMA_HOST: database
PMA_PORT: 3306
PMA_ARBITRARY: 1
TZ: Asia/Shanghai
Deployment and Management
To launch the stack in the background, run:
docker-compose up -d
If you modify the YAML file or configurations, recreate the containers:
docker-compose down
docker-compose up -d --force-recreate
Verification
Testing MySQL
Access the database container and log in:
docker exec -it mysql-service bash
mysql -u root -p
Testing phpMyAdmin
Open your browser and navigate to http://localhost:8081. Log in using the root credentials defined in the compose file.