648 lines
14 KiB
Markdown
648 lines
14 KiB
Markdown
# FrankenPHP Docker Environment
|
|
|
|
A modern, lightweight Docker environment for PHP applications using FrankenPHP, featuring HTTP/2, HTTP/3, automatic HTTPS, and built-in Node.js support for multiple PHP frameworks.
|
|
|
|
## Features
|
|
|
|
- 🚀 **FrankenPHP Server**: Modern PHP server with HTTP/2, HTTP/3, and automatic HTTPS via Caddy
|
|
- 🗄️ **MariaDB Database**: Persistent relational database for your applications
|
|
- 📦 **Node.js Integration**: Full Node.js runtime (v20.x) for frontend tooling and build processes
|
|
- 🎯 **Multi-Framework Support**: Optimized build targets for Laravel, Symfony, Magento2, WordPress, and OpenCart
|
|
- 📝 **PHP 8.0 - 8.5**: Support for multiple PHP versions with configurable extensions
|
|
- 🔧 **Flexible Configuration**: Local, proxy, and production modes
|
|
- 🔒 **Automatic HTTPS**: Let's Encrypt SSL certificates in production
|
|
- 🎨 **Extension-Rich**: Pre-installed essential PHP extensions (PDO/MySQL, Redis, APCu, and more)
|
|
- ⚡ **Alpine-Based**: Lightweight, fast, and efficient container images
|
|
- 🔄 **Hot Reload**: Automatic code reloading during development
|
|
|
|
## Requirements
|
|
|
|
- Docker Desktop (or Docker Engine + Docker Compose)
|
|
- 2GB+ RAM available
|
|
- Terminal/Command-line access
|
|
|
|
## Quick Start
|
|
|
|
### 1. Clone the Repository
|
|
|
|
```bash
|
|
git clone <repository-url>
|
|
cd franken
|
|
```
|
|
|
|
### 2. Configure Environment
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
Edit the `.env` file with your preferred settings:
|
|
|
|
```bash
|
|
# Core Configuration
|
|
PHP_VERSION=8.4 # PHP version (8.0-8.5)
|
|
FRAMEWORK=opencart # Framework: laravel, symfony, magento2, wordpress, opencart
|
|
MODE=proxy # Mode: local, prod, proxy
|
|
PORT=80 # Local port
|
|
PROJECT_NAME=opencart # Project name
|
|
|
|
# Database Configuration
|
|
MYSQL_ROOT_PASSWORD=root
|
|
MYSQL_DATABASE=database
|
|
MYSQL_USER_DATABASE=app
|
|
MYSQL_PASSWORD_DATABASE=secret
|
|
```
|
|
|
|
### 3. Start Services
|
|
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
### 4. Access Your Application
|
|
|
|
- **Local/Proxy Mode**: http://localhost:{PORT}
|
|
- Default: http://localhost:80
|
|
|
|
## Configuration Guide
|
|
|
|
### Environment Variables
|
|
|
|
| Variable | Description | Options |
|
|
|----------|-------------|---------|
|
|
| `PHP_VERSION` | PHP version | `8.0`, `8.1`, `8.2`, `8.3`, `8.4`, `8.5` |
|
|
| `FRAMEWORK` | Target framework | `laravel`, `symfony`, `magento2`, `wordpress`, `opencart` |
|
|
| `MODE` | Run mode | `local` (dev), `proxy` (behind reverse proxy), `prod` (production) |
|
|
| `PORT` | HTTP port | Any available port (default: `80`) |
|
|
| `PROJECT_NAME` | Project identifier | Any alphanumeric name |
|
|
| `MYSQL_ROOT_PASSWORD` | Database root password | Your secure password |
|
|
| `MYSQL_DATABASE` | Database name | `database` |
|
|
| `MYSQL_USER_DATABASE` | Database user | `app` |
|
|
| `MYSQL_PASSWORD_DATABASE` | Database user password | Your secure password |
|
|
| `SERVER_NAME` | Domain (prod mode) | Your domain (e.g., `example.com`) |
|
|
|
|
### Framework-Specific Setup
|
|
|
|
#### Laravel
|
|
|
|
1. Update `.env`:
|
|
```
|
|
FRAMEWORK=laravel
|
|
```
|
|
|
|
2. Uncomment Laravel volume in `docker-compose.yml`:
|
|
```yaml
|
|
volumes:
|
|
- ./www:/app # Instead of /app/public
|
|
```
|
|
|
|
3. Start services:
|
|
```bash
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
#### Symfony
|
|
|
|
1. Update `.env`:
|
|
```
|
|
FRAMEWORK=symfony
|
|
```
|
|
|
|
2. Uncomment Symfony volume in `docker-compose.yml`:
|
|
```yaml
|
|
volumes:
|
|
- ./www:/app # Instead of /app/public
|
|
```
|
|
|
|
3. Build and start:
|
|
```bash
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
#### WordPress
|
|
|
|
1. Update `.env`:
|
|
```
|
|
FRAMEWORK=wordpress
|
|
```
|
|
|
|
2. The default volume mount `/app/public` works for WordPress
|
|
|
|
3. Start services:
|
|
```bash
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
#### OpenCart
|
|
|
|
1. Update `.env`:
|
|
```
|
|
FRAMEWORK=opencart
|
|
```
|
|
|
|
2. Default configuration uses `/app/public`
|
|
|
|
3. Start services:
|
|
```bash
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
#### Magento 2
|
|
|
|
1. Update `.env`:
|
|
```
|
|
FRAMEWORK=magento2
|
|
```
|
|
|
|
2. Start services:
|
|
```bash
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
### Modes Explained
|
|
|
|
- **local**: Development mode with internal TLS disabled, suitable for local development
|
|
- **proxy**: Designed for use behind a reverse proxy or load balancer
|
|
- **prod**: Production mode with HTTPS enabled, automatic SSL certificates, and optimized PHP settings
|
|
|
|
### Production Deployment
|
|
|
|
1. Update `.env`:
|
|
```
|
|
MODE=prod
|
|
SERVER_NAME=yourdomain.com
|
|
PHP_VERSION=8.4
|
|
```
|
|
|
|
2. Enable HTTPS in `docker-compose.yml`:
|
|
```yaml
|
|
ports:
|
|
- "443:443" # HTTPS
|
|
- "443:443/udp" # HTTP/3
|
|
```
|
|
|
|
3. Start services:
|
|
```bash
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
4. FrankenPHP automatically obtains SSL certificates from Let's Encrypt
|
|
|
|
## How to Run
|
|
|
|
### Start Services
|
|
|
|
```bash
|
|
# Start in background
|
|
docker-compose up -d
|
|
|
|
# Start with output
|
|
docker-compose up
|
|
|
|
# Start and rebuild images
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
### Stop Services
|
|
|
|
```bash
|
|
docker-compose down
|
|
```
|
|
|
|
### View Logs
|
|
|
|
```bash
|
|
# View all logs
|
|
docker-compose logs -f
|
|
|
|
# View specific service logs
|
|
docker-compose logs -f php
|
|
docker-compose logs -f db
|
|
```
|
|
|
|
### Access Container Shell
|
|
|
|
```bash
|
|
# PHP container
|
|
docker-compose exec php sh
|
|
|
|
# Database container
|
|
docker-compose exec db mysql -u app -p
|
|
```
|
|
|
|
## Development Workflow
|
|
|
|
### Running Commands Inside Container
|
|
|
|
```bash
|
|
# Composer commands
|
|
docker-compose exec php composer install
|
|
docker-compose exec php composer require package/name
|
|
|
|
# NPM/Node commands
|
|
docker-compose exec php npm install
|
|
docker-compose exec php npm run dev
|
|
docker-compose exec php npm run build
|
|
|
|
# PHP CLI
|
|
docker-compose exec php php -v
|
|
docker-compose exec php php artisan migrate # Laravel
|
|
docker-compose exec php bin/console doctrine:schema # Symfony
|
|
|
|
# Database management
|
|
docker-compose exec db mysql -u app -p database
|
|
```
|
|
|
|
### File Structure
|
|
|
|
```
|
|
franken/
|
|
├── docker-compose.yml # Docker services configuration
|
|
├── Dockerfile # Multi-stage PHP container build
|
|
├── .env # Environment configuration
|
|
├── php.ini # Custom PHP settings
|
|
├── www/ # Web application root
|
|
│ └── index.php # Entry point
|
|
└── README.md # This file
|
|
```
|
|
|
|
### PHP Configuration
|
|
|
|
Edit `php.ini` to customize PHP settings:
|
|
|
|
```ini
|
|
; Example configurations
|
|
display_errors = On
|
|
memory_limit = 512M
|
|
upload_max_filesize = 100M
|
|
post_max_size = 100M
|
|
```
|
|
|
|
Changes take effect after container restart:
|
|
|
|
```bash
|
|
docker-compose restart php
|
|
```
|
|
|
|
## Redis Caching
|
|
|
|
### Setup
|
|
|
|
Redis is included and pre-configured in `docker-compose.yml`. It runs in a separate container with:
|
|
|
|
- **Image**: `redis:alpine` (lightweight, fast)
|
|
- **Persistent Storage**: Redis data is stored in `redis_data` volume
|
|
- **Health Check**: Built-in health check to verify Redis is running
|
|
- **Networking**: Connected to `app-network` for internal PHP communication
|
|
|
|
### Redis Service Configuration
|
|
|
|
Redis is automatically started with `docker-compose up`. To verify it's running:
|
|
|
|
```bash
|
|
# Check Redis container status
|
|
docker-compose ps redis
|
|
|
|
# Connect to Redis CLI
|
|
docker-compose exec redis redis-cli
|
|
|
|
# Test Redis connection from PHP container
|
|
docker-compose exec php php -r "
|
|
\$redis = new Redis();
|
|
\$redis->connect('redis', 6379);
|
|
echo 'Redis connected: ' . (\$redis->ping() ? 'OK' : 'FAILED');
|
|
\$redis->close();
|
|
"
|
|
```
|
|
|
|
### Using Redis in Your Application
|
|
|
|
#### Laravel Example
|
|
|
|
Update your `.env`:
|
|
|
|
```env
|
|
CACHE_DRIVER=redis
|
|
SESSION_DRIVER=redis
|
|
REDIS_HOST=redis
|
|
REDIS_PORT=6379
|
|
REDIS_PASSWORD=null
|
|
```
|
|
|
|
Install/configure in your Laravel app:
|
|
|
|
```bash
|
|
# Inside container
|
|
docker-compose exec php composer require predis/predis
|
|
|
|
# Or use PHP's native Redis extension (recommended)
|
|
```
|
|
|
|
#### PHP Native Example
|
|
|
|
```php
|
|
<?php
|
|
$redis = new Redis();
|
|
$redis->connect('redis', 6379);
|
|
|
|
// Set a cache value
|
|
$redis->set('user:1:name', 'John Doe', 3600); // 1 hour TTL
|
|
|
|
// Get a value
|
|
$name = $redis->get('user:1:name');
|
|
|
|
// Check if key exists
|
|
if ($redis->exists('user:1:name')) {
|
|
echo "Key exists";
|
|
}
|
|
|
|
// Delete a key
|
|
$redis->del('user:1:name');
|
|
|
|
// Increment counter
|
|
$redis->incr('page_views');
|
|
|
|
$redis->close();
|
|
?>
|
|
```
|
|
|
|
#### Symfony Example
|
|
|
|
Configure in `config/packages/cache.yaml`:
|
|
|
|
```yaml
|
|
framework:
|
|
cache:
|
|
default_redis_provider: 'redis://redis:6379'
|
|
pools:
|
|
cache.app:
|
|
adapter: cache.adapter.redis
|
|
provider: 'redis://redis:6379'
|
|
```
|
|
|
|
#### WordPress Example
|
|
|
|
Use a Redis plugin like "Redis Object Cache" and configure:
|
|
|
|
```php
|
|
define('WP_REDIS_HOST', 'redis');
|
|
define('WP_REDIS_PORT', 6379);
|
|
```
|
|
|
|
### Common Redis Operations
|
|
|
|
```bash
|
|
# Connect to Redis CLI
|
|
docker-compose exec redis redis-cli
|
|
|
|
# Inside redis-cli commands:
|
|
PING # Check connection
|
|
SET mykey "Hello" # Set a key
|
|
GET mykey # Get a value
|
|
DEL mykey # Delete a key
|
|
KEYS * # List all keys
|
|
FLUSHDB # Clear all keys
|
|
INFO # Show Redis info
|
|
MONITOR # Monitor commands in real-time
|
|
```
|
|
|
|
### Redis Persistence
|
|
|
|
- Data persists in the `redis_data` volume
|
|
- If you need to reset Redis data: `docker volume rm gold_redis_data`
|
|
- Configure persistence in `docker-compose.yml` if needed:
|
|
|
|
```yaml
|
|
redis:
|
|
command: redis-server --appendonly yes # Enable AOF persistence
|
|
```
|
|
|
|
### Troubleshooting Redis
|
|
|
|
```bash
|
|
# Check if Redis is running
|
|
docker-compose logs redis
|
|
|
|
# Restart Redis
|
|
docker-compose restart redis
|
|
|
|
# Clear Redis cache
|
|
docker-compose exec redis redis-cli FLUSHDB
|
|
|
|
# Monitor Redis activity
|
|
docker-compose exec redis redis-cli MONITOR
|
|
```
|
|
|
|
## Docker Architecture
|
|
|
|
### Multi-Stage Build
|
|
|
|
The Dockerfile uses multi-stage builds to optimize for different frameworks:
|
|
|
|
- **base**: Foundation with core PHP extensions
|
|
- **node**: Adds Node.js runtime
|
|
- **laravel**: Laravel-specific extensions (Redis, APCu)
|
|
- **symfony**: Symfony-specific extensions (APCu, Sodium)
|
|
- **wordpress**: WordPress-specific configuration
|
|
- **opencart**: OpenCart-specific configuration
|
|
- **magento2**: Magento 2-specific configuration
|
|
|
|
### Services
|
|
|
|
#### PHP Service (FrankenPHP)
|
|
|
|
- **Image**: `dunglas/frankenphp:php{PHP_VERSION}-alpine`
|
|
- **Includes**:
|
|
- PHP 8.0-8.5
|
|
- Node.js v20.x
|
|
- Caddy web server
|
|
- Framework-specific extensions
|
|
|
|
#### Database Service (MariaDB)
|
|
|
|
- **Image**: `mariadb:latest`
|
|
- **Volume**: `db_data` (persistent)
|
|
- **Port**: `3306` (internal)
|
|
|
|
#### Redis Service (Cache)
|
|
|
|
- **Image**: `redis:alpine` (lightweight)
|
|
- **Volume**: `redis_data` (persistent)
|
|
- **Port**: `6379` (internal)
|
|
- **Health Check**: Built-in Redis ping monitoring
|
|
- **Available in all frameworks**: Laravel, Symfony, WordPress, OpenCart, Magento2
|
|
|
|
### Network & Volumes
|
|
|
|
```yaml
|
|
networks:
|
|
app-network: # Internal communication
|
|
driver: bridge
|
|
|
|
volumes:
|
|
caddy_data: # Caddy cache and data
|
|
caddy_config: # Caddy configuration
|
|
db_data: # Database persistence
|
|
```
|
|
|
|
## PHP Extensions
|
|
|
|
### Core Extensions
|
|
|
|
- **Database**: `pdo_mysql`, `mysqli`
|
|
- **String**: `mbstring`, `ctype`, `iconv`
|
|
- **Data**: `xml`, `dom`, `simplexml`, `fileinfo`
|
|
- **Security**: `openssl`, `tokenizer`
|
|
- **Utilities**: `curl`, `zip`, `intl`, `opcache`
|
|
|
|
### Framework-Specific Extensions
|
|
|
|
**All Frameworks** (Laravel, Symfony, WordPress, OpenCart, Magento2):
|
|
- `redis`: Redis cache and session support
|
|
|
|
**Laravel/Magento2**:
|
|
- Additional caching optimizations
|
|
|
|
**Symfony**:
|
|
- `apcu`: APCu caching
|
|
- `sodium`: Modern cryptography
|
|
|
|
**WordPress**:
|
|
- Additional compatibility features
|
|
|
|
## Troubleshooting
|
|
|
|
### Port Already in Use
|
|
|
|
```bash
|
|
# Change PORT in .env and restart
|
|
PORT=8080 docker-compose up -d
|
|
```
|
|
|
|
### Database Connection Issues
|
|
|
|
Verify credentials in `.env`:
|
|
|
|
```bash
|
|
docker-compose exec php php -r "
|
|
\$db = new mysqli('db', 'app', 'secret', 'database');
|
|
if (\$db->connect_error) exit('Connection failed: ' . \$db->connect_error);
|
|
echo 'Connected successfully!';
|
|
"
|
|
```
|
|
|
|
### Permission Issues
|
|
|
|
```bash
|
|
# Fix permissions in www directory
|
|
chmod -R 755 www/
|
|
```
|
|
|
|
### Rebuild Everything
|
|
|
|
```bash
|
|
docker-compose down -v
|
|
docker-compose up --build -d
|
|
```
|
|
|
|
### Check Container Status
|
|
|
|
```bash
|
|
docker-compose ps
|
|
docker-compose logs -f
|
|
```
|
|
|
|
## Useful Commands
|
|
|
|
```bash
|
|
# List running containers
|
|
docker-compose ps
|
|
|
|
# Restart a service
|
|
docker-compose restart php
|
|
|
|
# Rebuild images
|
|
docker-compose build --no-cache
|
|
|
|
# Execute command in container
|
|
docker-compose exec php <command>
|
|
|
|
# Copy files from container
|
|
docker cp <container>:/path/to/file ./local/path
|
|
|
|
# View resource usage
|
|
docker stats
|
|
```
|
|
|
|
## Performance Optimization
|
|
|
|
### For Production
|
|
|
|
1. Set `MODE=prod` in `.env`
|
|
2. Enable opcache in `php.ini`:
|
|
```ini
|
|
opcache.enable=1
|
|
opcache.memory_consumption=256
|
|
```
|
|
3. Configure Redis for caching:
|
|
```bash
|
|
docker-compose exec php redis-cli
|
|
```
|
|
|
|
### Database Optimization
|
|
|
|
1. Set appropriate `MYSQL_ROOT_PASSWORD`
|
|
2. Monitor with:
|
|
```bash
|
|
docker-compose exec db mysql -u root -p -e "SHOW PROCESSLIST;"
|
|
```
|
|
|
|
## Security Best Practices
|
|
|
|
- ✅ Change default database credentials in `.env`
|
|
- ✅ Use strong passwords for `MYSQL_ROOT_PASSWORD` and `MYSQL_PASSWORD_DATABASE`
|
|
- ✅ Set `MODE=prod` for production deployments
|
|
- ✅ Keep `php.ini` locked to read-only (default)
|
|
- ✅ Use environment variables for sensitive data
|
|
- ✅ Keep Docker images updated
|
|
|
|
## Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch (`git checkout -b feature/improvement`)
|
|
3. Make your changes
|
|
4. Test thoroughly
|
|
5. Commit with clear messages (`git commit -am 'Add improvement'`)
|
|
6. Push to your fork (`git push origin feature/improvement`)
|
|
7. Open a Pull Request
|
|
|
|
## License
|
|
|
|
[Specify your license here]
|
|
|
|
## Support & Resources
|
|
|
|
- **FrankenPHP Docs**: https://frankenphp.dev/
|
|
- **Caddy Docs**: https://caddyserver.com/docs/
|
|
- **Docker Docs**: https://docs.docker.com/
|
|
- **Compose Docs**: https://docs.docker.com/compose/
|
|
|
|
## Changelog
|
|
|
|
### v1.1.0 (Current)
|
|
- Multi-stage Docker build for framework-specific optimization
|
|
- Node.js v20.x integration
|
|
- Support for 5+ PHP frameworks with dedicated configurations
|
|
- Improved documentation and examples
|
|
- Production mode with automatic HTTPS
|
|
|
|
### v1.0.0
|
|
- Initial release with FrankenPHP and MariaDB
|
|
- Basic framework support
|
|
- Development and production modes
|
|
|
|
---
|
|
|
|
**Last Updated**: March 2026
|
|
**Maintainer**: Development Team
|