mulertech / docker-dev
The MulerTech Docker-dev package
Requires
- php: >=8.0
- ext-posix: *
README
The MulerTech Docker-dev package provides complete Docker-based development environments for web projects with a modular, composable architecture (Apache, MySQL/PostgreSQL, Symfony, Redis, MailPit, Ollama...) and includes integrated testing capabilities.
Description
This package simplifies web development by providing pre-configured Docker environments for different project types. It uses a modular system where each service (database, cache, mail...) is an independent module that can be freely combined. It includes integrated testing tools (PHPUnit, PHPStan, PHP-CS-Fixer) that work seamlessly within the containerized environment.
Prerequisites
For PHP Projects
- Docker
- PHP
- Composer
For Static HTML/CSS/JS Projects
- Docker only
Installation
For PHP Projects (Symfony, Apache-MySQL, Apache-Simple)
-
Include the package as a dev dependency with Composer :
composer require --dev mulertech/docker-dev
For Static HTML/CSS/JS Projects (Apache-HTML)
Since static projects don't use PHP or Composer, the modular system (mtdocker) is not available. A standalone template is provided with two setup options:
Option 1: Quick Setup with Install Script (Recommended)
# Download and run the installation script in the project directory curl -sSL https://raw.githubusercontent.com/mulertech/docker-dev/main/install-apache-html.sh | bash
This script will:
- Download all necessary Docker files (
Dockerfile,compose.yml,.env) - Auto-configure environment variables (USER_ID, GROUP_ID, unique ports)
- Create a sample
index.htmlfile (if none exists) - Provide ready-to-use Docker environment
Option 2: Manual Setup
- Download the standalone template files from
templates/apache-html/ - Copy the 3 files to your project root:
Dockerfilecompose.yml.env.example(rename to.envand adjust USER_ID, GROUP_ID, APACHE_PORT)
- Run the Docker environment:
docker compose up -d
Usage
Development Environment (Modular System)
🚀 Zero-Configuration Mode: No setup required. Just run any command and the environment is automatically created based on your composer.json:
./vendor/bin/mtdocker up -d
./vendor/bin/mtdocker test
./vendor/bin/mtdocker phpstan
The system detects your project type (Symfony, database, AI/RAG packages...) and activates the appropriate modules automatically.
Manual initialization: If you want to control which modules are activated, use init with a comma-separated list:
# Auto-detect modules ./vendor/bin/mtdocker init # Or choose specific modules ./vendor/bin/mtdocker init frankenphp,symfony,postgres,redis,mailpit,adminer ./vendor/bin/mtdocker init frankenphp,postgres,adminer ./vendor/bin/mtdocker init frankenphp # View active modules ./vendor/bin/mtdocker modules
Managing Your Development Environment
# Start your development environment ./vendor/bin/mtdocker up -d # Stop your environment ./vendor/bin/mtdocker down # Check environment status ./vendor/bin/mtdocker ps
Testing and Code Quality Tools
Integrated testing tools work seamlessly within your development environment:
Running the tests
To run the tests, use the following command:
./vendor/bin/mtdocker test [arguments...]
You can pass any additional arguments to PHPUnit:
# Run specific test class ./vendor/bin/mtdocker test --filter=MyTestClass # Run with verbose output ./vendor/bin/mtdocker test --verbose # Run specific test method ./vendor/bin/mtdocker test --filter=MyTestClass::testMyMethod
To run the tests with code coverage, use the following command:
./vendor/bin/mtdocker test-coverage
The code coverage report will be generated in the ./.phpunit.cache/coverage folder.
To get a plain text coverage report (useful for CI or AI agents):
./vendor/bin/mtdocker test-coverage-text
The coverage report will be displayed directly in the terminal as plain text without colors.
These commands will:
- Check if the Docker container is running.
- If the container is not running, it will be started.
- Run the PHPUnit tests in the container with all provided arguments.
- Stop the container if it was not running before the tests were executed.
Running phpstan
To run phpstan, use the following command:
./vendor/bin/mtdocker phpstan [arguments...]
You can pass any additional arguments to phpstan:
# Run with custom memory limit ./vendor/bin/mtdocker phpstan analyse --memory-limit=2G # Generate baseline ./vendor/bin/mtdocker phpstan analyse --generate-baseline
This command will:
- Check if the Docker container is running.
- If the container is not running, it will be started.
- Run phpstan in the container with all provided arguments.
- Stop the container if it was not running before phpstan was executed.
Running php-cs-fixer
To run php-cs-fixer, use the following command:
./vendor/bin/mtdocker cs-fixer [arguments...]
You can pass any additional arguments to php-cs-fixer:
# Fix specific files ./vendor/bin/mtdocker cs-fixer fix src/MyClass.php # Check only (dry-run) ./vendor/bin/mtdocker cs-fixer fix --dry-run
This command will:
- Check if the Docker container is running.
- If the container is not running, it will be started.
- Run php-cs-fixer in the container with all provided arguments.
- Stop the container if it was not running before php-cs-fixer was executed.
Composer Commands
You can run Composer commands directly in the Docker container:
# Install dependencies ./vendor/bin/mtdocker composer install # Update dependencies ./vendor/bin/mtdocker composer update # Require a new package ./vendor/bin/mtdocker composer require vendor/package # Remove a package ./vendor/bin/mtdocker composer remove vendor/package # Any other Composer command ./vendor/bin/mtdocker composer [command] [arguments...]
This command will:
- Check if the Docker container is running.
- If the container is not running, it will be started.
- Run
composer [command]in the container with all provided arguments. - Stop the container if it was not running before the command was executed.
Symfony Console Commands (Symfony projects only)
For Symfony projects, you can run console commands directly in the container:
# Create a new entity ./vendor/bin/mtdocker symfony make:entity MyEntity # Run database migrations ./vendor/bin/mtdocker symfony doctrine:migrations:migrate # Clear cache ./vendor/bin/mtdocker symfony cache:clear # Any other Symfony console command ./vendor/bin/mtdocker symfony [command] [arguments...]
This command will:
- Check that your project is a Symfony project.
- Check if the Docker container is running.
- If the container is not running, it will be started.
- Run
php bin/console [command]in the container with all provided arguments. - Stop the container if it was not running before the command was executed.
Running php-cs-fixer, phpunit and phpstan
To run php-cs-fixer, phpunit and phpstan, use the following command:
./vendor/bin/mtdocker all
This command will:
- Check if the Docker container is running.
- If the container is not running, it will be started.
- Run php-cs-fixer, phpunit and phpstan in the container.
- Stop the container if it was not running before the checks were executed.
Advanced Configuration
Getting the project name
To get the project name used for Docker Compose (useful for PHPStorm configuration), use the following command:
./vendor/bin/mtdocker name
This command will output the project name that should be used in the COMPOSE_PROJECT_NAME environment variable when configuring PHPStorm.
Getting the application link
To get the clickable link to access your application, use the following command:
./vendor/bin/mtdocker link
This command will display a clickable link to your application (e.g., http://localhost:8080).
Available Modules
Each module is an independent Docker Compose file that can be freely combined with others.
| Module | Services | Description |
|---|---|---|
frankenphp |
FrankenPHP (Caddy) | Default. Modern PHP app server built on Caddy. Defines the shared network. |
apache-php |
Apache + PHP | Alternative base web server with Apache + mod_php. Defines the shared network. |
apache-html |
Apache | Static web server without PHP (httpd:2.4-alpine). Defines the shared network. |
symfony |
(overlay) | Adds Symfony configuration: php.ini, Caddyfile/apache.conf, mailer secret. |
postgres |
PostgreSQL 16 | PostgreSQL database with volume persistence and SQL init scripts. |
mysql |
MySQL 8 | MySQL database with volume persistence, UTF-8 charset, and SQL init scripts. |
pgvector |
PostgreSQL 17 + pgvector | PostgreSQL with vector embeddings extension for AI/RAG projects. |
redis |
Redis 7 | Redis cache server (Alpine). |
mailpit |
MailPit | Local mail server with SMTP capture and web interface. |
adminer |
Adminer | Database web administration interface with auto-login and dark theme. |
ollama |
Ollama | Local LLM server for AI/RAG projects. |
Smart auto-detection
When running ./vendor/bin/mtdocker init without arguments, modules are automatically selected based on your composer.json:
| Detection criteria | Modules activated |
|---|---|
symfony/framework-bundle, symfony/symfony, or symfony/kernel detected + AI packages (pgvector, openai, anthropic, langchain, chromadb, yethee/tiktoken) |
frankenphp, symfony, pgvector, ollama, redis, mailpit, adminer |
symfony/framework-bundle, symfony/symfony, or symfony/kernel detected |
frankenphp, symfony, postgres, redis, mailpit, adminer |
ext-pdo requirement detected |
frankenphp, postgres, adminer |
| PHP version detected (any PHP project) | frankenphp |
| No PHP detected | apache-html |
For Symfony projects, the AI/RAG packages in composer.json determine whether pgvector + ollama or standard postgres is activated. To use Apache instead of FrankenPHP, pass the modules explicitly (e.g., mtdocker init apache-php,symfony,postgres,redis,mailpit,adminer).
Module combinations examples
# Symfony standard stack (FrankenPHP) ./vendor/bin/mtdocker init frankenphp,symfony,postgres,redis,mailpit,adminer # Symfony AI/RAG stack ./vendor/bin/mtdocker init frankenphp,symfony,pgvector,ollama,redis,mailpit,adminer # PHP + PostgreSQL + Adminer ./vendor/bin/mtdocker init frankenphp,postgres,adminer # Minimal PHP only ./vendor/bin/mtdocker init frankenphp # Symfony with Apache (instead of FrankenPHP) ./vendor/bin/mtdocker init apache-php,symfony,postgres,redis,mailpit,adminer # PHP + MySQL with Apache ./vendor/bin/mtdocker init apache-php,mysql,adminer # Static HTML site ./vendor/bin/mtdocker init apache-html
Initialization process
- Creates a
.mtdocker/directory in your project root - Copies necessary build files (Dockerfile, configs, secrets, SQL scripts)
- Creates a
.envfile with auto-detected system settings (USER_ID, GROUP_ID, PHP version, absolute paths) - Saves the active module list in
.mtdocker/modules.json - Generates deterministic ports based on project name to avoid conflicts
- Automatically adds
.mtdocker/to.gitignore(best practice) - For Symfony projects: Automatically configures Doctrine settings for PostgreSQL into
doctrine.yaml - For Symfony projects: Automatically configures Mailer to use MailPit into
mailer.yaml - Provides a complete development environment ready to use
Migration from legacy templates
If your project was initialized with a previous version (using monolithic templates with compose.yml), running any mtdocker command will detect the legacy configuration and propose a re-initialization with the new module system.
Database Initialization
For configurations with database modules (mysql, postgres, or pgvector), you can easily initialize your database with custom SQL files:
# 1. Copy your SQL files to the sql directory cp my-backup.sql .mtdocker/sql/02-my-data.sql cp schema.sql .mtdocker/sql/01-schema.sql # 2. Restart the environment to apply changes ./vendor/bin/mtdocker down ./vendor/bin/mtdocker up -d
File execution order:
01-init-user.sql(system - for MySQL creates user with network permissions, for PostgreSQL provides additional setup if needed)- Your SQL files in alphabetical order (e.g.,
01-schema.sql,02-data.sql) - Supports
.sql,.sql.gz, and.shfiles
IDE Integration
PHPStorm Configuration
Configure PHPStorm to work with your Docker development environment:
PHP Interpreter Setup:
- Open PHPStorm settings →
PHP - Click
...next toCLI Interpreterfield - Add new interpreter:
From Docker, Vagrant, VM, WSL, Remote... - Configure Docker Compose interpreter:
- Server:
Docker(create new if needed) - Configuration files: select the compose module files from
vendor/mulertech/docker-dev/templates/modules/matching your active modules (see./vendor/bin/mtdocker modules) - Service:
apache - Environment variables:
COMPOSE_PROJECT_NAME=<project name>(get with./vendor/bin/mtdocker name)
- Server:
PHPUnit Integration:
- Go to
PHP→Test Frameworks - Add
PHPUnit by Remote Interpreter - Select your Docker interpreter
- Path to script:
/var/www/html/vendor/autoload.php - Default configuration file:
/var/www/html/phpunit.dist.xml(needed for Symfony projects)
Architecture
Core Classes
Application: Main CLI dispatcher handling all commandsComposer: Project analysis (PHP version detection, database requirements, Symfony detection, AI/RAG package detection)Docker: Module initialization, Docker Compose lifecycle, port generation, container namingModuleResolver: Module auto-detection logic based oncomposer.jsonanalysis, file resolution for each module combinationSymfony: Symfony-specific configurations (Doctrine, Mailer)
Command System
CommandInterface: Contract for all commandsBaseCommand: Abstract base with Docker lifecycle management- Specific Commands:
PhpunitCommand,PhpStanCommand,CsFixerCommand,ComposerCommand,SymfonyCommand CommandRegistry: Command routing and management
Module System
templates/modules/: 10 independent Docker Compose files, one per module. They stay in the package and are referenced via absolute paths.templates/shared/: Build context files (Dockerfiles, configs, SQL scripts, secrets) copied into.mtdocker/during initialization.- Docker Compose merge: Modules are combined via
docker compose -f ... -f .... The base module (apache-phporapache-html) is always loaded first, then overlays are applied in order.
Key Features
- Composable Modules: Mix and match services freely instead of choosing from fixed templates
- Custom Arguments: All commands support additional arguments (e.g.,
./vendor/bin/mtdocker phpstan --generate-baseline) - Auto-initialization: Environment setup happens automatically when needed
- Smart Detection: Project type detection for optimal module selection
- Permission Handling: Proper UID/GID management for file permissions
- Legacy Migration: Automatic detection and migration from old template-based configurations