Manual Magento 2 setup is like a Rubik's Cube. Learn how Docker Compose aligns every dependency so your store runs first time. Follow the guide.
On this page
Setting up Magento2 manually can feel like solving a Rubik’s Cube – every dependency (PHP, MySQL, Elasticsearch, Redis, Nginx/Apache) needs to align perfectly. Enter Docker Compose, a tool that simplifies this process by managing all services with a single configuration file.
At Raulji Technologies, we use Docker Compose to create efficient Magento2 development environments. As Yuvraj Raulji, our Magento2 expert, explains: “Docker Compose allows Magento2 developers to launch a fully functional environment with just one command, saving time and effort.” In this guide, we’ll walk you through running Magento2 with Docker Compose from scratch.
Why Use Docker Compose for Magento2?
- Quick Setup: No need to install services manually – Docker Compose does it for you.
- Consistency: Your setup works identically across all environments, eliminating the “it works on my machine” problem.
- Modularity: Easily add or remove services like Redis or Elasticsearch.
- Easier Management: Start, stop, and rebuild services with simple commands.
Step 2: Set Up a Magento2 Project with Docker Compose
Create a new directory for your Magento2 project and navigate into it:
Copy
mkdir magento-docker && cd magento-docker
Step 3: Define Services in docker-compose.yml
Create a docker-compose.yml file inside the magento-docker directory and add the following configuration
Copy
version: ‘3.7’
services:
app:
image: magento/magento2
container_name: magento_app
restart: always
depends_on:
– db
– redis
volumes:
– ./app:/var/www/html
environment:
– MYSQL_HOST=db
– MYSQL_USER=magento
– MYSQL_PASSWORD=magento
– MYSQL_DATABASE=magento
ports:
– “80:80″db:
image: mysql:5.7
container_name: magento_db
restart: always
environment:
– MYSQL_ROOT_PASSWORD=root
– MYSQL_DATABASE=magento
– MYSQL_USER=magento
– MYSQL_PASSWORD=magento
ports:
– “3306:3306″elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.9.3
container_name: magento_elasticsearch
environment:
– discovery.type=single-node
– ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
– “9200:9200″redis:
image: redis:latest
container_name: magento_redis
restart: always
ports:
– “6379:6379”
What This File Does
- app: Runs Magento2 using an official Magento Docker image.
- db: Sets up a MySQL 5.7 database for Magento.
- elasticsearch: Required for Magento 2.4+ search functionality.
- redis: Improves caching and performance.
Step 4: Clone Magento2 Source Code
Run the following command inside the magento-docker directory to download the Magento2 source code:
Copy
mkdir app && cd app
git clone https://github.com/magento/magento2.git .
Step 5: Start Magento2 with Docker Compose
Run the following command in the magento-docker directory to start the containers
Copy
docker-compose up -d
This will:
- Download the necessary Docker images.
- Start Magento2 and its required services.
- Mount the Magento2 source code inside the container.
Step 6: Install Magento2 in the Container
After starting the containers, install Magento2 by running:
Copy
docker exec -it magento_app bin/magento setup:install \
–base-url=http://localhost/ \
–db-host=db \
–db-name=magento \
–db-user=magento \
–db-password=magento \
–admin-firstname=Admin \
–admin-lastname=User \
–admin-email=admin@example.com \
–admin-user=admin \
–admin-password=Admin123 \
–language=en_US \
–currency=USD \
–timezone=America/New_York \
–use-rewrites=1
Step 7: Access Magento2 in Your Browser
Once the installation is complete, open your browser and visit:
Admin Panel: http://localhost/admin
Step 8: Manage Magento2 with Docker Compose
Restart Containers:
Copy
docker-compose restart
Stop Containers:
Copy
docker-compose down
Run Magento CLI Commands Inside the Container:
Copy
docker exec -it magento_app bin/magento cache:flush
docker exec -it magento_app bin/magento indexer:reindex
View Logs:
Copy
docker logs magento_app
Step 9: Configure Additional Services (Optional)
Adding Varnish for Full-Page Caching
Add the following to your docker-compose.yml file:
Copy
varnish:
image: varnish:6.5
container_name: magento_varnish
depends_on:
– app
ports:
– “6081:6081”
Varnish speeds up page loading times by caching responses.
Adding Mailhog for Email Testing
Add the following to your docker-compose.yml file:
Copy
mailhog:
image: mailhog/mailhog
container_name: magento_mailhog
ports:
– “1025:1025”
– “8025:8025”
Mailhog catches outgoing emails so you can test them in a browser.
Final Thoughts
Using Docker Compose to run Magento2 is the fastest and most reliable way to set up a local development environment. This method ensures that your Magento store runs smoothly, with all necessary services in isolated containers.
At Raulji Technologies, we rely on Docker for efficient Magento development. Yuvraj Raulji highly recommends this approach to developers looking for an easy-to-manage environment.
What’s Next?
Stay tuned for our upcoming tutorials on:
- Optimizing Magento2 Performance with Docker: Fine-tune your setup for maximum speed.
- Deploying Magento2 with Docker: Learn how to take your Dockerized Magento store to production.
- Advanced Docker Compose Configurations: Explore custom images, multi-container orchestration, and more.
Ready to supercharge your Magento2 development with Docker? Let Raulji Technologies help you build a faster, more efficient eCommerce store. Contact us today! 🚀
Frequently Asked Questions
Answers to the questions we hear most often.
Is it docker-compose or docker compose now?
Use docker compose with a space. Compose is now a plugin inside the Docker CLI, and the old standalone docker-compose binary written in Python is version 1, which reached end of life and is no longer shipped or supported. Any guide that tells you to install docker-compose separately predates that change. The compose file format itself did not break, so existing files keep working, but write your scripts, aliases and documentation against the plugin form or they will fail on a clean install.
Do I still need the version key at the top of the compose file?
No. The top level version field is obsolete and current versions of Compose ignore it, warning if it is present. It dates from the era when the file format was numbered and the tool chose behaviour from that number. Modern Compose reads the file as the current specification. Removing the line is safe and tidies up the warning noise on every command, which matters because real warnings get lost in a wall of ignorable ones.
Which Magento version does this compose file target?
Decide explicitly, then pin every image. Magento Open Source 2.4.9 became generally available on 12 May 2026 and Adobe's supported stack is PHP 8.5, Composer 2.10, MySQL 8.4 or MariaDB 12.3, OpenSearch 3, Valkey 9, RabbitMQ 4.3, Varnish 8 and nginx 1.30. If you are still on 2.4.8, that line covers PHP 8.3 and 8.4 with Elasticsearch 8. A compose file that quietly mixes services from both matrices will install and then fail in ways that look like application bugs.
What does depends_on actually guarantee?
Less than most people assume. By default it only controls start order, not readiness, so Magento can start before MySQL is accepting connections and the install fails on a refused connection. The fix is a health check on the database and search services plus a depends_on condition that waits for that health check to pass. This single change removes most of the flaky first-run failures that people work around by running the setup command twice.
How do I keep optional services out of a lightweight run?
Use Compose profiles. Tag Varnish, RabbitMQ, the mail catcher and anything else optional with a profile name, and they stay stopped unless you explicitly request that profile. One repository then serves a front end developer who wants four containers and a backend developer who wants eight, without maintaining two compose files. It is much better than commenting services out, because commented-out configuration rots and nobody notices until they uncomment it.
What is an override file and when should I use one?
Compose automatically merges a compose.override file on top of the base one, which lets you keep shared configuration committed and personal adjustments local. Exposed ports, extra debugging settings and an editor specific mount belong there. It is the clean answer to the situation where one developer needs the database on a different port because something else on their machine already uses it, and they currently solve it by editing the shared file and remembering not to commit.
What is the difference between down and stop?
Stop halts the containers and leaves them, so starting again is quick and everything is preserved. Down removes the containers and the project network. Neither deletes named volumes unless you add the volumes flag, which is the command that wipes your database and search indexes. Knowing that distinction saves real work, because people reach for the most destructive form out of habit and then wonder why they are reinstalling Magento every few days.
How do I connect Magento to the database and search services?
By service name, not localhost. Compose puts every service on a private network and registers each under its name, so the database host is db or mysql and the search host is opensearch. Inside a container, localhost means that container. This is the single most common configuration error when someone moves a working manual installation into Compose, because the old env.php still says 127.0.0.1 and Magento reports a connection refused with no hint about why.
Why does docker compose up fail with a port already allocated error?
Something on your host is already listening on that port, often another Magento project's stack, a locally installed MySQL, or a previous run that did not shut down. Map the service to a different host port in your override file, or stop the conflicting stack. On a machine that runs several projects, the durable answer is to stop publishing database and search ports at all, since you rarely need them from the host, and to route web traffic through a single shared reverse proxy that dispatches by hostname.
How do I run Magento CLI commands with Compose?
Use docker compose exec against the PHP service, running as the file-owning user rather than root. Running bin/magento as root is a habit worth breaking, because it leaves root-owned files in var and generated that the web server user can then no longer write, producing permission errors that appear minutes later and look unrelated. Wrap the whole invocation in a short script inside your repository so everyone on the team runs it the same way.
Does scaling a service help a local Magento environment?
Rarely for PHP, sometimes for consumers. Compose can start multiple instances of a service, which is genuinely useful for testing that queue consumers behave correctly when several run in parallel, a real source of production bugs. Scaling PHP FPM locally does little, because your bottleneck is a single developer's requests and your machine's memory, not concurrency. Treat scaling as a correctness testing tool locally, and leave real horizontal scaling to your production orchestrator.
How do I see what a service is doing when something breaks?
Read its logs before changing anything. Compose can follow the output of one service or all of them, which usually names the problem outright: a database rejecting a data directory created by a different major version, a search engine exiting on memory, or PHP FPM failing to start because of a syntax error in a mounted configuration file. Magento's own exception log is the second place to look, not the first, because a dead dependency never reaches Magento's error handling at all.






