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

Laravel Zero Docker Laravel Package

owenvoke/laravel-zero-docker

Provides Docker support for Laravel Zero applications, with a ready-made container setup for building, running, and distributing standalone PHP CLI apps. Helps keep local and production environments consistent and simplifies packaging Laravel Zero projects as portable Docker images.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a build-time generator, not a runtime dependency. The whole value is the Dockerfile it emits, which you then own and commit.

  1. Install as a dev dependency so nothing leaks into the production image:
    composer require owenvoke/laravel-zero-docker --dev
    
  2. Find the command. The package registers an artisan command that generates Docker scaffolding. Discover its exact name and signature:
    php artisan list
    php artisan <docker-command> --help
    
    Look specifically for --path (where to write the file) and --force (overwrite) options before running it.
  3. Inspect the stubs first. Laravel Zero packages typically ship a stub Dockerfile under vendor/owenvoke/laravel-zero-docker/. Read that stub before generating — it tells you which PHP/Box/base-image versions the generator assumes, which is the biggest thing you need to know.
  4. Generate, review, commit.
    php artisan <docker-command>
    git add Dockerfile docker-compose.yml .dockerignore 2>/dev/null || true
    
  5. First build and smoke test:
    docker build -t my-cli .
    docker run --rm my-cli list          # or my-cli --version
    

Where to look first / first use case: the canonical first use case is "my Laravel Zero CLI works locally but the target host has no PHP/Composer." The generator gets you to a multi-stage Box → PHAR → slim runtime image so the host only needs Docker. Treat the generated Dockerfile as a code review artifact, not as final output — that review is the real step.

If you are not on Laravel Zero, or you don't use Box, stop here: copy the pattern from the repo and skip the dependency.

Implementation Patterns

Vendor-then-own (the intended pattern). Generate once, commit the Dockerfile, and stop invoking the generator. The dependency exists to save you the first draft. Re-running it later is a deliberate upgrade action, not a routine build step.

Multi-stage build shape. The generated Dockerfile should follow this order — keep it intact when you harden:

# Stage 1: builder — Composer deps, Box, compile PHAR
FROM php:8.x-cli AS builder
# ... install extensions, composer install --no-dev --optimize-autoloader, box compile

# Stage 2: runtime — slim base + PHAR only
FROM php:8.x-cli-slim   # or alpine
COPY --from=builder /app/build/<output>.phar /usr/local/bin/my-cli
USER app
ENTRYPOINT ["/usr/local/bin/my-cli"]

Keep box.json and the COPY --from line in the same commit. The PHAR output path in box.json is the exact path the runtime stage copies. Rename the app or the output and the build silently breaks — pair the change with a CI smoke test.

Local dev loop with docker-compose. Use the generated compose file for interactive runs and volume-mounted iteration, and the plain Dockerfile for the release artifact. Don't blur them — the compose setup is a developer convenience, the Dockerfile is the deliverable.

CI integration tip. Wire a smoke test that actually executes the image, not just builds it:

docker build -t my-cli:$GIT_SHA .
docker run --rm my-cli:$GIT_SHA list   # proves PHAR boots, extensions load

Add image scanning and SBOM generation in the same job. The generated file gives you a runtime with no build toolchain — that's a scan-friendly starting point.

Standardize across a portfolio. If you have multiple Laravel Zero CLIs, promote the hardened, pinned Dockerfile as an internal template (same base image, same non-root user, same stages, same entrypoint convention) and stop generating per-repo. That consistency is the actual win; the package is just the seed.

Customization approach. Prefer post-generation edits over fighting the generator: pin base-image digests, add PHP extensions to both stages, add .dockerignore, adjust the entrypoint. If the package supports publishing stubs, publish and edit them once — otherwise treat each generated file as a fork you maintain.

Gotchas and Tips

Version drift is the number-one risk. The stub hardcodes a PHP/Box/Laravel Zero combination. Before you standardize, confirm the versions and align the generator's base image tag with your composer.json php constraint. A single-maintainer package with low adoption will drift — budget a compatibility pass whenever you bump Laravel Zero, PHP, or Box.

Box must be installed inside the builder stage. Verify the stub doesn't expect box on the host PATH or a pre-existing global install. If it does, fix it — otherwise the build fails only on clean CI runners, which is the worst place to discover it.

Missing extensions show up in either stage. A Symfony/Laravel Zero app can build a PHAR fine and still fail at runtime because a required extension (pdo_mysql, intl, bcmath, sodium) is in the builder but not the slim runtime. Audit php -m in both stages:

docker run --rm <builder-image> php -m
docker run --rm <runtime-image> php -m

PHAR path drift and app renames are the most common silent breakage. The COPY --from=builder path is a string that has no compile-time check. Keep it tied to box.json's output and gate with a smoke test.

Non-root and file permissions. After USER app, the PHAR must be readable and any runtime cache/config directory writable. Test the image as the unprivileged user, not as root by accident.

Entrypoint and signal handling. For CronJob or queue-style usage, the container must forward signals correctly and exit with the app's status code — not the shell's. Use ENTRYPOINT ["/usr/local/bin/my-cli"] (exec form), not shell form, and confirm docker run --rm my-cli returns the CLI's exit code.

Debugging a failed build. Drop into each stage rather than guessing:

docker build --target builder -t my-cli-builder .
docker run --rm -it my-cli-builder sh

Re-run the failing step (composer install, box compile) manually inside that shell.

Generator overwrite semantics. If the command supports --force, never run it on an already-hardened Dockerfile without a diff. Decide your policy up front: commit-and-edit (preferred) or generate-in-CI-never-edit — don't mix, or you'll silently clobber your hardening.

Single-arch assumption. If the stub uses plain FROM, it builds only for the host architecture. For multi-arch delivery, add Buildx with --platform linux/amd64,linux/arm64; verify the base image supports both.

Private Composer auth. The builder's composer install needs credentials for private packages (or a CI cache path). Document the build secret/credential route — don't discover it mid-CI.

Oversized images. The runtime stage should contain only the PHAR and runtime extensions — no vendor/, no source, no dev tooling. If your image is hundreds of MB, something from the builder leaked into the runtime stage.

Exit cheaply. Because the output is a checked-in file, you can drop the dependency any time and keep the Dockerfile. Fork or copy the stub if upstream goes quiet — the reversal cost is minutes.

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