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

Takeout Laravel Package

tightenco/takeout

Takeout is a Laravel package and CLI for running local development services like MySQL, Redis, Postgres, and Mailhog via Docker. Define the services you need in a simple config file, then start, stop, and connect to them with a single Artisan command.

View on GitHub
Deep Wiki
Context7

Getting Started

Takeout is a require-dev Composer package that generates and drives a per-project docker-compose.yml for backing services. It does not install Docker, and it does not rewrite your .env or config/database.php. Internalizing that boundary early prevents most first-day confusion.

Prerequisites — verify before installing:

docker compose version      # Takeout shells out to Compose v2

You need a running engine (Docker Desktop, OrbStack, or Colima on macOS; Docker Desktop/WSL2 on Windows; native Docker with your user in the docker group on Linux) and Compose v2 on PATH. If docker compose doesn't work standalone, Takeout won't either.

Install and first run:

composer require --dev tighten/takeout
./vendor/bin/takeout list                # authoritative service list + exact spelling
./vendor/bin/takeout enable mysql

Note the invocation: ./vendor/bin/takeout, not php artisan takeout. Update any onboarding docs or scaffolder templates that assume an Artisan command.

enable starts the container and prints the host port it assigned. Wire it immediately:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306        # whatever enable printed
DB_DATABASE=myapp
DB_USERNAME=root
DB_PASSWORD=
php artisan config:clear
php artisan migrate

Where to look first, in order:

  1. ./vendor/bin/takeout list and takeout <command> --help — the CLI is the documentation.
  2. The generated docker-compose.yml in the project root — plain Compose, readable, and the source of truth for what is running.
  3. The config file Takeout writes in the project root after the first enable — the record of enabled services and assigned ports. Read it; don't trust memory.
  4. docker compose ps — the only trustworthy answer to "what port is it on right now?"

First use case to validate: enable MySQL → wire .env → config:clear → migrate → disable/enable → confirm data survived. That loop is the whole package. Everything else is the same loop with different service names.

Implementation Patterns

One service at a time, commit as you go. Enable → smoke-test → commit the generated YAML → next service. Adding MySQL, Redis, Mailpit, and MinIO in one sitting leaves you with four suspects when something breaks. The YAML is a reviewable artifact living beside your code; treat it that way from the first commit.

Pin image tags in the committed file. The v3.2.1 release is a PostgreSQL 18 volume-path fix — anyone tracking postgres:latest was silently moved to 18 by an upstream push and hit initdb errors or restart loops. After enable postgres, edit the tag to an explicit version and commit it. Do this for every service immediately. Tag bumps then become reviewable PRs instead of surprise outages.

Regenerate; don't hand-edit the base file. For a version bump, a port scheme change, or a PG 18 migration, the supported path is takeout disable postgres && takeout enable postgres. Hand-edits survive until the next regeneration silently overwrites them.

Use Compose's native override for customization. Need a fourth service, a platform: pin, a healthcheck, or a mounted init script? Put it in docker-compose.override.yml. Compose merges it automatically on every invocation, so it survives Takeout regenerating the base file. This is the correct extension point.

Resolve the per-enable ports vs. committed YAML tension explicitly. Takeout picks a free host port on enable, which enables concurrency across projects but means the committed YAML and each developer's .env drift. Two viable stances — pick one per team and write it down, because the failure mode is half the team assuming each:

  • Concurrency-first: don't treat ports as gospel. Document "run takeout enable <service> and paste the printed port into .env" in the README. Nothing in the app hardcodes ports, so divergence is fine.
  • Determinism-first: use --default-port (check takeout enable --help) or fix the port in the YAML after enabling, then commit. Predictable across the team, but one project per service at a time on a given machine.

Learn the two distinct reset operations:

./vendor/bin/takeout disable mysql && ./vendor/bin/takeout enable mysql   # keeps data
docker compose down -v                                                    # destroys volumes

