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

Vengala Vinay

Having 12+ Years of Experience in Software Development

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

Dockerizing and Orchestrating Legacy Magento 2 Systems on Modern Google Cloud Infrastructure

Containerizing the Magento 2 Monolith

Migrating a legacy Magento 2 installation to a containerized environment on Google Cloud Platform (GCP) requires a methodical approach, especially when dealing with complex dependencies and stateful services like databases and caches. Our goal is to break down the monolithic Magento application into manageable, independently scalable services.

We’ll start by creating a Dockerfile for the core Magento application. This involves carefully selecting a base image, installing necessary PHP extensions, configuring web server settings, and ensuring all Magento dependencies are met. For a typical Magento 2 setup, this means PHP with specific extensions (e.g., `gd`, `intl`, `soap`, `zip`, `opcache`), Composer, and a web server like Nginx or Apache.

Dockerfile for Magento Application

This Dockerfile assumes a Debian-based image and installs common Magento 2 requirements. We’ll use Nginx as the web server. Adjust PHP version and extensions as per your specific Magento installation.

# Use an official PHP image with a specific version and extensions
FROM php:8.1-fpm-buster

# Set environment variables
ENV MAGENTO_VERSION=2.4.6 \
    COMPOSER_HOME=/composer \
    COMPOSER_ALLOW_SUPERUSER=1 \
    PATH="/composer/vendor/bin:$PATH"

