• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 9+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Dockerizing and Orchestrating Legacy Magento 2 Systems on Modern AWS Infrastructure

Dockerizing and Orchestrating Legacy Magento 2 Systems on Modern AWS Infrastructure

Containerizing the Magento 2 Monolith: A Phased Approach

Migrating a legacy Magento 2 installation to a containerized environment on AWS requires a deliberate, phased strategy. The primary challenge with older Magento 2 deployments is their inherent monolithic nature, often tightly coupled with specific OS configurations, PHP versions, and complex dependency chains. Our goal is to decouple these components into manageable, reproducible Docker containers, paving the way for modern orchestration and scaling.

We’ll start by dissecting the core Magento 2 application and its essential services (web server, PHP-FPM, database, Redis, Elasticsearch, etc.) into individual Docker images. This process involves identifying the exact versions of all dependencies and crafting Dockerfiles that precisely replicate the existing production environment, albeit in a containerized form.

Dockerfile Essentials for Magento 2 Components

Let’s begin with the web server and PHP-FPM layer. For a typical Magento 2 setup, Nginx is a common choice. We’ll create a Dockerfile that installs Nginx, PHP-FPM, and all necessary PHP extensions required by Magento.

Nginx and PHP-FPM Dockerfile

This Dockerfile assumes a Debian-based image (e.g., `debian:buster-slim`) and installs PHP 7.4, a common version for many Magento 2 installations. Adjust the PHP version and OS base image as per your legacy system’s requirements.

# Dockerfile for Magento 2 Web/PHP-FPM
FROM debian:buster-slim

LABEL maintainer="Antigravity <[email protected]>"

ENV DEBIAN_FRONTEND=noninteractive

# Install Nginx, PHP 7.4, and common extensions
RUN apt-get update && apt-get install -y \
    nginx \
    php7.4-fpm \
    php7.4-cli \
    php7.4-mysql \
    php7.4-gd \
    php7.4-curl \
    php7.4-mbstring \
    php7.4-xml \
    php7.4-zip \
    php7.4-intl \
    php7.4-bcmath \
    php7.4-opcache \
    supervisor \
    vim \
    git \
    unzip \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

# Configure PHP-FPM
COPY --chown=www-data:www-data php-fpm.conf /etc/php/7.4/fpm/php-fpm.conf
COPY --chown=www-data:www-data www.conf /etc/php/7.4/fpm/pool.d/www.conf

# Configure Nginx
COPY --chown=www-data:www-data nginx.conf /etc/nginx/nginx.conf
COPY --chown=www-data:www-data magento.conf /etc/nginx/sites-available/default
RUN ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

# Configure Supervisor for Nginx and PHP-FPM
COPY --chown=root:root supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# Magento specific configurations
RUN mkdir -p /var/www/html/pub/static/frontend /var/www/html/pub/static/adminhtml /var/www/html/var/view_preprocessed /var/www/html/var/cache /var/www/html/var/page_cache
RUN chown -R www-data:www-data /var/www/html

# Expose port 80
EXPOSE 80

# Start services using Supervisor
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]

Next, we need the configuration files for PHP-FPM, Nginx, and Supervisor.

PHP-FPM Configuration (www.conf)

; /etc/php/7.4/fpm/pool.d/www.conf
[www]
user = www-data
group = www-data
listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 50
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.start_servers = 2
pm.idle_timeout = 10s
request_terminate_timeout = 60s
request_slowlog_timeout = 30s
slowlog = /var/log/php7.4-fpm.log
catch_workers_output = yes

Nginx Configuration (magento.conf)

# /etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _; # Replace with your domain if needed

    root /var/www/html/pub;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Deny access to hidden files
    location ~ /\. {
        deny all;
    }

    # Magento static content and media
    location /static/ {
        alias /var/www/html/pub/static/;
        expires 1d;
        add_header Cache-Control "public";
    }

    location /media/ {
        alias /var/www/html/pub/media/;
        expires 1d;
        add_header Cache-Control "public";
    }

    # Prevent access to sensitive files
    location ~* (LICENSE.txt|/app/|/bin/|/composer.json|/composer.lock|/vendor/|/var/log/|/var/session/) {
        deny all;
    }
}