The first is the daily context-switch. The second is "migrations are wedged / I want a clean seed" — irrecoverable, and the answer to a surprising number of "nothing works" moments. Reach for it deliberately.

Mail is the highest-value, lowest-risk adoption. Swap MAIL_MAILER=smtp and point at the printed Mailpit/Mailhog port. Every project gets its own web inbox instead of a shared one full of other people's test mail.

Redis covers cache, queue, and sessions in one container. Set CACHE_STORE=redis, QUEUE_CONNECTION=redis, optionally SESSION_DRIVER=redis, then run php artisan queue:work on the host against the published port. No extra service required.

Multi-project concurrency is the real differentiator. Per-project containers and named volumes let you hold three client apps live simultaneously with isolated databases. Document a realistic ceiling (each MySQL/Postgres is a few hundred MB of RAM) so engineers self-limit rather than discovering it during a demo.

Wire it into onboarding, not CI. A workable README block:

cp .env.example .env && composer install
docker compose version && ./vendor/bin/takeout enable mysql
# paste the printed port into .env, then:
php artisan key:generate && php artisan migrate --seed

A small composer setup script that ends by telling the developer to run takeout enable is fine. Do not attempt automated port injection into .env — half-working automation here is worse than a two-line README.

Gotchas and Tips

Port drift is the #1 support ticket. Every disable/enable can hand you a different host port, and Takeout will not update .env. The symptom is "connection refused," universally misdiagnosed as credentials or an auth-plugin problem. First question for any local DB failure: did you re-run enable, and does .env match docker compose ps?

takeout disable does not delete data. Named volumes persist. Engineers expect a wipe and get their old broken schema back; others expect persistence and lose seed data to down -v. State both facts in the README.

PostgreSQL 18 specifically. The v3.2.1 fix moved the mount from /var/lib/postgresql/data to /var/lib/postgresql. If you see initdb: directory not empty or a restart loop after upgrading, do not hand-patch the mount line — regenerate with takeout disable postgres && takeout enable postgres. Better: pin postgres:17 or an explicit 18.x so upstream pushes can't move you.

Never run Takeout alongside Laravel Sail in the same project. Both own docker-compose.yml and both claim host ports; the resulting errors are genuinely confusing. One orchestrator per project, decided once, written down.

Takeout is not a CI, staging, or production tool. In CI, mirror your pinned tags into explicit services: blocks with healthchecks. Don't wrap a developer-convenience CLI into a pipeline.

Use 127.0.0.1, not localhost, for DB_HOST. On many systems localhost resolves to ::1 first and the container isn't listening on IPv6 — a fast, misleading "connection refused." Same for Redis.

.env values are perspective-dependent. 127.0.0.1:<published port> is correct for php artisan on the host. If you later containerize the app, the host becomes the service name (mysql) and the port the internal one (3306). Don't copy a colleagueʼs .env across that boundary.

Apple Silicon. Some images remain amd64-only and will be slow or fail. Fix with an explicit platform: linux/amd64 in docker-compose.override.yml — never in the generated file. Budget a short compatibility pass before declaring Takeout ready for a mixed-hardware team.

php artisan config:clear after any config change. Cached config is the second-most-common reason a corrected .env "doesn't work." In local dev, consider not caching config at all.

Debugging commands worth memorizing:

docker compose ps                     # real ports, real state
docker compose logs -f mysql          # why did it exit
docker compose down -v                # nuke and start over
./vendor/bin/takeout list             # exact service names, no guessing

Linux permission trip. A socket permission error means your user isn't in the docker group: sudo usermod -aG docker $USER, then log out and back in. It looks like a Takeout bug and never is.

Know the package's boundary. Takeout doesn't rewrite .env, manage PHP versions, provide an app runtime, or help with multi-repo networking. If you find yourself wishing it did, what you actually want is Sail, DDEV, or a platform solution — and that's a per-project decision, not something to bolt on top.

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.
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
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route