A modular Docker setup for Laravel applications with multiple build stages for different use cases.
- Base:
php:8.3-apache-bullseye - PHP Extensions: pdo, pdo_mysql, zip, pcntl
- Tools: Composer, Apache, Supervisor
- Process Management: Supervisor configured to run web server, queue workers, and scheduler
- Optimized: Production-only dependencies, no development tools
- Security: Proper file permissions, no root processes
- Base: Production stage + Xdebug
- Debugging: Xdebug configured for IDE integration
- UID Matching: Configurable UID/GID for host file permissions
- Development Dependencies: Full composer install with dev packages
laravel-docker/
├── production/
│ ├── Dockerfile # Clean production build
│ └── config/
│ ├── 000-default.conf # Apache configuration
│ ├── supervisord.conf # Supervisor configuration
│ ├── supervisorctl.conf # Supervisor control configuration
│ └── entrypoint.sh # Container entrypoint script
└── development/
└── Dockerfile # Development with Xdebug
docker build -f production/Dockerfile -t laravel:production .# Default (UID 1000 - matches most development environments)
docker build -f development/Dockerfile -t laravel:development .
# Custom UID for your environment
docker build -f development/Dockerfile \
--build-arg WWW_DATA_UID=1001 \
--build-arg WWW_DATA_GID=1001 \
-t laravel:development .Create a Dockerfile.app in your Laravel project:
# syntax=docker/dockerfile:1.3
# Production target
FROM git://github.com/your-username/laravel-docker.git//production#main AS production
COPY . /var/www/html
RUN composer install --optimize-autoloader --no-dev && \
chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
# Development target
FROM git://github.com/your-username/laravel-docker.git//development#main AS development
COPY . /var/www/html
RUN composer install && \
chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
Build specific targets:
# Production
docker build -f Dockerfile.app --target production -t myapp:prod .
# Development
docker build -f Dockerfile.app --target development -t myapp:dev .
version: '3.8'
services:
app-prod:
build:
context: .
dockerfile: Dockerfile.app
target: production
ports:
- "80:80"
environment:
- APP_ENV=production
app-dev:
build:
context: .
dockerfile: Dockerfile.app
target: development
ports:
- "8080:80"
- "9003:9003" # Xdebug
volumes:
- .:/var/www/html
environment:
- APP_ENV=local
Location: Development stage only
Default: 1000/1000
Purpose: Match host user permissions for development
# Check your host UID
id -u
# Build with matching UID
docker build -f development/Dockerfile \
--build-arg WWW_DATA_UID=$(id -u) \
--build-arg WWW_DATA_GID=$(id -g) \
-t laravel:development .Why only in development?
- Production doesn't need host file permission matching
- Development uses volume mounts that need proper permissions
- No root processes: All services run as www-data
- Proper permissions: 755 instead of 777 for supervisor directories
- Configurable UID: Can match host user for development
- Isolated stages: Each stage has only necessary components
- Docker with BuildKit support (Docker 23.0+)
- Git repository access for BuildKit git contexts
- Enable BuildKit:
export DOCKER_BUILDKIT=1
- Fork the repository
- Create a feature branch
- Make your changes
- Test with different UID configurations
- Submit a pull request
MIT License