# Install system dependencies
RUN apt-get update && apt-get install -y \
    git \
    unzip \
    libzip-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libxslt1-dev \
    libicu-dev \
    libonig-dev \
    libxml2-dev \
    libssl-dev \
    zlib1g-dev \
    libbz2-dev \
    libcurl4-openssl-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libxslt1-dev \
    libicu-dev \
    libonig-dev \
    libxml2-dev \
    libssl-dev \
    zlib1g-dev \
    libbz2-dev \
    libcurl4-openssl-dev \
    acl \
    supervisor \
    nginx \
    vim \
    cron \
    && rm -rf /var/lib/apt/lists/*

# Install PHP extensions
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install -j$(nproc) intl \
    && docker-php-ext-install -j$(nproc) soap \
    && docker-php-ext-install -j$(nproc) zip \
    && docker-php-ext-install -j$(nproc) opcache \
    && docker-php-ext-install -j$(nproc) bcmath \
    && docker-php-ext-install -j$(nproc) sockets \
    && docker-php-ext-install -j$(nproc) xml \
    && docker-php-ext-install -j$(nproc) pdo pdo_mysql \
    && pecl install redis \
    && docker-php-ext-enable redis

# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Configure Nginx
COPY nginx/default.conf /etc/nginx/sites-available/default
RUN ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default \
    && sed -i 's/listen \[::\]\:80/listen 80/g' /etc/nginx/sites-available/default

# Configure Supervisor for PHP-FPM and Cron
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# Set working directory
WORKDIR /var/www/html

# Copy Magento application code (assuming it's in a 'src' directory locally)
# In a real-world scenario, you'd likely use a volume or a build-time copy
COPY src/ /var/www/html/

# Ensure correct permissions for Magento files
RUN chown -R www-data:www-data /var/www/html \
    && chmod -R 755 /var/www/html \
    && find /var/www/html -type f -exec chmod 644 {} \; \
    && find /var/www/html -type d -exec chmod 755 {} \; \
    && chown www-data:www-data /var/www/html/var/log \
    && chown www-data:www-data /var/www/html/var/session \
    && chown www-data:www-data /var/www/html/pub/media \
    && chown www-data:www-data /var/www/html/pub/static

# Install Magento dependencies via Composer
RUN composer install --no-dev --optimize-autoloader

# Magento specific commands (run these during deployment, not necessarily in Dockerfile)
# RUN php bin/magento setup:upgrade
# RUN php bin/magento setup:static-content:deploy en_US en_GB --theme Magento/luma
# RUN php bin/magento indexer:reindex
# RUN php bin/magento cache:flush

# Expose port 80 for Nginx
EXPOSE 80

# Start Supervisor to manage Nginx and PHP-FPM
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]

Nginx Configuration

The Nginx configuration is crucial for serving Magento efficiently. It needs to handle static files, proxy requests to PHP-FPM, and manage SSL termination (which we’ll offload to GCP Load Balancer later).

server {
    listen 80;
    server_name localhost; # Replace with your domain name

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

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

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public";
        access_log off;
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; # Adjust socket path if needed
        fastcgi_index index.php;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        # Prevent other PHP files from being executed
        try_files $uri =404;
    }

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

    # Magento specific security settings
    location ~ ^/(app/etc|bin/Magento|composer\.json|composer\.lock) {
        deny all;
    }

    # Magento static content directory
    location /static/ {
        # Ensure static content is served directly by Nginx
        expires 1y;
        add_header Cache-Control "public";
        access_log off;
        autoindex off;
        try_files $uri $uri/ /static/index.php?$args;
    }

    # Magento media directory
    location /media/ {
        expires 1y;
        add_header Cache-Control "public";
        access_log off;
        autoindex off;
        try_files $uri $uri/ /media/index.php?$args;
    }
}

Supervisor Configuration

Supervisor will manage the PHP-FPM process and the cron daemon, ensuring they restart if they crash. This is essential for a robust containerized application.

[program:php-fpm]
command=/usr/sbin/php-fpm8.1 --nodaemonize
autostart=true
autorestart=true
priority=10
stdout_logfile=/var/log/supervisor/php-fpm.log
stderr_logfile=/var/log/supervisor/php-fpm.err.log

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

[program:cron]
command=/usr/sbin/cron -f
autostart=true
autorestart=true
priority=30
stdout_logfile=/var/log/supervisor/cron.log
stderr_logfile=/var/log/supervisor/cron.err.log

Database and Cache Services

Magento 2 relies heavily on a robust database (MySQL) and a fast caching layer (Redis). These will be deployed as separate services within GCP.

Cloud SQL for MySQL

For production, we’ll use Google Cloud SQL for MySQL. This managed service handles patching, backups, and replication, significantly reducing operational overhead. When deploying, ensure your Magento container can connect to the Cloud SQL instance. This typically involves configuring firewall rules and using the Cloud SQL Auth Proxy or direct IP access (less recommended for security).

Key Configuration Points:

  • Instance Type: Choose an instance size that can handle your read/write load.
  • High Availability: Enable for production to ensure uptime.
  • Backups: Configure automated backups and retention policies.
  • Replication: Set up read replicas for scaling read operations if necessary.
  • Network: Configure private IP for secure access from your GKE cluster.
  • Database User: Create a dedicated user for Magento with appropriate privileges.

Memorystore for Redis

Redis is critical for Magento’s performance. Google Cloud Memorystore offers a managed Redis service. Similar to Cloud SQL, configure network access for your containers.

Key Configuration Points:

  • Instance Size: Select based on your cache hit rate and data volume.
  • Replication: Use read replicas if your application pattern benefits from it.
  • Network: Configure private IP for secure access.
  • Persistence: Understand Redis persistence options (RDB, AOF) and their impact on performance and data durability. For caching, durability might be less critical than for a primary data store.

Orchestration with Google Kubernetes Engine (GKE)

GKE is the ideal platform for orchestrating our containerized Magento services. It provides automated deployment, scaling, and management of containerized applications.

Kubernetes Deployment and Service Definitions

We’ll define Kubernetes Deployments for our Magento application and potentially for background worker processes (if you separate them). Services will expose these deployments internally and externally.

Magento Application Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: magento-app
  labels:
    app: magento
spec:
  replicas: 3 # Adjust based on traffic
  selector:
    matchLabels:
      app: magento
  template:
    metadata:
      labels:
        app: magento
    spec:
      containers:
      - name: magento
        image: your-gcr-repo/magento-app:latest # Replace with your image
        ports:
        - containerPort: 80
        env:
        - name: DB_HOST
          value: "your-cloudsql-instance-ip" # Or use Cloud SQL Auth Proxy sidecar
        - name: DB_NAME
          value: "magento_db"
        - name: DB_USER
          value: "magento_user"
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: magento-db-secrets
              key: password
        - name: REDIS_HOST
          value: "your-redis-instance-ip" # Or use Memorystore DNS name
        - name: REDIS_PORT
          value: "6379"
        # Add other Magento specific environment variables
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"
        livenessProbe:
          httpGet:
            path: /healthz # You might need to create a health check endpoint
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /healthz
            port: 80
          initialDelaySeconds: 15
          periodSeconds: 5
      # Consider using a sidecar for Cloud SQL Auth Proxy if not using private IP
      # - name: cloudsql-proxy
      #   image: gcr.io/cloudsql-docker/gce-proxy:1.19.1
      #   command: ["/cloud_sql_proxy", "-instances=your-project:your-region:your-instance=tcp:3306"]
      #   ports:
      #   - containerPort: 3306

Magento Application Service:

apiVersion: v1
kind: Service
metadata:
  name: magento-service
spec:
  selector:
    app: magento
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP # This will be exposed via an Ingress or LoadBalancer

Ingress Controller and Load Balancing

We’ll use a GCP Load Balancer, managed by a Kubernetes Ingress controller, to expose the Magento application to the internet. This handles SSL termination, traffic routing, and can integrate with Cloud CDN for static assets.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: magento-ingress
  annotations:
    kubernetes.io/ingress.class: "gce" # For GCP GKE
    # For SSL termination with Google-managed certificates
    networking.gke.io/managed-certificates: "magento-managed-cert"
spec:
  rules:
  - host: "your.magento.domain.com" # Replace with your domain
    http:
      paths:
      - path: "/"
        pathType: Prefix
        backend:
          service:
            name: magento-service
            port:
              number: 80
---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: magento-managed-cert
spec:
  domains:
    - "your.magento.domain.com" # Replace with your domain

Ensure you have a Google-managed SSL certificate configured for your domain. The Ingress controller will provision and manage this certificate.

Persistent Storage for Media and Static Content

Magento’s `pub/media` and `pub/static` directories need persistent storage. We’ll use Google Cloud Filestore or Persistent Disks. For `pub/media`, a shared filesystem is often preferred if you have multiple Magento instances or need to sync uploads across pods. For `pub/static`, it can be generated on deployment or mounted from a persistent volume.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: magento-media-pvc
spec:
  accessModes:
    - ReadWriteMany # For Filestore or NFS-compatible storage
  resources:
    requests:
      storage: 10Gi # Adjust size as needed
  storageClassName: "your-filestore-class" # Or a suitable CSI driver for PD
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: magento-static-pvc
spec:
  accessModes:
    - ReadWriteOnce # For Persistent Disk
  resources:
    requests:
      storage: 5Gi
  storageClassName: "your-pd-class" # e.g., standard-rwo

You would then mount these PVCs into your Magento application pods. For `pub/static`, consider generating it during the Docker build or as a Kubernetes Job on deployment to avoid mounting a read-write volume for static assets.

Deployment Workflow and CI/CD

A robust CI/CD pipeline is essential for managing deployments, updates, and rollbacks. We’ll leverage Cloud Build for automated builds and deployments to GKE.

Cloud Build Configuration

A `cloudbuild.yaml` file defines the steps for building the Docker image, pushing it to Google Container Registry (GCR), and deploying to GKE.

steps:
  # Build the Docker image
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/magento-app:$COMMIT_SHA', '.']

  # Push the Docker image to GCR
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/$PROJECT_ID/magento-app:$COMMIT_SHA']

  # Deploy to GKE
  - name: 'gcr.io/cloud-builders/kubectl'
    args:
      - 'apply'
      - '-f'
      - 'k8s/deployment.yaml' # Your deployment YAML
    env:
      - 'CLOUDSDK_COMPUTE_ZONE=your-gke-zone'
      - 'CLOUDSDK_CONTAINER_CLUSTER=your-gke-cluster'

  # Optional: Run Magento setup/upgrade commands as a Kubernetes Job
  # - name: 'gcr.io/cloud-builders/kubectl'
  #   args:
  #     - 'create'
  #     - 'job'
  #     - '--from=file=k8s/magento-setup-job.yaml'
  #   env:
  #     - 'CLOUDSDK_COMPUTE_ZONE=your-gke-zone'
  #     - 'CLOUDSDK_CONTAINER_CLUSTER=your-gke-cluster'

images:
  - 'gcr.io/$PROJECT_ID/magento-app:$COMMIT_SHA'

You’ll need to create a Kubernetes Job YAML for running `bin/magento setup:upgrade`, `setup:static-content:deploy`, and `indexer:reindex` post-deployment. This job should run only when a new image is deployed and should have access to the database and Redis.

Managing Magento Configuration and Secrets

Magento’s configuration (`app/etc/env.php`) and sensitive credentials should be managed securely. Use Kubernetes Secrets for database passwords, API keys, etc. For `app/etc/env.php`, you can either:

  • Mount it as a ConfigMap or Secret, updating it dynamically during deployment.
  • Use environment variables and have an entrypoint script in your Docker image that generates `app/etc/env.php` on startup based on these variables.

The latter approach is generally more flexible in a containerized environment.

Performance Tuning and Monitoring

Once deployed, continuous monitoring and tuning are critical for a high-performance Magento store.

GCP Monitoring and Logging

Leverage Google Cloud’s operations suite (formerly Stackdriver) for metrics, logging, and tracing. Ensure your containers are configured to send logs to stdout/stderr, which Cloud Logging can collect.

Magento Specific Tuning

Key areas to monitor and tune:

  • OpCache: Ensure it’s enabled and configured optimally in your PHP-FPM settings.
  • Redis: Monitor hit/miss ratios and memory usage.
  • Database: Analyze slow queries, optimize indexing, and ensure proper connection pooling.
  • Cron Jobs: Offload cron jobs to dedicated pods or a separate cron service to avoid impacting web requests.
  • Static Content Deployment: Automate this process during deployments to ensure fresh assets.
  • Varnish Cache: For high-traffic sites, consider integrating Varnish as a caching layer in front of Nginx. This would typically be another service in your GKE cluster or a managed service.

By containerizing your legacy Magento 2 system and orchestrating it on GCP with GKE, Cloud SQL, and Memorystore, you gain scalability, resilience, and a more manageable infrastructure for your e-commerce platform.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability
  • Scala Pekko vs. Go Goroutines: Actor Model vs. CSP for Event-Driven Reactive Systems
  • Java Loom Virtual Threads vs. Go Goroutines: Under-the-Hood Scheduler and Thread Overhead Comparison

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (584)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (806)
  • PHP (5)
  • PHP Development (21)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (19)
  • Ruby on Rails (1)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (357)

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (806)
  • Debugging & Troubleshooting (584)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala