Knowledge Base Guide

Docker for PrestaShop: Development Environment Setup

Set up Docker for PrestaShop development — multi-version testing, module workflow, database management, Xdebug debugging, and production considerations.

Why Docker for PrestaShop Development?

If you've ever tried to run PrestaShop 1.6, 1.7, 8.x, and 9.x on the same machine, you know the pain. Each version needs a different PHP version, different MySQL version, and different configuration. Installing all of that natively is a recipe for hours of troubleshooting.

Docker solves this. Each PrestaShop version runs in its own isolated container with exactly the dependencies it needs. Nothing conflicts. Nothing breaks.

  • Multi-version testing: Run PS 1.7, 8.x, and 9.x simultaneously. Test a module across all of them in one afternoon.
  • Isolation: Each container has its own PHP runtime, MySQL database, and file system.
  • Reproducibility: Your entire environment is defined in a single docker-compose.yml. Share it with your team and everyone gets an identical setup.
  • Easy cleanup: Run docker compose down -v and everything is gone. Recreate it fresh in two minutes.
We run over 25 PrestaShop containers on a single server — from PS 1.6 through PS 9.1 — for module development and testing. Docker is the only practical way to manage that. This guide shares the patterns we've refined over years of real-world usage.

Prerequisites

Installing Docker

Ubuntu/Debian: curl -fsSL https://get.docker.com | sh — then sudo usermod -aG docker $USER to run Docker without sudo.

macOS: Download Docker Desktop for Mac (Intel and Apple Silicon supported).

Windows: Install WSL2 first, then Docker Desktop with WSL2 backend enabled.

Key Docker Concepts

  • Image: A read-only template containing an OS, PHP, Apache, and PrestaShop. Official images: prestashop/prestashop on Docker Hub.
  • Container: A running instance of an image. You can run multiple containers from the same image.
  • Volume: Persistent storage that survives container restarts. Without volumes, data is lost when the container is removed.
  • Network: A virtual network allowing containers to communicate — PrestaShop needs to reach its MySQL container.

Hardware Requirements

Budget 1.5–2GB RAM per PrestaShop instance (app + database). For 2–3 versions, 8GB RAM and an SSD is comfortable. For 10+ containers, 32GB+ and fast SSDs are recommended.

Basic Setup: Single PrestaShop Container

Create a directory and add this docker-compose.yml:

version: '3.8'
services:
  prestashop:
    image: prestashop/prestashop:8.2
    container_name: my-ps-shop
    ports:
      - "8080:80"
    environment:
      - DB_SERVER=db
      - DB_USER=prestashop
      - DB_PASSWD=prestashop_password
      - DB_NAME=prestashop
      - PS_DOMAIN=localhost:8080
      - PS_FOLDER_ADMIN=admin-dev
      - PS_FOLDER_INSTALL=disabled
      - ADMIN_MAIL=admin@yourshop.com
      - ADMIN_PASSWD=admin_password_123
    volumes:
      - ps-data:/var/www/html
    depends_on:
      - db

  db:
    image: mysql:8.0
    container_name: my-ps-shop-db
    environment:
      - MYSQL_ROOT_PASSWORD=root_password
      - MYSQL_DATABASE=prestashop
      - MYSQL_USER=prestashop
      - MYSQL_PASSWORD=prestashop_password
    volumes:
      - db-data:/var/lib/mysql

volumes:
  ps-data:
  db-data:

DB_SERVER must match the service name (db). PS_DOMAIN tells PrestaShop where it's accessible. PS_FOLDER_INSTALL=disabled skips the install wizard on subsequent starts. Start with docker compose up -d and watch the first-time install with docker compose logs -f prestashop (takes 1-2 minutes).

Access your store at http://localhost:8080 and the back office at http://localhost:8080/admin-dev.

Always use named volumes for your database. Without volumes, removing a container destroys all data — products, orders, everything. Named volumes persist until you explicitly delete them.

Multi-Version Testing Setup

This is where Docker shines. Running three PrestaShop versions side by side is just a matter of defining them in your compose file with different ports:

version: '3.8'
services:
  ps178:
    image: prestashop/prestashop:1.7.8
    ports: ["8081:80"]
    environment:
      - DB_SERVER=ps178-db
      - PS_DOMAIN=localhost:8081
      # ... same pattern as above
    volumes:
      - ps178-data:/var/www/html
    networks: [ps-network]

  ps178-db:
    image: mysql:5.7
    volumes: [ps178-db-data:/var/lib/mysql]
    networks: [ps-network]

  ps82:
    image: prestashop/prestashop:8.2
    ports: ["8082:80"]
    environment:
      - DB_SERVER=ps82-db
      - PS_DOMAIN=localhost:8082
    volumes:
      - ps82-data:/var/www/html
    networks: [ps-network]

  ps82-db:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    volumes: [ps82-db-data:/var/lib/mysql]
    networks: [ps-network]

  ps9:
    image: prestashop/prestashop:9.0
    ports: ["8083:80"]
    environment:
      - DB_SERVER=ps9-db
      - PS_DOMAIN=localhost:8083
    volumes:
      - ps9-data:/var/www/html
    networks: [ps-network]

  ps9-db:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    volumes: [ps9-db-data:/var/lib/mysql]
    networks: [ps-network]

networks:
  ps-network:
    driver: bridge

Pick a consistent port scheme: 8081 for PS 1.7, 8082 for PS 8.x, 8083 for PS 9.x. For a nicer experience, use Nginx Proxy Manager to assign hostnames like ps178.dev.local instead of port numbers.

Always use separate databases. Never share a single MySQL instance across PrestaShop versions — the schema differs between versions, and migrations will corrupt data.

Module Development Workflow

Bind-mount your module directory into the container so every edit is immediately available:

volumes:
  - ps82-data:/var/www/html
  - /home/user/modules/my_module:/var/www/html/modules/my_module

To test across all versions, mount the same directory into every container. Edit one file, refresh three browser tabs — your change is live everywhere.

Symlinks vs Volume Mounts

Volume mounts (recommended): Changes are instant, works across all platforms, clean separation. Symlinks: Only works if PrestaShop files are on the host filesystem, doesn't work well with Docker volumes. For most setups, volume mounts are the right choice.

Handling the Cache

PrestaShop aggressively caches templates and configs. During development, clear cache after changes:

docker exec ps82 rm -rf /var/www/html/var/cache/*

Or disable template cache in Back Office > Advanced Parameters > Performance during active development. Re-enable it when testing is complete — cache-related bugs are real.

Database Management

Connecting to MySQL

# Interactive MySQL session
docker exec -it ps82-db mysql -u root -p'root' prestashop

# Run a single query
docker exec ps82-db mysql -u root -p'root' -e "SELECT COUNT(*) FROM ps_product;" prestashop

phpMyAdmin Container

  phpmyadmin:
    image: phpmyadmin:latest
    ports: ["9090:80"]
    environment:
      - PMA_HOSTS=ps178-db,ps82-db,ps9-db
      - PMA_USER=root
      - PMA_PASSWORD=root
    networks: [ps-network]

Import and Export

# Export
docker exec ps82-db mysqldump -u root -p'root' prestashop > backup.sql

# Import
docker exec -i ps82-db mysql -u root -p'root' prestashop < backup.sql

Persistent vs Ephemeral

Persistent (named volumes): Data survives restarts — use for main development environments. Ephemeral (no volume): Fresh install every time — useful for "does this module install cleanly on a blank store?" tests.

Email Testing with Mailpit

Mailpit catches all outgoing emails and displays them in a web UI — essential for testing checkout flows without sending real emails.

  mailpit:
    image: axllent/mailpit
    ports:
      - "8025:8025"  # Web UI
      - "1025:1025"  # SMTP
    networks: [ps-network]

In PrestaShop Back Office > Advanced Parameters > E-mail: set SMTP server to mailpit, port 1025, no encryption, no authentication. View caught emails at http://localhost:8025.

Debugging with Xdebug

Xdebug 3 Configuration

Create a custom Dockerfile:

FROM prestashop/prestashop:8.2
RUN pecl install xdebug && docker-php-ext-enable xdebug
COPY xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

The xdebug.ini:

[xdebug]
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.idekey=VSCODE

On Linux, add extra_hosts: ["host.docker.internal:host-gateway"] to your compose service — host.docker.internal doesn't exist by default on Linux.

VS Code Setup

Install the PHP Debug extension and add to .vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [{
    "name": "Listen for Xdebug (Docker)",
    "type": "php",
    "request": "launch",
    "port": 9003,
    "pathMappings": {
      "/var/www/html/modules/my_module": "${workspaceFolder}"
    }
  }]
}

The pathMappings are critical — they tell VS Code how container paths map to local paths. Without this, breakpoints won't trigger.

PHPStorm

Settings > PHP > Servers: add a server with localhost and your container's port, mapping /var/www/html to your local project. Set Xdebug port to 9003 under PHP > Debug and click "Start Listening."

Useful Docker Commands

TaskCommand
Start all containersdocker compose up -d
Stop all containersdocker compose down
Stop and delete all datadocker compose down -v
View logsdocker compose logs -f
Clear PS cachedocker exec CONTAINER rm -rf /var/www/html/var/cache/*
MySQL CLIdocker exec -it CONTAINER-db mysql -u root -p'PASS' prestashop
Export databasedocker exec CONTAINER-db mysqldump -u root -p'PASS' prestashop > backup.sql
Import databasedocker exec -i CONTAINER-db mysql -u root -p'PASS' prestashop < backup.sql
Shell into containerdocker exec -it CONTAINER bash
Check resource usagedocker stats --no-stream
Rebuild after Dockerfile changesdocker compose up -d --build
Run PrestaShop consoledocker exec CONTAINER php bin/console cache:clear --env=prod
Run Composer in moduledocker exec -w /var/www/html/modules/my_module CONTAINER composer install

Production Considerations

For most PrestaShop shops, Docker is a development tool. Production stores run better on traditional hosting because:

  • A single-server LAMP stack is simpler to maintain and monitor
  • Native file I/O is faster than Docker volumes (PrestaShop loads thousands of PHP files per request)
  • Most PrestaShop hosts provide cPanel/Plesk, not Docker

Docker in production makes sense when: you have a large dev team with CI/CD pipelines, you need auto-scaling during sales events, you manage 10+ stores, or you need zero-downtime deployments (build new image, swap in, roll back if broken).

Docker Compose vs Kubernetes: Compose handles up to 20–30 containers on one server and is simple to manage. Kubernetes adds auto-scaling, self-healing, and multi-node orchestration but requires significant infrastructure. For most PrestaShop deployments, Compose on a powerful server is sufficient.

Common Problems and Solutions

File Permission Issues

Symptom: "Permission denied" errors, can't upload modules or save images.

Cause: Apache runs as www-data (UID 33) inside the container, but mounted host files may be owned by your user (UID 1000).

docker exec my-ps-shop chown -R www-data:www-data /var/www/html/var
docker exec my-ps-shop chown -R www-data:www-data /var/www/html/img
docker exec my-ps-shop chown -R www-data:www-data /var/www/html/modules

Container Can't Connect to Database

  • DB_SERVER must match the MySQL service name in your compose file exactly
  • MySQL may not be ready — add a healthcheck and use depends_on: condition: service_healthy
  • Both containers must be on the same Docker network
  • MySQL 8.0 uses caching_sha2_password by default — add command: --default-authentication-plugin=mysql_native_password to the MySQL service

Slow File I/O on macOS

Symptom: Pages take 10–30 seconds to load with bind mounts.

Solutions:

  • VirtioFS: Switch from gRPC FUSE to VirtioFS in Docker Desktop settings — biggest single improvement
  • Mount less: Only mount your module directory, use named volumes for PrestaShop core
  • Mutagen: Fast two-way file sync that eliminates the macOS penalty

SSL in Development

Payment modules and social login often require HTTPS. Options:

  • Nginx Proxy Manager: Handles SSL termination for all containers. Cleanest approach.
  • mkcert: Generate locally-trusted certificates with mkcert localhost and mount them into Apache.
  • Traefik: Auto-discovers containers and provisions certificates.

Container Runs Out of Memory

MySQL 8.0 is memory-hungry by default. Limit it:

command: >
  --innodb-buffer-pool-size=128M
  --max-connections=50

On Docker Desktop (macOS/Windows), increase the global memory limit in Settings > Resources to at least 6GB for 3+ containers. Stop containers you're not actively using: docker compose stop ps178.

Auto-Install Loops

If PrestaShop reinstalls on every restart, ensure your /var/www/html volume persists and PS_FOLDER_INSTALL=disabled is set in your environment.

Mixed Content After Port Change

Update the domain in the database when you change port mappings:

docker exec ps82-db mysql -u root -p'root' -e "
  UPDATE ps_configuration SET value='localhost:8082'
    WHERE name IN ('PS_SHOP_DOMAIN','PS_SHOP_DOMAIN_SSL');
  UPDATE ps_shop_url SET domain='localhost:8082', domain_ssl='localhost:8082';
" prestashop

Summary

Docker transforms PrestaShop development from a fragile, single-version experience into a reproducible, multi-version workflow. The initial setup takes an afternoon. After that, you can spin up any PrestaShop version in minutes, test modules across all supported versions simultaneously, and share your exact environment with your team.

Start with the basic single-container setup. Once comfortable, add more versions, phpMyAdmin, Mailpit, and Xdebug. The compose files in this guide are production-tested patterns from our own infrastructure. Copy them, adapt them, and build on them.

The PrestaShop Docker repository on GitHub is an excellent resource for staying current with official image updates and best practices.

More guides available

Browse our knowledge base for more practical PrestaShop tutorials, or reach out if you need help.

Loading...
Back to top