Supervisor Configuration (supervisord.conf)

[supervisord]
nodaemon=true
user=root

[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
autostart=true
autorestart=true
stderr_logfile=/var/log/supervisor/nginx_err.log
stdout_logfile=/var/log/supervisor/nginx_out.log

[program:php-fpm]
command=/usr/sbin/php7.4-fpm --nodaemonize
autostart=true
autorestart=true
stderr_logfile=/var/log/supervisor/php-fpm_err.log
stdout_logfile=/var/log/supervisor/php-fpm_out.log

With these Dockerfiles and configuration files in place, you can build the image:

docker build -t my-magento-web:latest .

Database and Cache Containerization

Magento 2 relies heavily on a robust database (typically MySQL/MariaDB) and a fast caching layer (Redis). These services should be containerized separately for better management and scalability.

MySQL Dockerfile (Example)

For the database, we can leverage official images and configure them appropriately. This example uses a MySQL 5.7 image, common for older Magento 2 versions.

# Dockerfile for Magento 2 MySQL
FROM mysql:5.7

LABEL maintainer="Antigravity <[email protected]>"

ENV MYSQL_ROOT_PASSWORD=changeme
ENV MYSQL_DATABASE=magento_db
ENV MYSQL_USER=magento_user
ENV MYSQL_PASSWORD=magento_password

COPY --chown=mysql:mysql my.cnf /etc/mysql/conf.d/my.cnf

# Magento requires specific character set and collation
RUN sed -i 's/^character-set-server.*/character-set-server = utf8mb4/' /etc/mysql/conf.d/my.cnf && \
    sed -i 's/^collation-server.*/collation-server = utf8mb4_unicode_ci/' /etc/mysql/conf.d/my.cnf

# Initialize database if it doesn't exist
# This is a simplified approach; for production, consider more robust initialization strategies
# or using a managed database service.
VOLUME ["/var/lib/mysql"]

EXPOSE 3306

And the MySQL configuration file:

MySQL Configuration (my.cnf)

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
innodb_flush_log_at_trx_commit = 2
innodb_buffer_pool_size = 128M
max_allowed_packet = 256M
wait_timeout = 600
interactive_timeout = 600
sql_mode = "NO_ENGINE_SUBSTITUTION"

Redis Dockerfile (Example)

For Redis, the official image is straightforward.

# Dockerfile for Magento 2 Redis
FROM redis:6.2

LABEL maintainer="Antigravity <[email protected]>"

# Magento requires Redis to be configured for persistence and specific settings
# For production, consider a more robust Redis configuration.
# This example uses default settings, which might not be optimal.
EXPOSE 6379

Orchestration with Docker Compose

Docker Compose is an excellent tool for defining and running multi-container Docker applications. It allows us to define our Magento 2 stack (web, PHP-FPM, MySQL, Redis, etc.) in a single YAML file.

docker-compose.yml for Development/Staging

version: '3.8'

services:
  db:
    build:
      context: ./db
      dockerfile: Dockerfile
    container_name: magento_db
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-changeme}
      MYSQL_DATABASE: ${MYSQL_DATABASE:-magento_db}
      MYSQL_USER: ${MYSQL_USER:-magento_user}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD:-magento_password}
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - magento_network

  redis:
    image: redis:6.2
    container_name: magento_redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    networks:
      - magento_network

  web:
    build:
      context: ./web
      dockerfile: Dockerfile
    container_name: magento_web
    ports:
      - "80:80"
      - "443:443" # If SSL is configured
    volumes:
      - ./magento2:/var/www/html # Mount your Magento code here
      - magento_static_content:/var/www/html/pub/static
      - magento_var_cache:/var/www/html/var/cache
      - magento_var_page_cache:/var/www/html/var/page_cache
    depends_on:
      - db
      - redis
    networks:
      - magento_network

