Getting Started
This guide gets Laradock running for your project. The fastest path is the Laradock CLI, a short wizard that sets everything up for you, so start there. If you would rather wire things up by hand with plain docker compose, see Manual setup, it is meant for advanced users who want full control.
Three ways to point your AI assistant at Laradock:
- Run it for you - the repo ships agent instructions (
AGENTS.md+ rule files for Claude Code, Gemini CLI, Cursor, Cline, and Windsurf). Open the repo in your agent and say "Set up Laradock for this project." - Ask about it, no clone - add the docs as an MCP server:
https://gitmcp.io/laradock/laradock. - Read a walkthrough - browse the AI-generated overview on DeepWiki, starting with its architecture diagram.
Building something specific? Jump straight to a guide tailored to the most popular platforms:
Not one of these? Browse the full list of 100+ supported projects, then follow its guide. Otherwise the generic steps below work for any PHP app.
Requirements
Get started with CLI
1 - Clone Laradock inside your PHP project (or anywhere, if you don't have one yet):
git clone https://github.com/laradock/laradock.git
cd laradock
2 - Start your stack:
./laradock start
On the first run, start walks you through a short setup wizard: it detects your framework and lets you pick your project, PHP version, and services (web server, database, cache), everything pre-answered, then points your app's .env at those services, starts the stack, and prints its URLs and credentials. After that, ./laradock start just starts and reprints them. Re-run the wizard any time with ./laradock setup.
3 - Enter the workspace, a dev shell with php, composer, node, and git inside:
./laradock workspace
4 - Open http://localhost. Done.
artisan, composer, npm?Inside the workspace container, not on your machine. Enter it once with ./laradock workspace and run commands from there, or prefix a single one: ./laradock exec workspace php artisan migrate.
The CLI hides nothing: it prints every real docker compose command it runs, keeps no state, and only ever writes your .env. Unknown commands pass straight through (./laradock logs -f nginx runs docker compose logs -f nginx). Full reference: The Laradock CLI.
How it works
The stack
Here is the whole picture from where you sit. You work two ways: open your app in a browser (Nginx serves it through PHP-FPM), or drop into the Workspace terminal to run artisan, composer, npm. Both act on the same codebase, mounted straight from your machine. Your code talks to whatever services you switch on, add as many as you need, and the same setup ships to production. Click any node to open its source.
Solid arrows are how you drive it; dashed arrows are the optional services your code uses. Each service is its own container, switch them on and off per project and they never conflict, and add as many as you like from the 100+ available.
How Laradock configuration works
- Your
.env(created on first run, orcp .env.example .envby hand) holds the shared settings: paths, PHP version, project name. - Each service keeps its own settings pre-filled in its folder:
mysql/defaults.env,nginx/defaults.env, and so on. You never need to copy or edit those files, they work out of the box. - To change any setting, shared or per-service, add that line to your
.envwith your value. Your.envalways wins over everydefaults.env. For example, to run MySQL on another port, addMYSQL_PORT=3307to your.env. - To discover what a service lets you configure, open its folder's
defaults.env, it's a short, readable list. - Upgrading from an older Laradock? Your existing full
.envkeeps working exactly as before, no changes needed.
MYSQL_PASSWORD, POSTGRES_PASSWORD, and the other database credentials are applied the first time that database starts, when it creates its data files on disk. Changing them in .env later (even with ./laradock rebuild) does not update an existing database; the old password keeps working. To change a database password for real, either run the change inside the database itself (for example ALTER USER), or delete that service's data folder under DATA_PATH_HOST so it initializes fresh (this erases that database's data).
How a request flows
Here is what actually happens when a browser hits your app: Nginx hands the request to PHP-FPM, which runs your code and talks to whichever services you enabled, then hands the response back. Anything you queue is passed to the worker and finishes in the background.
The database and cache here are whatever you enabled (Postgres, Valkey, and so on): the shape stays the same.
How the repository is organized
One folder per service, and everything about a service lives in its folder:
laradock/
├── docker-compose.yml # the service catalog: shared networks/volumes + include list
├── .env.example # shared settings template (copy to .env)
├── mysql/
│ ├── compose.yml # mysql's container definition
│ ├── defaults.env # mysql's settings, pre-filled
│ └── Dockerfile # mysql's image
├── nginx/
│ ├── compose.yml
│ ├── defaults.env
│ ├── Dockerfile
│ └── sites/ # your site configs
└── ... # ~100 more services, same pattern
So when you want to:
| You want to... | Edit... |
|---|---|
| Change any setting (port, version, password, flag) | your .env (add one line, it wins) |
| See what a service lets you configure | <service>/defaults.env (read-only for you) |
| Change a container's structure (mounts, links, ...) | <service>/compose.yml |
| Change how an image is built | <service>/Dockerfile, then rebuild |
The root docker-compose.yml pulls every service in via Compose include, which requires Docker Compose v2.20 or newer. Every top-level folder in the repo is a runnable container, so the folder list is always the up-to-date list of available services.
How networking works
Containers sit on two Docker networks. The web server faces the outside on the frontend network; everything else (PHP-FPM, your database, cache, queue, search, and the background worker) lives on the backend network, out of reach from outside. The web server bridges the two so it can pass requests through to PHP-FPM.
The browser reaches the web server through published ports, not a Docker network. Switch the driver for both networks with NETWORKS_DRIVER in your .env. More: Networking.
Running multiple projects
One Laradock can serve one project, or many. Run an isolated Laradock per project (separate containers and data), or serve several sites from one Laradock with a web-server config each. Different PHP versions per project are supported too.
→ Full guide: Running Multiple Projects · Multiple PHP Versions
Manual setup (advanced, full control)
Rather wire things up by hand? Everything the CLI does, you can do with plain docker compose, same files, same result. It's the path for advanced users who want full control over exactly which containers run and how they're configured.
→ Full guide: Manual Setup (without the CLI)