Docker Compose Configuration

version: '3.8'
services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./www:/var/www/html
    depends_on:
      - php

  php:
    image: php:8.2-fpm
    volumes:
      - ./www:/var/www/html
    environment:
      - DB_HOST=mysql
      - DB_NAME=${DB_NAME:-appdb}
      - DB_USER=${DB_USER:-appuser}
      - DB_PASS=${DB_PASS:-changeme}

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASS:-rootpass}
      MYSQL_DATABASE: ${DB_NAME:-appdb}
      MYSQL_USER: ${DB_USER:-appuser}
      MYSQL_PASSWORD: ${DB_PASS:-changeme}
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 10s
      retries: 5

volumes:
  db_data:

.env File

# .env (create this file in the same directory)
DB_NAME=mywebsite
DB_USER=webapp
DB_PASS=your_secure_password_here
MYSQL_ROOT_PASS=root_secure_password

Usage

# Start all services
docker-compose up -d

# View logs
docker-compose logs -f

# Stop services
docker-compose down

# Reset database (warning: deletes all data)
docker-compose down -v && docker-compose up -d

What This Stack Includes

Service Image Purpose
Nginx nginx:alpine Web server and reverse proxy
PHP php:8.2-fpm PHP application server
MySQL mysql:8.0 Relational database

Security Notes

  1. Change default passwords in .env before deploying
  2. MySQL port 3306 is not exposed externally by default (only accessible within Docker network)
  3. Use the provided .env template to manage secrets securely
  4. For production, add a restart: always policy to each service