volumes:
  db_data:
  redis_data:
  magento_static_content:
  magento_var_cache:
  magento_var_page_cache:

networks:
  magento_network:
    driver: bridge

To use this, you would place your Magento 2 codebase in a directory named magento2 at the same level as your docker-compose.yml file, and the Dockerfiles for db and web in their respective subdirectories. You can then run:

docker-compose up -d

AWS Infrastructure Integration: ECS and ECR

For production deployments on AWS, Docker Compose is not sufficient. We’ll leverage Amazon Elastic Container Service (ECS) for orchestration and Amazon Elastic Container Registry (ECR) for image storage.

ECR Repository Setup

First, create ECR repositories for each of your container images (e.g., `magento-web`, `magento-db`, `magento-redis`).

aws ecr create-repository --repository-name magento-web
aws ecr create-repository --repository-name magento-db
aws ecr create-repository --repository-name magento-redis

Then, authenticate your Docker client to ECR and push your built images:

aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com

# Tag and push web image
docker tag my-magento-web:latest YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/magento-web:latest
docker push YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/magento-web:latest

# Repeat for other images (assuming you built them locally or are using official ones)

ECS Task Definitions

Task definitions describe how your application should run on ECS. This involves specifying container images, CPU/memory requirements, environment variables, and port mappings.

Example Task Definition (JSON)

{
    "family": "magento-task",
    "networkMode": "awsvpc",
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "1024",
    "memory": "2048",
    "executionRoleArn": "arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/ecsTaskExecutionRole",
    "containerDefinitions": [
        {
            "name": "magento-web",
            "image": "YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/magento-web:latest",
            "portMappings": [
                {
                    "containerPort": 80,
                    "hostPort": 80,
                    "protocol": "tcp"
                }
            ],
            "environment": [
                {"name": "DB_HOST", "value": "db.magento.local"},
                {"name": "DB_NAME", "value": "magento_db"},
                {"name": "DB_USER", "value": "magento_user"},
                {"name": "DB_PASSWORD", "value": "YOUR_DB_PASSWORD"}
            ],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/ecs/magento-web",
                    "awslogs-region": "us-east-1",
                    "awslogs-stream-prefix": "ecs"
                }
            },
            "essential": true
        },
        {
            "name": "magento-db",
            "image": "mysql:5.7",
            "environment": [
                {"name": "MYSQL_ROOT_PASSWORD", "value": "YOUR_ROOT_PASSWORD"},
                {"name": "MYSQL_DATABASE", "value": "magento_db"},
                {"name": "MYSQL_USER", "value": "magento_user"},
                {"name": "MYSQL_PASSWORD", "value": "YOUR_DB_PASSWORD"}
            ],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/ecs/magento-db",
                    "awslogs-region": "us-east-1",
                    "awslogs-stream-prefix": "ecs"
                }
            },
            "essential": true
        },
        {
            "name": "magento-redis",
            "image": "redis:6.2",
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/ecs/magento-redis",
                    "awslogs-region": "us-east-1",
                    "awslogs-stream-prefix": "ecs"
                }
            },
            "essential": true
        }
    ]
}

Note: For production, it’s highly recommended to use AWS RDS for your database and ElastiCache for Redis instead of running them in ECS containers. This offloads management and provides better reliability and scalability. If using RDS/ElastiCache, remove the `db` and `redis` container definitions from your task and update the `DB_HOST` environment variable in the `magento-web` container to point to your RDS endpoint.

ECS Service and Cluster Setup

You’ll need an ECS Cluster and a Service to manage your tasks. The service will define how many instances of your task definition should run and how they should be networked. For production, consider using AWS Fargate for serverless container management.

When setting up the ECS Service, you’ll configure networking (VPC, subnets, security groups) and potentially load balancing with an Application Load Balancer (ALB) to distribute traffic across your Magento web containers.

