Skip to content
intermediate Phase 94 · Docker

Docker Setup

Docker setup - Docker Compose for Magento, PHP/Nginx/MySQL/Redis/OpenSearch

1h
0 problems
Topic Progress 0%

Docker Compose Architecture

Docker Compose Structure

  ┌─────────────────────────────────────────┐
  │            Docker Compose               │
  ├─────────────────────────────────────────┤
  │  Nginx │ PHP-FPM │ MySQL │ Redis │ OS  │
  │  :80   │ :9000   │ :3306 │ :6379 │:9200│
  └─────────────────────────────────────────┘

docker-compose.yml

version: '3.8'

services:
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./src:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php-fpm
    networks:
      - magento-network

  php-fpm:
    build:
      context: ./docker/php
      dockerfile: Dockerfile
    volumes:
      - ./src:/var/www/html
    depends_on:
      - mysql
      - redis
      - opensearch
    networks:
      - magento-network

  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: magento
      MYSQL_USER: magento
      MYSQL_PASSWORD: magento
    volumes:
      - mysql-data:/var/lib/mysql
      - ./docker/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - magento-network

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    networks:
      - magento-network

  opensearch:
    image: opensearchproject/opensearch:2.5.0
    ports:
      - "9200:9200"
      - "9600:9600"
    environment:
      - discovery.type=single-node
      - plugins.security.disabled=true
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
    volumes:
      - opensearch-data:/usr/share/opensearch/data
    networks:
      - magento-network

networks:
  magento-network:
    driver: bridge

volumes:
  mysql-data:
  redis-data:
  opensearch-data:

Directory Structure

  docker/
    ├── nginx/
    │   └── default.conf
    ├── php/
    │   ├── Dockerfile
    │   └── php.ini
    ├── mysql/
    │   └── init.sql
    └── docker-compose.yml

PHP Configuration

PHP Dockerfile

FROM php:8.2-fpm-alpine

# Install system dependencies
RUN apk add --no-cache \
    git \
    curl \
    libpng-dev \
    libjpeg-turbo-dev \
    freetype-dev \
    oniguruma-dev \
    libxml2-dev \
    zip \
    unzip \
    icu-dev \
    $PHPIZE_DEPS

# Install PHP extensions
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install \
    pdo_mysql \
    mbstring \
    exif \
    pcntl \
    bcmath \
    gd \
    xml \
    intl \
    opcache

# Install Redis extension
RUN pecl install redis && docker-php-ext-enable redis

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# PHP configuration
COPY php.ini /usr/local/etc/php/conf.d/custom.ini

# Working directory
WORKDIR /var/www/html

# Set permissions
RUN chown -R www-data:www-data /var/www/html

EXPOSE 9000
CMD ["php-fpm"]

php.ini Configuration

; Memory and execution
memory_limit = 2G
max_execution_time = 1800
max_input_time = 1800

; Error handling
display_errors = On
error_reporting = E_ALL
log_errors = On
error_log = /var/log/php-errors.log

; File uploads
file_uploads = On
upload_max_filesize = 100M
post_max_size = 100M

; OPcache
opcache.enable = 1
opcache.memory_consumption = 512
opcache.interned_strings_buffer = 64
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 0

; Session
session.gc_maxlifetime = 1440

Nginx Configuration

server {
    listen 80;
    server_name localhost;
    root /var/www/html/pub;
    index index.php index.html;

    # Magento rewrite rules
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location /static/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }

    location /media/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }

    location ~ \.php$ {
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Deny access to sensitive files
    location ~ /\.(?!well-known/) {
        deny all;
    }
}

Service Configuration

MySQL Configuration

-- docker/mysql/init.sql
CREATE DATABASE IF NOT EXISTS magento;
CREATE USER IF NOT EXISTS 'magento'@'%' IDENTIFIED BY 'magento';
GRANT ALL PRIVILEGES ON magento.* TO 'magento'@'%';
FLUSH PRIVILEGES;

-- Performance settings
SET GLOBAL innodb_buffer_pool_size = 1073741824;  -- 1GB
SET GLOBAL innodb_log_file_size = 268435456;       -- 256MB
SET GLOBAL max_connections = 500;

Redis Configuration

# docker/redis/redis.conf
maxmemory 256mb
maxmemory-policy allkeys-lru
appendonly yes
save 900 1
save 300 10
save 60 10000

OpenSearch Configuration

# docker/opensearch/opensearch.yml
cluster.name: magento-cluster
network.host: 0.0.0.0
discovery.type: single-node
plugins.security.disabled: true

Environment Variables

# .env
COMPOSE_PROJECT_NAME=magento2
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=magento
MYSQL_USER=magento
MYSQL_PASSWORD=magento
REDIS_HOST=redis
REDIS_PORT=6379
OPENSEARCH_HOST=opensearch
OPENSEARCH_PORT=9200

Build and Run

Build Commands

# Build images
docker-compose build

# Start services
docker-compose up -d

# View logs
docker-compose logs -f

# Stop services
docker-compose down

# Remove volumes
docker-compose down -v

Magento Installation

# Enter PHP container
docker-compose exec php-fpm bash

# Install Magento
bin/magento setup:install \
    --db-host=mysql \
    --db-name=magento \
    --db-user=magento \
    --db-password=magento \
    --admin-firstname=admin \
    --admin-lastname=admin \
    --admin-email=admin@example.com \
    --admin-user=admin \
    --admin-password=admin123 \
    --backend-frontname=admin \
    --search-engine=opensearch \
    --opensearch-host=opensearch \
    --opensearch-port=9200 \
    --opensearch-index-prefix=magento2 \
    --cache-backend=redis \
    --cache-backend-redis-server=redis \
    --cache-backend-redis-db=0 \
    --session-save=redis \
    --session-save-redis-host=redis \
    --session-save-redis-db=1

Development Mode

# Enable developer mode
docker-compose exec php-fpm bin/magento deploy:mode:set developer

# Compile DI
docker-compose exec php-fpm bin/magento setup:di:compile

# Deploy static content
docker-compose exec php-fpm bin/magento setup:static-content:deploy -f

# Clear cache
docker-compose exec php-fpm bin/magento cache:clean

Health Checks

# docker-compose.yml health checks
services:
  mysql:
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

Quiz

1. What is the purpose of docker-compose.yml?

Question 1 options

2. Why use PHP-FPM with Nginx?

Question 2 options

3. What is the benefit of Docker volumes?

Question 3 options

Flashcards

Question

What is docker-compose?

Answer

Tool for defining multi-container Docker applications

Question

Why PHP-FPM + Nginx?

Answer

Nginx serves static, PHP-FPM processes PHP

Question

What are Docker volumes?

Answer

Persistent data storage outside containers

Question

What is a Docker network?

Answer

Bridge connecting containers for communication

Revision Notes

Key Takeaways

  • 1. Docker Compose defines all services in one file
  • 2. PHP-FPM processes PHP, Nginx serves HTTP
  • 3. MySQL, Redis, OpenSearch run as separate containers
  • 4. Volumes persist data across container restarts
  • 5. Networks enable inter-container communication

Interview Tips

  • Explain the Docker Compose architecture
  • Discuss PHP-FPM vs mod_php
  • Describe volume persistence strategy
  • Talk about container networking

Cheat Sheet

Docker Compose:
  Services → nginx, php-fpm, mysql, redis, opensearch
  Networks → bridge for communication
  Volumes → persistent data

Commands:
  docker-compose build → build images
  docker-compose up -d → start services
  docker-compose logs -f → view logs
  docker-compose down → stop services

Magento Install:
  bin/magento setup:install --db-host=mysql ...