Running Magento2 with Docker Compose: A Step-by-Step Guide

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.

Yuvraj RauljiYuvraj RauljiRaulji Technologies Feb 7, 2025 4 min read Updated Jun 1, 2026 Intermediate
Quick Answer

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:

bash
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

yaml
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:

bash
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

bash
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:

bash
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:

Storefront: http://localhost/
Admin Panel: http://localhost/admin

Step 8: Manage Magento2 with Docker Compose

Restart Containers:
bash
Copy
docker-compose restart
Stop Containers:
bash
Copy
docker-compose down
Run Magento CLI Commands Inside the Container:
bash
Copy
docker exec -it magento_app bin/magento cache:flush
docker exec -it magento_app bin/magento indexer:reindex
View Logs:
bash
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:

yaml
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:

yaml
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

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.

Yuvraj Raulji

Yuvraj Raulji

Verified expert

Founder

Founder of Raulji Technologies with expertise in enterprise eCommerce solutions. Specialized in Magento 2, Shopify, and headless commerce architecture. Driving growth through CRO, SEO, and performance engineering. Helping businesses turn technology into measurable revenue.
Share
Ready When You Are

Turn your store into a revenue machine

Our team has helped 150+ brands scale with Magento, Shopify and AI-powered solutions.

Get a Free Growth Plan
Stay in the loop

Get our latest insights by email

Practical eCommerce, Magento, Shopify and AI growth strategies. No spam, unsubscribe any time.

By subscribing you agree to our Privacy Policy.

Book Free Consultation

We're Trusted By Businesses Across The Globe

Discover why 100+ global brands choose Raulji Technologies for AI-driven eCommerce, web development, and digital transformation, scaling their digital growth with innovation, performance, and trust.

100+
Brands Served
150+
Projects Delivered
12+
Years Experience
4.9
Average Rating
Clutch 5.0

Clutch Verified Profile

Rated 5.0 by verified clients on Clutch for Magento, Shopify, and AI-driven digital transformation.

View Clutch Profile
DesignRush 5.0

DesignRush Verified Profile

Listed and reviewed on DesignRush as a top eCommerce and web development agency.

View DesignRush Profile
Google 5.0

Google Verified Profile

Reviewed by clients on Google across India, the Gulf, and worldwide for delivery and support.

Read Google Reviews