Setting up a Magento 2 test instance on Docker

Published: 2021-01-22T22:00:00.000Z

Setting up a Magento 2 test instance on Docker

Magento currently doesn't provide an official docker container for its open source product (AFAIK). Getting it up and running took me a bit, so I hope this guide eases the pain a bit for you.

The setup I used was a bunch of docker containers without using docker-compose. Creating Dockerfiles and a docker-compose file from this guide should be pretty straight forward as well though.

Network

Magento requires a MySQL and an Elasticsearch instance. We'll these databases in separate containers. We want the main application container to have access to the database containers. We don't want expose them to anyone else though. So we'll create a separate Docker network:

$ docker network create \
  -o 'com.docker.network.bridge.host_binding_ipv4=127.0.0.1' \
  magento

The Magento container will only be available on the loopback interface (localhost) and not from the outside. You can remove the -o 'com.docker.network...' option to bind to 0.0.0.0 and expose the application container to others in your network (or the whole internet or whatever).

Databases

The main database for Magento is MySQL (or MariaDB). So let's spawn a container in our new network.

$ docker run \
  --detach \
  --network magento \
  --name magento_mysql \
  --env MYSQL_ROOT_PASSWORD=my-secret-mysql-pw \
  mysql:8.0

We'll also need to create a database for Magento to use (magento2 is the default Magento database name).

docker exec magento_mysql \
  sh -c 'echo "CREATE DATABASE magento2;" | mysql --password=my-secret-mysql-pw'

For full-text search, Magento uses Elasticsearch. Running this is just as simple as starting a MySQL database.

$ docker run \
  --detach \
  --network magento \
  --name magento_elasticsearch \
  --env "discovery.type=single-node" \
  docker.elastic.co/elasticsearch/elasticsearch:7.10.2

Main Application Container

As a basis for the main application container we'll use the official php docker image. Specifically the Apache httpd version. Note that at the time of writing Magento only supports PHP 7. So we need php:7.4-apache.

$ docker run \
  --publish-all \
  --detach \
  --network magento \
  --name magento_php \
  php:7.4-apache

Now let's drop into the container we just created and set up some stuff.

$ docker exec -it magento_php bash

First some changes in the httpd (or Apache) configuration are needed. The recommended configuration is described in the official docs). Let's stick to the minimum for this development instance though. First we need to enable Magento's .htaccess file to be evaluated.

# cat  <<__EOF__ >> /etc/apache2/sites-enabled/000-default.conf
<Directory "/var/www/html">
  AllowOverride All
</Directory>
__EOF__

Magento has pretty URLs, so we need mod_rewrite.

# a2enmod rewrite

Magento also needs a bunch of PHP extensions. A quick and dirty approach is using the Docker PHP extension installer. Setting it up and installing extensions with it is very easy.

# curl -L https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions \
  > /usr/local/bin/install-php-extensions
chmod u+x /usr/local/bin/install-php-extensions

Quite a few PHP extensions are also required (list from here). I just included all of them here. Most will be reported as being already installed.

# install-php-extensions \
  bcmath \
  ctype \
  curl \
  dom \
  gd \
  hash \
  iconv \
  intl \
  mbstring \
  openssl \
  pdo_mysql \
  simplexml \
  soap \
  xsl \
  zip \
  sockets

Running the Magento installer requires more then 128mb of memory, so I had to increase the limit. Me being lazy and this being a development instance, I just disabled it:

# cat /usr/local/etc/php/php.ini-development \
  | sed -Ee 's/^memory_limit = .*$/memory_limit = -1/' \
  > /usr/local/etc/php/php.ini

Now download the Magento archive here. Note that you need to create an account. But you can use a Mailinator email and none of the fields are validated. So no need to give Adobe any of your info for using "libre" software.

Once downloaded you can copy the zip into your container:

$ docker cp magento-ce-2.4.1_sample_data-2020-09-25-04-46-06.zip magento_php:/

Then extract the ZIP archive your container. Note that you should land in /var/www/html automatically, which is also the location where you want to have all your Magento files.

# apt-get update && apt-get install zip
# unzip -q /magento-ce-2.4.1_sample_data-2020-09-25-04-46-06.zip
# rm /magento-ce-2.4.1_sample_data-2020-09-25-04-46-06.zip

Now run the Magento installer (Note that Magento forces you to choose a password with both numbers and letters in it):

# ./bin/magento setup:install \
  --admin-firstname=testy \
  --admin-lastname=tester \
  --admin-email='magento-test@example.com' \
  --admin-user=something \
  --admin-password=super-secret \
  --base-url=http://127.0.0.1 \
  --db-host=magento_mysql \
  --db-password=my-secret-mysql-pw \
  --elasticsearch-host=magento_elasticsearch

Make sure to copy the admin path which is given in the last lines of output of this command.

By default Magento uses email-based, two-factor authentication for backend users. Since this is running on a development machine we don't really want to be sending emails. So we can disable this.

# ./bin/magento module:disable Magento_TwoFactorAuth

Lastly hand over all files to the www-data user, used by httpd:

# chown -R www-data:www-data .

The changes to the php.ini and the httpd configuration only take effect after httpd is restarted, which means restarting the container. So exit the container and run:

$ docker restart magento_php

And now you're all set up and ready.