laravel-fans/docker
A Docker-based development environment for Laravel, helping you spin up consistent PHP, database, and service containers for local development with minimal setup and easy configuration.
laravel-fans/laravel-docker is a Docker environment scaffold, not a runtime PHP library — expect to consume it as a template/config set rather than via composer require. The first practical use is standing up a Laravel stack (app + web server + database + cache) from the shipped Compose/Dockerfile definitions.
Minimal steps:
docker-compose.yml (or compose.yaml) — the source of truth for services, networks, and volumes.Dockerfile (and any docker/*/Dockerfile) — base images, PHP version, extensions.docker/ (or dockerfiles/, .docker/) — nginx/site configs, php.ini, supervisord, entrypoints.README.md and any .env.example — the expected environment variable names.docker/ subfolder), since a 42-star package with 0 dependents is almost certainly a "clone and adapt" asset rather than a maintained Composer dependency. Pin the source commit you copied so upgrades are intentional.composer.json platform.php, database driver in .env vs. the compose service name, and the document root used by nginx vs. your public/.cp .env.example .env (adjust APP_URL, DB_HOST to the compose service name), docker compose build, docker compose up -d, then docker compose exec app php artisan key:generate && php artisan migrate.If the package is exposed as a Composer package, its install path will be in the README (composer require + php artisan vendor:publish); verify before assuming. Given the star count, check last-commit date and open issues before depending on it in production.
Treat it as a layered template, not a library. The highest-leverage pattern is to keep the upstream files pristine and layer your changes:
docker-compose.yml — upstream services.docker-compose.override.yml — developer-only tweaks (bind mounts, Xdebug, exposed ports).docker-compose.prod.yml — production resource limits, no bind mounts, secrets, log drivers.Run with docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d so you never edit the vendor/template file.
Standard Laravel service topology to expect or add:
| Service | Purpose | Notes |
|---|---|---|
app |
PHP-FPM running Laravel | Build target from Dockerfile |
web |
nginx (or Caddy) | root /var/www/public, fastcgi_pass app:9000 |
db |
MySQL/Postgres | Named volume for data |
redis |
Cache/session/queue | Shared by app + workers |
queue |
php artisan queue:work |
Same image as app, different command |
scheduler |
php artisan schedule:work or cron |
Same image again |
Reusing one image for app, queue, and scheduler with different command: values is the cleanest pattern and avoids "works in web, fails in worker" drift.
Environment wiring. Compose service names become hostnames, so .env inside the container must use them:
DB_HOST=db
REDIS_HOST=redis
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
Avoid baking .env into the image. Inject at runtime via compose env_file: or orchestrator secrets.
Multi-stage Dockerfile pattern (if the repo doesn't already do this, add it):
base — PHP + extensions (pdo_mysql, redis, gd, zip, bcmath, intl).vendor — composer install --no-dev --optimize-autoloader from composer.lock.assets — node stage running npm ci && npm run build.runtime — copy vendor + built assets + app, set opcache.validate_timestamps=0, run as non-root.Deployment workflow. Build once, promote the same image through staging→prod. Run php artisan config:cache route:cache view:cache in an entrypoint after env injection, never in the Dockerfile (otherwise you cache build-time values and silently ship wrong config).
Local dev integration. Mount the app as a bind volume, keep vendor/ and node_modules/ as named volumes so the container's copies aren't clobbered. Use docker compose watch (Compose v2.17+) or a host-side npm run dev proxied through Vite's server.host setting if the template's nginx doesn't handle HMR.
.env is not automatically read by Compose. docker compose reads a root .env for variable substitution in the YAML, while Laravel reads the app's .env inside the container. Confusing the two is the most common failure — e.g., DB_HOST=${DB_HOST} resolves from host context, not the container's file.config:cache runs during docker build, APP_KEY, APP_URL, and DB credentials get frozen. Always cache at container start after secrets are mounted.storage/ and bootstrap/cache/ writable by the FPM user (www-data typical). Bind mounts on Linux will expose UID mismatches; align with user: in compose or an entrypoint chown. Don't chmod 777.opcache.validate_timestamps=0 is a production win but will make code edits invisible in dev — keep a dev override that re-enables it (or skip opcache there).php artisan queue:restart after each release, and set --max-time/--tries so long-lived workers recycle. The image alone won't do this for you.healthcheck: to db, redis, and app; make dependent services use depends_on: { condition: service_healthy } so migrations don't race the database on cold start.migrate service or a release phase in your orchestrator, not "migrate on boot in every app container."json-file will accumulate; set logging: { driver: json-file, options: { max-size, max-file } } or route to your platform.docker compose logs <svc>, docker compose run --rm app sh to bypass the entrypoint, and docker compose exec app php artisan about to confirm env/config values Laravel actually sees.ARG PHP_VERSION, an entrypoint.sh hook, nginx site config under docker/nginx/conf.d/, and php.ini overrides in docker/php/conf.d/. Copy these into your repo so upstream changes can be re-merged.php:8.3-fpm@sha256:...), run docker scout cves / trivy image, and schedule base-image bumps yourself — don't rely on the package for CVE patching.How can I help you explore Laravel packages today?