Database Migrations and Magento Setup

Once your containers are running, you’ll need to perform the initial Magento 2 setup and database migrations. This can be done by exec-ing into the web container or by creating a separate initialization container.

Running Magento Setup Commands

# Get a shell into your running web container
docker exec -it magento_web bash

# Inside the container:
# Ensure you are in the Magento root directory (/var/www/html)
cd /var/www/html

# Set correct permissions (if not handled by Dockerfile)
chown -R www-data:www-data .

# Install Magento (if this is a fresh deployment or you're re-initializing)
# This command requires database credentials to be set as environment variables
# or in app/etc/env.php
php bin/magento setup:install \
    --base-url="http://localhost/" \
    --db-host="db" \
    --db-name="magento_db" \
    --db-user="magento_user" \
    --db-password="magento_password" \
    --admin-firstname="Admin" \
    --admin-lastname="User" \
    --admin-email="[email protected]" \
    --admin-user="admin" \
    --admin-password="YOUR_ADMIN_PASSWORD" \
    --language="en" \
    --timezone="UTC" \
    --currency="USD" \
    --use-cache-string=true \
    --session-save=redis \
    --session-save-redis-host="redis" \
    --session-save-redis-port="6379"

# Compile dependency injection
php bin/magento setup:di:compile

# Deploy static content
php bin/magento setup:static-content:deploy -f en_US en_GB # Add your required locales

# Reindex data
php bin/magento indexer:reindex

# Clear cache
php bin/magento cache:clean
php bin/magento cache:flush

For production, consider automating these steps using an ECS Task Definition for a one-off initialization task or by baking them into your Docker image build process if the code is static. For database migrations, use a dedicated migration container that runs before the web application starts.

Advanced Considerations for Production

Migrating a legacy Magento 2 system to AWS containers is a significant undertaking. Here are some advanced points to consider for a robust production environment:

  • Managed Services: Utilize AWS RDS for MySQL, ElastiCache for Redis, and OpenSearch Service for Elasticsearch. This significantly reduces operational overhead.
  • CI/CD Pipeline: Implement a CI/CD pipeline (e.g., AWS CodePipeline, Jenkins, GitLab CI) to automate building, testing, and deploying container images.
  • Secrets Management: Use AWS Secrets Manager or AWS Systems Manager Parameter Store to securely manage database credentials, API keys, and other sensitive information, injecting them as environment variables into your ECS tasks.
  • Monitoring and Logging: Configure comprehensive monitoring with Amazon CloudWatch, Prometheus, or Datadog. Ensure centralized logging from all containers.
  • Scalability: Configure ECS Service Auto Scaling based on metrics like CPU utilization, memory utilization, or request count from your ALB.
  • Persistent Storage: For Magento’s `var/media` and `var/log` directories, consider using Amazon EFS or S3 with a suitable connector for shared, persistent storage across multiple web container instances.
  • CDN Integration: Integrate with Amazon CloudFront for serving static assets and improving global performance.
  • Security Groups and Network ACLs: Implement strict network security policies to control traffic flow between containers and external services.

By following this structured approach, you can successfully containerize and orchestrate your legacy Magento 2 system on modern AWS infrastructure, unlocking the benefits of cloud-native deployments.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Disaster Recovery 101: Architecting Auto-Failovers for Redis and PHP Deployments on OVH
  • How We Audited a High-Traffic WooCommerce Enterprise Stack on Google Cloud and Mitigated Race conditions during high-concurrency payment processing
  • Disaster Recovery 101: Architecting Auto-Failovers for Elasticsearch and Magento 2 Deployments on DigitalOcean
  • An Auditor’s Checklist for Securing WordPress Backends on OVH
  • Step-by-Step: Diagnosing Perl script high CPU throttling due to unoptimized regular expressions on AWS Servers

Copyright © 2026 · Vinay Vengala