• 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 Shopify Systems on Modern OVH Infrastructure

Dockerizing and Orchestrating Legacy Shopify Systems on Modern OVH Infrastructure

Understanding the Challenge: Legacy Shopify & OVH Infrastructure

Migrating or modernizing legacy Shopify systems, often characterized by custom themes, extensive app integrations, and sometimes monolithic PHP architectures, onto a modern cloud infrastructure like OVH presents unique challenges. These systems were typically designed for a shared hosting environment with specific PHP versions, module dependencies, and filesystem structures. OVH’s Public Cloud, while offering robust IaaS and PaaS capabilities, requires a deliberate approach to containerization and orchestration to replicate or improve upon the original environment’s stability and performance.

The primary goal is to encapsulate the Shopify application, its dependencies (PHP, web server, database), and any custom code into portable, reproducible containers. This allows for consistent deployment across development, staging, and production environments on OVH, leveraging services like Kubernetes (via OVH’s managed Kubernetes offering) or Docker Swarm for orchestration.

Phase 1: Containerizing the Shopify Application Stack

We’ll start by building Docker images for the core components: the PHP application itself and its web server (typically Nginx or Apache). For a legacy Shopify setup, this often means a specific PHP version (e.g., PHP 7.x) with particular extensions enabled, and a database (MySQL/MariaDB).

Dockerfile for the Shopify PHP Application

This Dockerfile assumes a typical PHP application structure. We’ll use an official PHP base image and install necessary extensions. For Shopify, `gd`, `imagick`, `mysqli`, `pdo_mysql`, `curl`, and `zip` are commonly required.

# Use a specific PHP version compatible with your legacy Shopify setup
FROM php:7.4-fpm

# Set working directory
WORKDIR /var/www/html

