Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dockerize Laravel Package

phpexperts/dockerize

Dockerize by PHP Experts quickly generates production-ready Dockerfiles and docker-compose configs for PHP and Laravel apps, including customizable PHP, Nginx, MySQL, and Redis services to containerize projects fast.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites: Docker Engine and the Compose plugin (docker compose version) on the host. This package generates Docker scaffolding — it does not run containers for you.

Install and first run

composer require --dev phpexperts/dockerize
vendor/bin/dockerize --help

The binary lives in bin/ upstream, so the exact entry point may be vendor/bin/dockerize or vendor/bin/dockerize.php depending on version. Run --help before anything else and treat the flags as the source of truth — the package moves fast relative to its docs.

What it produces: a Dockerfile, a docker-compose.yml, and a docker/ directory containing entrypoint.sh helpers plus grab_files.sh / extract-binaries.sh for multi-stage binary copying. That docker/ tree is the real product; the Dockerfile is mostly a thin wrapper around docker-php-ext-install plus copying those scripts in.

Where to look first, in order:

  1. docker/entrypoint.sh — this is what runs on container start and controls permissions, DB wait, and boot commands.
  2. The docker-php-ext-install / pecl install lines in the Dockerfile — that's the extension list you will almost certainly edit.
  3. docker-compose.yml — check service names, ports, volumes, and whether app, web, db, redis were separated correctly.

First use case — a Laravel app with MySQL and Redis:

vendor/bin/dockerize          # scaffold
# review Dockerfile + docker-compose.yml + docker/entrypoint.sh
docker compose build
docker compose up -d
docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate

Then hit http://localhost. If you get a 500, it's almost always storage//bootstrap/cache/ permissions from the bind mount — see Gotchas.

Implementation Patterns

Scaffold once, then own the files. Treat dockerize as a code generator, not a dependency. Run it, review the output, commit it, and hand-maintain from there. Regenerating later will overwrite your edits, so when you do update the package, regenerate into a throwaway branch and diff:

git switch -c regen-docker
vendor/bin/dockerize
git diff

Split dev and prod concerns with Compose overrides. Keep docker-compose.yml minimal and add docker-compose.override.yml for local dev (bind mounts, Xdebug, mailhog), and docker-compose.prod.yml for the deployed shape (no bind mounts, opcache on, Xdebug off, restart policies).

# docker-compose.override.yml
services:
  app:
    volumes:
      - .:/var/www/html
    environment:
      XDEBUG_MODE: develop,debug

Run queue workers and the scheduler as sibling services. This is the single most common thing a generated compose file omits. Copy the app service and override the command:

  queue:
    build: .
    command: php artisan queue:work --tries=3 --sleep=1
    depends_on: [db, redis]
  scheduler:
    build: .
    command: php artisan schedule:work

Customize the extension list in the Dockerfile, not on every build. The generated list is a starting point. For a typical Laravel app you'll add pdo_mysql, bcmath, gd, intl, zip, redis (via pecl install redis), and possibly imagick. Add them once, rebuild once:

RUN docker-php-ext-install pdo_mysql bcmath gd intl zip \
 && pecl install redis \
 && docker-php-ext-enable redis

Use the docker/ scripts as your integration seam. entrypoint.sh is the intended hook for “wait for DB, fix permissions, run composer install if vendor/ is missing, then exec the CMD.” grab_files.sh and extract-binaries.sh are what you reach for when a multi-stage build needs to copy artifacts (e.g., a Go binary, or composer's vendor/) out of a builder stage. Read them before rewriting them; they encode the intended conventions.

CI usage. Build the same Dockerfile in CI and run tests inside it, so local and CI environments match:

- run: docker compose -f docker-compose.yml -f docker-compose.ci.yml build app
- run: docker compose run --rm app vendor/bin/phpunit

Environment handling. Never bake .env into the image — the scaffold already tends toward env_file/inline environment in compose. Keep a committed .env.example, mount or env_file: the real one locally, and set real values through your platform's secret store in prod. APP_KEY and DB_* should come from the environment, not the image.

Composer caching. If builds are slow, add a BuildKit cache mount for Composer's cache in a builder stage rather than re-downloading on every compose build.

Gotchas and Tips

It is a generator, and a young one. With ~76 stars and zero dependents, treat the output as a well-informed template, not a battle-tested runtime. Read every generated file before you git add it. The AGENTS.md workflow (per-commit shell tests, signed commits, rebase over merge) tells you the maintainers test image builds aggressively — but that does not mean your app's quirks are covered.

PHP version detection is the most likely thing to be wrong. The tool guesses from composer.json's platform or require.php, and that guess can disagree with what you actually deploy on. Pin the base image explicitly (FROM php:8.3-fpm or similar) and verify php -v inside the container matches production.

Permissions on bind mounts. Linux hosts with www-data (uid 33) inside the container will fail to write storage/, bootstrap/cache/, and database/database.sqlite if your host uid differs. Fixes, in order of preference: chown -R www-data:www-data in entrypoint.sh; run the app as your host uid via user: in compose; or use a named volume instead of a bind mount for writable dirs. Do not solve this with chmod 777.

Don't COPY . . in dev. It defeats live reload and bloats the image. Keep source out of the dev image and use a bind mount; reserve COPY for the production stage.

.dockerignore matters more than people expect. At minimum: .git, node_modules, vendor, storage/logs/*, *.log, .env, .idea, .vscode. Without it, every build ships your node_modules and half a gigabyte of logs.

depends_on does not wait for the database. A generated compose file will start MySQL and PHP at the same time. Either add healthchecks:

  db:
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 3s
      retries: 20

or keep the wait loop in entrypoint.sh. Either is fine; having neither is a source of flaky CI.

Xdebug. Enable it only via build arg or XDEBUG_MODE env, never in the default image. It routinely triples request time and confuses people benchmarking their app.

Opcache in dev. If opcache.validate_timestamps=0 leaked into your dev config, file edits silently do nothing until restart. Check with php -i | grep opcache inside the container before blaming your editor.

Composer install location. Doing composer install on every container start is slow and races when you scale to multiple replicas. Prefer a builder stage that produces vendor/, then copy it in — or gate the entrypoint's install behind [ ! -d vendor ].

Debugging checklist. docker compose build --no-cache (rules out stale layers), docker compose run --rm --entrypoint sh app (gets you a shell even if the entrypoint crashes), docker compose logs -f app (entrypoint output), and docker inspect <container> for env and mount reality versus what compose claims. Most “it worked yesterday” issues are a stale layer or an env var that only exists in one compose file.

Extension points, summarized. The Dockerfile stages, entrypoint.sh, and the grab_files.sh / extract-binaries.sh helpers are all yours to edit after generation — they're ordinary scripts, not framework magic. Adding a healthcheck, a new service, or a multi-stage build that copies binaries from another image are all supported workflows, not hacks.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings