DDEV is a convenient tool but not the only way. Your own Docker Compose stack gives full control: exactly the service versions you need, custom network, CI/CD integration, deployable to any server without changes. I show a minimal but complete stack for Magento 2 with PHP 8.4, MariaDB 10.6, Redis, OpenSearch and nginx.
Project structure
magento-docker/
docker-compose.yml
docker-compose.override.yml
.env
docker/
nginx/default.conf
php/Dockerfile
php/php.ini
mysql/my.cnf
docker-compose.yml
services:
nginx:
image: nginx:1.27-alpine
ports: ["80:80", "443:443"]
volumes:
- .:/var/www/html:cached
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on: [php]
networks: [magento]
php:
build: {context: ./docker/php, args: {PHP_VERSION: "8.4"}}
volumes:
- .:/var/www/html:cached
environment:
XDEBUG_MODE: "${XDEBUG_MODE:-off}"
extra_hosts: ["host-gateway:host-gateway"]
networks: [magento]
db:
image: mariadb:10.6
environment:
MARIADB_ROOT_PASSWORD: root
MARIADB_DATABASE: magento
MARIADB_USER: magento
MARIADB_PASSWORD: magento
volumes: [db_data:/var/lib/mysql]
networks: [magento]
redis:
image: redis:7.2-alpine
command: redis-server --maxmemory 512mb --maxmemory-policy volatile-lru
networks: [magento]
opensearch:
image: opensearchproject/opensearch:2.13.0
environment:
discovery.type: single-node
DISABLE_SECURITY_PLUGIN: "true"
OPENSEARCH_JAVA_OPTS: "-Xms512m -Xmx512m"
volumes: [opensearch_data:/usr/share/opensearch/data]
networks: [magento]
mailpit:
image: axllent/mailpit:latest
ports: ["8025:8025", "1025:1025"]
networks: [magento]
volumes: {db_data: {}, opensearch_data: {}}
networks: {magento: {driver: bridge}}
PHP Dockerfile
FROM php:8.4-fpm-alpine
RUN apk add --no-cache freetype-dev libjpeg-turbo-dev libpng-dev \
libzip-dev oniguruma-dev libxml2-dev icu-dev git unzip
RUN docker-php-ext-configure gd --with-freetype --with-jpeg && \
docker-php-ext-install -j$(nproc) \
bcmath gd intl mbstring opcache pdo_mysql soap sockets xml zip
RUN pecl install redis xdebug && docker-php-ext-enable redis
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
Daily commands
docker compose up -d docker compose exec php sh docker compose exec php bin/magento cache:flush docker compose exec php composer require vendor/package XDEBUG_MODE=debug docker compose up -d php docker compose logs -f php
Summary
Your own Docker Compose gives full control at the cost of configuration. DDEV does the same but automatically – the choice depends on needs. A custom stack is worth having when: you use non-standard service versions, integrate with CI/CD (same docker-compose.yml on dev and pipeline), or need specific network configuration. DDEV wins for quick starts and simple projects.