# Install system dependencies
RUN apt-get update && apt-get install -y \
    libzip-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libwebp-dev \
    libssl-dev \
    libicu-dev \
    libonig-dev \
    unzip \
    git \
    && rm -rf /var/lib/apt/lists/*

# Install PHP extensions
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install -j$(nproc) zip \
    && docker-php-ext-install -j$(nproc) pdo_mysql \
    && docker-php-ext-install -j$(nproc) mysqli \
    && docker-php-ext-install -j$(nproc) curl \
    && docker-php-ext-install -j$(nproc) intl \
    && docker-php-ext-install -j$(nproc) opcache

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

# Copy Shopify application code
# IMPORTANT: This assumes your Shopify code is in a 'shop' directory relative to the Dockerfile.
# You might need to adjust this based on your project structure.
COPY ./shop/ /var/www/html/

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

# Set appropriate permissions for web server
RUN chown -R www-data:www-data /var/www/html/storage \
    && chown -R www-data:www-data /var/www/html/bootstrap/cache

# Expose port 9000 for PHP-FPM
EXPOSE 9000

# Default command to run PHP-FPM
CMD ["php-fpm"]

Dockerfile for the Nginx Web Server

This Nginx configuration will serve the PHP application, forwarding requests to the PHP-FPM service.

FROM nginx:stable-alpine

# Remove default Nginx configuration
RUN rm -rf /etc/nginx/conf.d/*

# Copy custom Nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Copy static assets if any (e.g., for themes)
# COPY ./public/ /usr/share/nginx/html/

# Expose port 80
EXPOSE 80

# Start Nginx in foreground
CMD ["nginx", "-g", "daemon off;"]

Nginx Configuration (nginx.conf)

This configuration is crucial for routing requests to the PHP-FPM container and handling static files efficiently.

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

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

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

    location ~ \.php$ {
        # Use the service name of your PHP-FPM container (e.g., 'php-fpm')
        # and the port it's listening on (9000 by default)
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    location ~ /\.ht {
        deny all;
    }

    # Cache static assets for a long time
    location ~* \.(css|js|jpg|jpeg|gif|png|ico|svg|webp|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public";
    }
}

Database Container (Docker Compose)

For simplicity in development and testing, we can use Docker Compose to define and run the multi-container Shopify application. For production, OVH’s managed database services (like Managed Databases for MySQL/PostgreSQL) are recommended.

version: '3.8'

services:
  php-fpm:
    build:
      context: .
      dockerfile: Dockerfile.php # Assuming your PHP Dockerfile is named Dockerfile.php
    container_name: shopify_php_fpm
    volumes:
      - ./shop:/var/www/html # Mount your Shopify code for development
    depends_on:
      - mysql
    networks:
      - shopify_network

  nginx:
    build:
      context: .
      dockerfile: Dockerfile.nginx # Assuming your Nginx Dockerfile is named Dockerfile.nginx
    container_name: shopify_nginx
    ports:
      - "8080:80" # Map host port 8080 to container port 80
    volumes:
      - ./shop:/var/www/html # Mount your Shopify code for development
    depends_on:
      - php-fpm
    networks:
      - shopify_network

  mysql:
    image: mysql:5.7 # Use a version compatible with your legacy system
    container_name: shopify_mysql
    environment:
      MYSQL_ROOT_PASSWORD: your_root_password
      MYSQL_DATABASE: shopify_db
      MYSQL_USER: shopify_user
      MYSQL_PASSWORD: shopify_password
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - shopify_network

volumes:
  mysql_data:

networks:
  shopify_network:
    driver: bridge

To build and run this stack locally:

# Navigate to the directory containing your Dockerfiles and docker-compose.yml
cd /path/to/your/shopify/project

# Build the images
docker-compose build

# Start the containers
docker-compose up -d

# Access your Shopify store at http://localhost:8080

Phase 2: Orchestration with OVH Managed Kubernetes (K8s)

For production deployments on OVH, Docker Compose is insufficient. We’ll leverage OVH’s Managed Kubernetes service. This involves defining Kubernetes resources (Deployments, Services, Ingress, PersistentVolumes) to manage the containerized application.

Kubernetes Deployment for PHP-FPM

This deployment will manage the PHP-FPM pods. We’ll use a persistent volume for the application code if it’s not baked into the image, or if updates are frequent.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: shopify-php-fpm
  labels:
    app: shopify
    tier: backend
spec:
  replicas: 3 # Adjust based on expected load
  selector:
    matchLabels:
      app: shopify
      tier: backend
  template:
    metadata:
      labels:
        app: shopify
        tier: backend
    spec:
      containers:
      - name: php-fpm
        image: your-docker-registry/shopify-php-fpm:latest # Replace with your image path
        ports:
        - containerPort: 9000
        volumeMounts:
        - name: app-storage
          mountPath: /var/www/html
      volumes:
      - name: app-storage
        persistentVolumeClaim:
          claimName: shopify-app-pvc # Defined below

Kubernetes Deployment for Nginx

This deployment manages the Nginx pods, which will serve traffic and proxy to PHP-FPM.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: shopify-nginx
  labels:
    app: shopify
    tier: frontend
spec:
  replicas: 3 # Adjust based on expected load
  selector:
    matchLabels:
      app: shopify
      tier: frontend
  template:
    metadata:
      labels:
        app: shopify
        tier: frontend
    spec:
      containers:
      - name: nginx
        image: your-docker-registry/shopify-nginx:latest # Replace with your image path
        ports:
        - containerPort: 80
        volumeMounts:
        - name: app-storage
          mountPath: /var/www/html # If Nginx needs access to app files
        - name: nginx-config-volume
          mountPath: /etc/nginx/conf.d/default.conf
          subPath: default.conf # Mount specific file
      volumes:
      - name: app-storage
        persistentVolumeClaim:
          claimName: shopify-app-pvc # Same PVC as PHP-FPM
      - name: nginx-config-volume
        configMap:
          name: nginx-configmap # Defined below

Kubernetes Service for PHP-FPM

This Service provides a stable internal IP address and DNS name for Nginx to connect to PHP-FPM.

apiVersion: v1
kind: Service
metadata:
  name: shopify-php-fpm-svc
  labels:
    app: shopify
spec:
  selector:
    app: shopify
    tier: backend
  ports:
  - protocol: TCP
    port: 9000
    targetPort: 9000
  clusterIP: None # Headless service for direct pod access if needed, or a ClusterIP for stable endpoint

Kubernetes Service for Nginx

This Service exposes the Nginx pods to the cluster, typically via an Ingress controller.

apiVersion: v1
kind: Service
metadata:
  name: shopify-nginx-svc
  labels:
    app: shopify
spec:
  selector:
    app: shopify
    tier: frontend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP # Ingress will handle external access

Kubernetes Ingress for External Access

An Ingress resource is used to manage external access to the services in a cluster, typically HTTP. OVH’s Managed Kubernetes often comes with an Ingress controller (like Nginx Ingress Controller or Traefik) pre-installed or easily deployable.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shopify-ingress
  annotations:
    # Annotations specific to your Ingress controller (e.g., Nginx Ingress)
    nginx.ingress.kubernetes.io/rewrite-target: /
    # Add SSL/TLS configuration here if using OVH Load Balancer with SSL termination
spec:
  rules:
  - host: your-shopify-domain.com # Replace with your actual domain
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: shopify-nginx-svc
            port:
              number: 80

Kubernetes Persistent Volume Claim (PVC) and Storage

For persistent storage of application code, logs, or uploads, we need PVCs. OVH Public Cloud offers various storage options (e.g., Block Storage, Object Storage) that can be integrated with Kubernetes.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shopify-app-pvc
spec:
  accessModes:
    - ReadWriteOnce # Or ReadWriteMany if your storage driver supports it and needed
  resources:
    requests:
      storage: 10Gi # Adjust size as needed
  storageClassName: ovh-block-storage # Or your specific OVH storage class name

You’ll need to ensure the `storageClassName` matches a provisioner configured in your OVH K8s cluster that maps to OVH’s storage solutions.

Database Management on OVH

Instead of running MySQL in a container within Kubernetes for production, it’s highly recommended to use OVH’s Managed Databases for MySQL or PostgreSQL. This offloads database administration, scaling, and high availability to OVH.

Your application containers (PHP-FPM) will then connect to the managed database endpoint provided by OVH. Ensure your application’s database credentials and connection strings are managed securely, perhaps using Kubernetes Secrets.

Phase 3: CI/CD Pipeline and Monitoring

A robust CI/CD pipeline is essential for automating the build, test, and deployment process. Tools like GitLab CI, GitHub Actions, or Jenkins can be integrated with your OVH Kubernetes cluster.

Example GitLab CI Configuration (.gitlab-ci.yml)

This is a simplified example. You’ll need to configure your Docker registry (e.g., GitLab Container Registry, Docker Hub, OVH’s registry) and Kubernetes context.

variables:
  DOCKER_REGISTRY: registry.gitlab.com/your-group/your-project
  KUBE_CONTEXT: your-ovh-kube-context # Configured in GitLab CI/CD settings

stages:
  - build
  - deploy

build-php-fpm:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $DOCKER_REGISTRY/shopify-php-fpm:$CI_COMMIT_SHA -f Dockerfile.php .
    - docker push $DOCKER_REGISTRY/shopify-php-fpm:$CI_COMMIT_SHA
  only:
    - main

build-nginx:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $DOCKER_REGISTRY/shopify-nginx:$CI_COMMIT_SHA -f Dockerfile.nginx .
    - docker push $DOCKER_REGISTRY/shopify-nginx:$CI_COMMIT_SHA
  only:
    - main

deploy-to-k8s:
  stage: deploy
  image: google/cloud-sdk:latest # Or an image with kubectl and helm
  script:
    - echo "Deploying to Kubernetes..."
    # Use kubectl apply with updated image tags
    - sed "s|your-docker-registry/shopify-php-fpm:latest|$DOCKER_REGISTRY/shopify-php-fpm:$CI_COMMIT_SHA|g" kubernetes/deployment-php-fpm.yaml | kubectl apply -f - --context=$KUBE_CONTEXT
    - sed "s|your-docker-registry/shopify-nginx:latest|$DOCKER_REGISTRY/shopify-nginx:$CI_COMMIT_SHA|g" kubernetes/deployment-nginx.yaml | kubectl apply -f - --context=$KUBE_CONTEXT
    # Apply other resources like Services, Ingress, PVCs if they change
    - kubectl apply -f kubernetes/service-php-fpm.yaml --context=$KUBE_CONTEXT
    - kubectl apply -f kubernetes/service-nginx.yaml --context=$KUBE_CONTEXT
    - kubectl apply -f kubernetes/ingress.yaml --context=$KUBE_CONTEXT
    - kubectl apply -f kubernetes/pvc.yaml --context=$KUBE_CONTEXT
  environment:
    name: production
    url: http://your-shopify-domain.com
  only:
    - main

Monitoring and Logging

Integrate monitoring tools like Prometheus and Grafana, and a logging solution (e.g., ELK stack, Loki) within your Kubernetes cluster. OVH’s Managed Kubernetes often provides integrations or allows for easy deployment of these tools.

Key metrics to monitor include:

  • Pod CPU and Memory usage
  • Nginx request rates, error rates (5xx, 4xx)
  • PHP-FPM process counts and queue lengths
  • Database connection counts and query latency
  • Application-specific metrics (e.g., order processing time)

Conclusion and Next Steps

Dockerizing and orchestrating legacy Shopify systems on OVH infrastructure is a significant undertaking. It requires a deep understanding of both the legacy application’s dependencies and the capabilities of modern containerization and cloud platforms. By following a phased approach—containerization, orchestration with Kubernetes, and robust CI/CD and monitoring—you can achieve a more scalable, resilient, and manageable Shopify environment on OVH Public Cloud.

Future considerations might include exploring service meshes (like Istio) for advanced traffic management and security, implementing autoscaling for your deployments based on load, and optimizing database performance with OVH’s managed services.

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

  • Step-by-Step: Diagnosing thread pools deadlock during concurrent ActiveRecord transaction processing on Linode Servers
  • Securing Your E-commerce APIs: Preventing SQL Injection (SQLi) in customized checkout queries in WooCommerce Implementations
  • Disaster Recovery 101: Architecting Auto-Failovers for MySQL and Ruby Deployments on Linode
  • High-Throughput Caching Strategies: Scaling MySQL for Perl Application APIs
  • Disaster Recovery 101: Architecting Auto-Failovers for DynamoDB and Laravel Deployments on DigitalOcean

Copyright © 2026 · Vinay Vengala