Environment Setup
Choose malt / Docker / manual setup based on your OS and team structure. This is a practical guide that consolidates the features, setup procedures, and operational points for each method in one place.
Method Selection
Method | Target OS | Features | Recommended Use |
---|---|---|---|
malt | macOS, WSL2, Linux | Homebrew-based, lightweight, configuration shareable, local-complete Batch service management commands |
Individual dev, team dev |
Docker | macOS, Windows, Linux | Container-based complete environment reproduction, CI/CD friendly | Team dev, CI/CD, production-like |
Manual | All OS | Use existing environment as-is, fine-grained control | Existing infrastructure, constrained environments |
Environment Setup with malt
Overview
malt is a development environment management tool based on Homebrew. It consolidates configuration and data directly under the project, achieving local completion.
Key Features
- Completely Local: All configuration and data stored within the project
- Clean Deletion: Folder deletion = environment deletion
- Dedicated Port Commands: Aliases like
mysql@3306
/redis@6379
- No Global Pollution: No impact on system MySQL/Redis etc.
- Configuration Visibility: Configuration files can be shared and reviewed within the project
- Batch Service Management:
malt start
/malt stop
can start/stop related services together
Prerequisites
- macOS or Linux (including WSL2)
- Homebrew installed
Installation
# Add Homebrew taps
brew tap shivammathur/php
brew tap shivammathur/extensions
brew tap koriym/malt
# Install malt
brew install malt
Basic Operations (Shortest Path)
malt init && malt install && malt create && malt start
source <(malt env)
Configuration Files
malt.json # malt configuration
malt/
conf/
my_3306.cnf # MySQL configuration
php.ini # PHP configuration
httpd_8080.conf # Apache configuration
nginx_80.conf # Nginx configuration
These files can be included in your project for team environment sharing.
Service Management
# Status check
malt status
# Start / stop / restart all services
malt start
malt stop
malt restart
# Specific services only
malt start mysql
malt stop nginx
Database Operations
mysql@3306 # Connect to project-specific MySQL
redis@6379 # Connect to project-specific Redis
mysql@3306 -e "CREATE DATABASE IF NOT EXISTS myapp"
Important:
mysql@3306
is project-specific connection. It’s isolated from the system’s global MySQL.
Environment Setup with Docker
Overview
Docker provides OS-independent, consistent development environments.
Docker Considerations:
- Global Command Conflicts: The system
mysql
command points to global MySQL installation - Container-specific Access: Requires specific connection methods for Docker container databases
- Port Conflict Risk: Ports like 3306 may conflict with system services
- macOS File Access: Host-container file mount performance degradation, especially noticeable during bulk file operations (builds, tests)
- Security:
MYSQL_ALLOW_EMPTY_PASSWORD
should be limited to development use only
Prerequisites
- Docker Desktop installed
- Docker Compose available
Basic docker-compose.yml
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ""
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_DATABASE: myapp
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./docker/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
command: --default-authentication-plugin=mysql_native_password
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 3
redis:
image: redis:alpine
ports:
- "6379:6379"
memcached:
image: memcached:alpine
ports:
- "11211:11211"
volumes:
mysql_data:
Usage
# Start environment
docker-compose up -d
# Check status
docker-compose ps
# Check logs
docker-compose logs mysql
# Stop environment
docker-compose stop
# Complete removal (including data)
docker-compose down -v
Database Connection
# Connect from host (port specification required)
mysql -h 127.0.0.1 -P 3306 -u root
# Connect from within container (recommended)
docker-compose exec mysql mysql -u root
Warning: If mysql
is installed on your system, running just mysql
will connect to your system’s MySQL, not the Docker container. To access the Docker database, you must either specify host/port or execute from within the container.
Manual Environment Setup
PHP
# macOS (Homebrew)
brew install php@8.4
brew install composer
# Ubuntu/Debian
sudo apt update
sudo apt install php8.4 php8.4-{cli,mysql,mbstring,xml,zip,curl}
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# CentOS/RHEL
sudo dnf install php php-{cli,mysql,mbstring,xml,zip,curl}
MySQL
# macOS (Homebrew)
brew install mysql@8.0
brew services start mysql@8.0
# Ubuntu/Debian
sudo apt install mysql-server-8.0
sudo systemctl start mysql
# CentOS/RHEL
sudo dnf install mysql-server
sudo systemctl start mysqld
Useful PHP Extensions for Development
# Xdebug (debugging)
brew install shivammathur/extensions/xdebug@8.4 # Homebrew
sudo apt install php8.4-xdebug # Ubuntu
# XHProf (profiling)
brew install shivammathur/extensions/xhprof@8.4 # Homebrew
sudo apt install php8.4-xhprof # Ubuntu
# Redis
brew install shivammathur/extensions/redis@8.4 # Homebrew
sudo apt install php8.4-redis # Ubuntu
# APCu (caching)
brew install shivammathur/extensions/apcu@8.4 # Homebrew
sudo apt install php8.4-apcu # Ubuntu
Important: Xdebug and XHProf impact performance, so avoid enabling them permanently in php.ini. Instead, enable them only when needed using the -d
option.
# Enable Xdebug only when debugging
php -dzend_extension=xdebug.so -S 127.0.0.1:8080 -t public
# Enable XHProf only when profiling
php -dzend_extension=xhprof.so script.php
# Disable extensions when running Composer (for speed)
php -dzend_extension= /usr/local/bin/composer install
BEAR.Sunday Quick Start Example
composer create-project bear/skeleton my-app
cd my-app
malt init && malt install && malt create && malt start
source <(malt env)
Project-specific Configuration
.env (Example)
# MySQL
DB_HOST=127.0.0.1
DB_PORT=3306
DB_NAME=myapp
DB_USER=root
DB_PASS=
DB_DSN=mysql:host=127.0.0.1;port=3306;dbname=myapp
# SQLite (for switching)
DB_DSN=sqlite:var/db.sqlite3
# Redis
REDIS_HOST=127.0.0.1:6379
# Memcached
MEMCACHED_HOST=127.0.0.1:11211
Migration (Phinx Example)
composer require --dev robmorgan/phinx
./vendor/bin/phinx init
./vendor/bin/phinx create MyMigration
./vendor/bin/phinx migrate
Development Server
PHP Built-in Server
# Start on port 8080
php -S 127.0.0.1:8080 -t public
# Enable Xdebug only when debugging
php -dzend_extension=xdebug.so -S 127.0.0.1:8080 -t public
malt Server
# Choose Apache / Nginx and start
malt start apache # http://127.0.0.1:8080
malt start nginx # http://127.0.0.1:80
# Check services
malt status
# Start/stop all services
malt start
malt stop
# Individual stop
malt stop apache
malt stop nginx
Troubleshooting
Port Conflicts
# macOS/Linux
lsof -i :3306
netstat -tulpn | grep :3306
# Kill the process
kill -9 <PID>
PHP Configuration Check
php --ini # Loaded configuration
php -m # Loaded modules
MySQL Connection Errors
# Connection test
mysql -h 127.0.0.1 -P 3306 -u root -p
# Linux service status
sudo systemctl status mysql
# Error logs
sudo tail -f /var/log/mysql/error.log
malt-specific Issues
# Status check
malt status
# Reset configuration
malt stop
rm -rf malt/
malt create
malt start
.gitignore for Team Development
malt/logs/
malt/data/
malt/tmp/
CI/CD (GitHub Actions Example)
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: ""
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: test_db
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: mbstring, xml, pdo_mysql, mysqli, intl, curl, zip
- name: Install dependencies
run: composer install --no-interaction --prefer-dist
- name: Run tests
run: ./vendor/bin/phpunit
Environment Selection Guidelines
Development environments prioritize transparency and direct access, while production environments prioritize reproducibility and monitoring capabilities.
- Daily Development & Learning: malt (instant
mysql@3306
, visible configuration, fast file access) - Team Development: malt (configuration sharing) or Docker (reproducibility priority)
- Production & CI/CD: Docker only (same behavior anywhere, rich monitoring tool ecosystem)
- Complex Configurations: Docker (assuming integration and scale of dependent services)
Follow your project’s tutorials and team conventions for detailed configuration and BEAR.Sunday best practices.