This repository is a first building block for running Magento 2 in cloud (GCP, AWS, Azure).
A fast, secure and lightweight Docker setup.
Suitable for development, UAT and production environments.
Ensure you have the following requirements:
- Locally installed Docker (Docker Engine >=18.09 version)
- Docker has enough allocated resources:
- at least 10 GB of free disk space for hosting containers
- at least 2 CPU cores (4 CPU recommended)
- at least 4 GB of RAM (6 GB recommended)
When building or modifying a component, prioritize production first and override for your development needs via Docker build args and environment variables.
The project should compile for a production environment with little to no intervention to configuration.
Below you will an answer to most of the use cases, but if you spot a missing gap, feel free to create a PR and contribute to the document.
PHP-FPM allows you to configure most of the values via ENV variables which makes it handy to tune the same Docker image for both performance and development needs.
Following the DRY rule, the same Dockerfile should be used for all environments. However, some instructions like installation of Xdebug should not slip into production.
Therefore, multi-stage build will have Docker ONBUILD instructions explicitly needed to keep the resulting image similar but with small differences for each environment. The resulting Dockerfile will have the following view:
ARG PHP_FPM_IMAGE=php:7.2-fpm-alpine
ARG BUILD_ENVIRONMENT_IMAGE=magento2-php-fpm-production-onbuild
# Base image
FROM ${PHP_FPM_IMAGE} as magento2-php-fpm-base
RUN ... software installation for all environments
# Production image
FROM magento2-php-fpm-base as magento2-php-fpm-production-onbuild
ONBUILD ... production specific instructions
# Development image
FROM magento2-php-fpm-base as magento2-php-fpm-development-onbuild
ONBUILD ... development specific instructions
# Final image compiles based on $BUILD_ENVIRONMENT_IMAGE argument
# "Base image" + "Production image" instructions
# OR
# "Base image" + "Development image" instructions
FROM ${BUILD_ENVIRONMENT_IMAGE} as magento2-php-fpm
By default, php.ini and PHP-FPM are configured to run as a container for production use. They may still be optimal for a development purpose.
A snippet of php.ini file
; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
memory_limit = ${PHP_MEMORY_LIMIT}
To redefine PHP_MEMORY_LIMIT value (or any other), set it in docker-compose.yaml or .env file
MAGENTO_RUN_MODE=development
PHP_DISPLAY_ERRORS=1
PHP_OPCACHE_CONSISTENCY_CHECK=1
PHP_MEMORY_LIMIT=4G
To change PHP version, modify the PHP_FPM_IMAGE
argument of the build section. Currently, 7.2, 7.3 and 7.4 versions supported
version: "3.7"
services:
php-fpm:
build:
context: .
dockerfile: ./build/php-fpm/Dockerfile
args:
PHP_FPM_IMAGE: "php:7.4-fpm-alpine"
The Magento software recommends MariaDB. It can be replaced with MySQL or Percona based on eventual production setup.
MariaDB version of the config file by default has a low amount of resource set.
In order to speed things up for local development my.cnf has innodb_buffer_pool_size
set to 1G
.
You may need to adjust it based on your database size and machine capacity.
slow_query_log
is enabled to log queries that are slower than 2 seconds.
To watch the file for changes, you may use the following command:
docker exec -it $(docker ps -f name=mysql -q) tail -f /var/log/mysql/mariadb-slow.log
Due to security reason, containers running in production must not use systems ports (0-1023).
Nginx runs under the same UID = 1000, and GID = 1000 as PHP-FPM and listens on port 8080
.
-
To run local environment without FPC, open the website directly on http://magento2.local:8080 or change the Nginx port mapping to
80:8080
in docker-compose.yaml as shown belowversion: "3.7" services: varnish: ports: - "6081" nginx: ... ports: - "80:8080"
-
Changing anything in Nginx configuration requires a restart
docker exec -it $(docker ps -f name=nginx -q) nginx -s reload
Due to security reason, containers running in production must not use systems ports (0-1023).
Varnish listens on its default port 6081
.
To run the local environment with FPC on, ensure you have the following configuration in docker-compose.yaml as shown below
version: "3.7"
services:
varnish:
ports:
- "80:6081"
nginx:
...
ports:
- "8080"
Elasticsearch is a default search engine for Magento starting with version 2.3. MySQL search engine support is removed in Magento 2.4
For simplicity' sake and to keep resource consumption low, Elasticsearch runs in a single-node configuration.
The same instance of Redis may be used to store user sessions and cache.
Connecting to Redis is pretty straight-forward, from your command line run
docker exec -it $(docker ps -f name=redis -q) redis-cli
To clear all the data, use the following command
docker exec -it $(docker ps -f name=redis -q) redis-cli FLUSHALL
Due to security reason, containers must not run under
root
Due to the nature of cron
, it runs only under root
user and not a good fit for the containerized solution. Supercronic was designed specifically for containers to replace standard cron. Many features come out of the box, including graceful shutdown and logging to STDOUT.
Emails configured via sendmail
command in php.ini file
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
; http://php.net/sendmail-path
sendmail_path = sendmail -t -i -S ${PHP_SENDMAIL_PATH}
External email providers:
- AWS SES
- Sendinblue
- Sendgrid
- MailHog (development setup)
PHP_SENDMAIL_PATH=mail:1025
It is known Xdebug can kill the performance and make your setup work slow. It also drastically degrades the speed of composer install
command, so it's recommended to turn it off during initial project import and for Frontend work.
To turn Xdebug on in docker-compose.yaml change BUILD_PHP_XDEBUG_ENABLE
to 1
and ensure you have BUILD_PHP_XDEBUG_REMOTE_HOST
defined
services:
...
php-fpm:
build:
...
args:
BUILD_PHP_XDEBUG_ENABLE: 1
BUILD_PHP_XDEBUG_REMOTE_HOST: "host.docker.internal."
then rebuild the container
docker-compose up --build
To enable it locally, set corresponding values in .env
NEWRELIC_ENABLED=1
NEWRELIC_LICENSE=your license goes here
NEWRELIC_APPNAME="your awesome project name"
uncomment New Relic agent in docker-compose.yaml
services:
...
newrelic-agent:
image: newrelic/php-daemon
restart: always
networks:
- backend
start PHP-FPM, CRON and New Relic containers
-
Follow these steps to setup the project
-
Ensure you have 'app/etc/config.php' file with
modules
andscopes
configurations
<?php
return [
'modules' => [
'Magento_AdminAnalytics' => 1,
...
],
'scopes' => [
'websites' => [
'admin' => [
'website_id' => '0',
'code' => 'admin',
'name' => 'Admin',
'sort_order' => '0',
'default_group_id' => '0',
'is_default' => '0',
],
'base' => [
'website_id' => '1',
'code' => 'base',
'name' => 'Main Website',
'sort_order' => '0',
'default_group_id' => '1',
'is_default' => '1',
],
],
'groups' => [
0 => [
'group_id' => '0',
'website_id' => '0',
'name' => 'Default',
'root_category_id' => '0',
'default_store_id' => '0',
'code' => 'default',
],
1 => [
'group_id' => '1',
'website_id' => '1',
'name' => 'Main Website Store',
'root_category_id' => '2',
'default_store_id' => '1',
'code' => 'main_website_store',
],
],
'stores' => [
'admin' => [
'store_id' => '0',
'code' => 'admin',
'website_id' => '0',
'group_id' => '0',
'name' => 'Admin',
'sort_order' => '0',
'is_active' => '1',
],
'default' => [
'store_id' => '1',
'code' => 'default',
'website_id' => '1',
'group_id' => '1',
'name' => 'Default Store View',
'sort_order' => '0',
'is_active' => '1',
],
],
]
];
-
Prepare access keys to Magento 2 and optionally to your GitHub account by copying auth.json.sample to
auth.json
and replacing credentials.auth.json
won't be added to the final image nor leave a trace in docker build history -
Run
make
to build imagesmake
-
Now you're ready to publish them into a cloud of your choice