PHP, MySQL, Nginx, Redis, Elasticsearch: Magento 2 needs a lot. Learn how Docker containers organize it all to simplify local development. Learn how each.
On this page
Magento2 is a robust eCommerce platform, but setting up a local development environment with its many dependencies – PHP, MySQL, Nginx, Redis, Elasticsearch, and more – can feel like assembling a jigsaw puzzle. Enter Docker, the ultimate tool for simplifying Magento2 development.
At Raulji Technologies, we rely on Docker to streamline our Magento2 workflows. As Yuvraj Raulji, our Magento2 expert, explains: “Docker simplifies Magento2 setup by using pre-configured containers, reducing compatibility issues and speeding up development.” In this guide, we’ll break down the essential Docker containers needed to run Magento2 efficiently and how they work together.
What Are Docker Containers?
Think of Docker containers as self-contained boxes that include everything an application needs to run – code, runtime, dependencies, and system libraries. Instead of manually installing software, Magento 2 runs inside multiple containers, each handling a specific service like PHP, MySQL, or Redis.
Using Docker Compose, we can define and manage these containers in a single docker-compose.yml file, creating a complete Magento2 development environment with just a few commands.
Magento2 Docker Containers Overview
Magento2 requires several key services to function properly. Below are the essential containers you’ll need:
1) Magento2 Application Container
This is the heart of your Magento2 setup. It runs the PHP codebase and serves the application using Apache or Nginx.
- Purpose: Hosts the Magento2 application.
- Image: Typically uses a PHP + Apache/Nginx image.
- Key Features:
- Mounts the Magento source code for development.
- Connects to the MySQL database and Redis for caching.
- Example Service: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”
2) Database (MySQL/MariaDB) Container
This container stores all your Magento data – products, orders, customers, and more.
- Purpose: Manages the database for Magento2.
- Image: Uses MySQL 5.7 or MariaDB.
- Key Features:
- Stores and retrieves data for the Magento application.
- Configurable with environment variables.
- Example Service: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”
3) Elasticsearch Container (For Magento 2.4+)
Magento2.4+ requires Elasticsearch for advanced search functionality.
- Purpose: Handles indexing and searching for Magento2.
- Image: Uses Elasticsearch 7.9.3 or later.
- Key Features:
- Powers fast and accurate search results.
- Configurable for single-node or clustered setups.
- Example Service: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”
4) Redis Container (Optional, for Caching)
Redis is used to store Magento’s cache and session data, improving performance.
- Purpose: Enhances performance by reducing database load.
- Image: Uses the latest Redis image.
- Key Features:
- Stores cache and session data in memory.
- Highly configurable for different caching strategies.
- Example Service:redis:
image: redis:latest
container_name: magento_redis
restart: always
ports:
– “6379:6379”
5) Varnish Container (Optional, for Full-Page Caching)
Varnish is a powerful caching tool that improves page load speed.
- Purpose: Caches full-page responses to reduce server load.
- Image: Uses Varnish 6.5 or later.
- Key Features:
- Sits between the web server and users.
- Dramatically improves performance for high-traffic stores.
- Example Service:varnish:
image: varnish:6.5
container_name: magento_varnish
depends_on:
– app
ports:
– “6081:6081”
6) Mailhog Container (For Email Testing)
Mailhog catches outgoing emails from Magento, making it perfect for testing.
- Purpose: Captures emails sent by Magento for testing purposes.
- Image: Uses the Mailhog image.
- Key Features:
- Prevents test emails from reaching real customers
- Provides a web interface to view captured emails.
- Example Service:mailhog:
image: mailhog/mailhog
container_name: magento_mailhog
ports:
– “1025:1025”
– “8025:8025”
How These Containers Work Together
When you start Magento2 with Docker, the Magento application container interacts with:
- MySQL for data storage
- Elasticsearch for search functionality.
- Redis for caching.
- Varnish for full-page caching.
- Mailhog for email testing.
Each service runs in its own isolated container but communicates internally using Docker networks. This setup ensures that your Magento2 environment is clean, consistent, and easy to manage.
Starting Magento2 with Docker
- Define Your Containers: Create a docker-compose.yml file with the services you need.
- Start the Containers: Run the following command:docker-compose up -d
- Stop the Containers: When you’re done, stop the containers with:docker-compose down
Final Thoughts
Using Docker for Magento2 development simplifies dependency management, improves performance, and provides a clean, repeatable environment. At Raulji Technologies, we use Docker to optimize our Magento2 development process, and we highly recommend it to every Magento developer.
Yuvraj Raulji’s Pro Tip: “Start with the essential containers (PHP, MySQL, Redis) and add others like Elasticsearch and Varnish as your store grows.”
What’s Next?
Stay tuned for our upcoming guides and 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.
Should I still run an Elasticsearch container for Magento 2.4?
Not for a new build. Adobe's supported version matrix for Magento 2.4.9, which reached general availability on 12 May 2026, lists OpenSearch 3 and does not list Elasticsearch at all. The 2.4.8 line is the last one that still shows Elasticsearch 8 alongside OpenSearch. Existing Elasticsearch environments keep working for now, but they are on a deprecated path, so any container stack you build today should use OpenSearch. The Magento configuration differs only in the engine you select and the port you point it at.
Is the Redis container still the right cache service?
For 2.4.8 and earlier, yes. For 2.4.9 Adobe's supported matrix lists Valkey 9 rather than Redis. Valkey is the community fork that continued from Redis's last open source release, and it speaks the same protocol, so Magento's existing cache, session and page cache backends work against it with no code changes. In practice you change the image name and the version pin. If you are planning an upgrade to 2.4.9, swapping the container now is a low risk change to get out of the way early.
What is the minimum set of containers a Magento 2 environment needs?
Four: a PHP FPM container running the application, a web server such as nginx in front of it, a database container running MySQL or MariaDB, and a search container running OpenSearch. Magento will not complete installation without a search engine, which surprises people coming from Magento 1. Everything else, meaning the cache, full page cache, message broker and mail catcher, is optional for a bare storefront but rapidly becomes necessary once you are testing real behaviour rather than just proving the site loads.
Why are PHP and nginx separate containers?
Because a container should run one process, and they scale and restart independently. nginx serves static files and terminates connections, then hands PHP requests to PHP FPM over a network socket. Splitting them means you can rebuild the PHP image with a new extension without touching the web server, and you can put a second nginx configuration in front of the same application for testing. It also mirrors how real Magento hosting is arranged, so what you debug locally resembles what runs in production.
What does the Varnish container actually do?
It sits in front of nginx and serves cached full pages from memory, so a repeat request for a category page never reaches PHP at all. Magento ships built-in Varnish integration and can generate the VCL configuration for you. Adobe's supported matrix for 2.4.9 lists Varnish 8. Many developers omit it locally because it hides code changes behind a cache and complicates debugging, then discover cache invalidation bugs only on staging. Running it locally behind a toggle is the better compromise.
Do I need a RabbitMQ container?
Only if you use Magento's asynchronous features, which increasingly you do. Message queues drive bulk API operations, asynchronous order placement, inventory updates and several Adobe Commerce features. Without a broker, consumers fall back to database queues that work but do not reflect production behaviour. Adobe's 2.4.9 matrix lists RabbitMQ 4.3. If your project runs any custom consumer, add the container early, because queue related bugs behave very differently when the broker is present.
What is Mailhog for and is it still maintained?
It captures every email your local Magento sends and shows it in a web interface, so order confirmations and password resets never leave your machine and never reach a real customer. That safety property is the real reason to run it. Mailhog itself is no longer actively developed, and many teams have moved to Mailpit, which is a drop-in replacement with a modern interface and active maintenance. Either way, the principle stands: a development environment should be physically incapable of emailing real people.
How do containers find each other inside Docker Compose?
Compose creates a private network for the project and registers each service under its service name. So Magento connects to the host db rather than to an IP address, and to opensearch on its own port. That is why you configure the database host as a service name during installation instead of localhost. Localhost inside a container means that container, not your machine, which is the single most common configuration mistake when people move a working manual setup into Docker.
What is the difference between a volume and a bind mount?
A bind mount maps a folder on your machine into the container, which is how your source code gets in and how your editor changes take effect immediately. A named volume is storage Docker manages itself, which is where database files and search indexes belong because they need speed and do not need to be edited by hand. Putting a database on a bind mount is a classic performance mistake. Putting your source code in a named volume means you cannot edit it. Use each for what it is good at.
Why does the OpenSearch container keep dying?
Nearly always memory or kernel settings. The service reserves a Java heap at startup and exits if the container cannot supply it, so an under-provisioned Docker allocation kills it silently. It also requires the host's vm.max_map_count to be raised above the default on Linux and on Docker Desktop's virtual machine. Check the container logs rather than the Magento error, because Magento simply reports that it cannot reach the search engine, which sends people looking in entirely the wrong place.
How much of this stack do I need for a simple theme change?
Less than you think. PHP, nginx, the database and OpenSearch are enough to render and style a storefront. Varnish will actively get in your way by caching the pages you are editing, and the message broker is irrelevant to front end work. Compose profiles let you define the optional services once and start them only when you need them, so the same repository serves a designer running four containers and a backend developer running eight.
Should each project have its own container stack?
Yes. That is the main reason to containerise in the first place. One client on 2.4.6 with Elasticsearch and PHP 8.2 can coexist with another on 2.4.9 with OpenSearch 3 and PHP 8.5, because neither installs anything on your machine. Give each project its own compose project name so container names and networks do not collide, and stop the stacks you are not using so they are not competing for memory. This is what makes agency work with mixed Magento versions manageable.






