Skip to content

Build a docker container for my Magento store

Docker is a powerful tool that can help developers streamline their development process and improve consistency across different environments. In this tutorial, we will walk through the steps to containerize a Magento 2 project.

Step 1: Prepare your application

Before you begin, you will need a valid app/etc/config.php with a few specific settings. Specifically, the scopes and themes settings.

For our purposes, we really only need the scopes and themes key, however you can include whatever else you think is useful that is applicable to all of your environments.

These settings must be added to your config.php ahead of time in order for you to containerize Magento 2.

TIP

If are migrating to Mappia and you have a running store already:

bash
bin/magento app:config:dump scopes themes

DANGER

Do not run bin/magento app:config:dump in production. You will lock the admin system configurations and someone will eventually be upset at you.

You should create a local version of your production application and run the command there.

INFO

Be aware that by moving the scopes and themes into app/etc/config.php, you are preventing business users from adding new stores in the admin panel.

Below is an example of what a sample config.php should look like when you are done.

php
<?php
return [
    'modules' => [
        'Magento_Store' => 1,
        ...
        'Magento_Wishlist' => 1,
        'Magento_WishlistAnalytics' => 1,
        'Magento_WishlistGraphQl' => 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' => 'default-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' => 'Default 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' => 'English',
                'sort_order' => '0',
                'is_active' => '1',
            ],
        ],
    ],
    'themes' => [
        'adminhtml/Magento/backend' => [
            'parent_id' => null,
            'theme_path' => 'Magento/backend',
            'theme_title' => 'Magento 2 backend',
            'is_featured' => '0',
            'area' => 'adminhtml',
            'type' => '0',
            'code' => 'Magento/backend',
        ],
    ]
];

Step 2: Setup

Next, install Docker on your machine if you haven't already done so. Once Docker is installed, we need to create a Dockerfile to define the image that we will use to run our Magento 2 application.

You can put this Dockerfile anywhere in your project, but for a sane default, the docker folder is a nice organizational folder for all docker related artifacts.

bash
mkdir -p docker
# We want to ignore the docker folder to allow faster rebuilds.
touch .dockerignore && echo "docker" >> .dockerignore
touch docker/Dockerfile

The Dockerfile should contain the following code:

docker
ARG BASE_IMAGE="mappia/magento-php:v0.7.1-alpine8.4"

FROM ${BASE_IMAGE}

WORKDIR /var/www/html

COPY ./ .

## Install Composer Dependencies
## Make sure that the composer auth.json file isn't stored in a temporary layer
RUN --mount=type=secret,id=composer.auth,target=/root/.composer/auth.json,required \
      composer install --no-dev --no-ansi --no-interaction --no-progress --no-suggest

RUN php bin/magento setup:di:compile &&  \
    composer dump-autoload -o --classmap-authoritative \
    && php bin/magento setup:static-content:deploy -f --theme $YOUR_THEME_HERE --theme Magento\backend \
    && find var pub/media -type f -exec chmod g+w {} + \
    && find var pub/media -type d -exec chmod g+ws {} + \
    && chown -R :www-data var pub/media \ 
    && chmod u+x bin/magento

TIP

Make sure you select the correct php version for your intended Magento version.

What does this Dockerfile mean?

Let's break down what's going on:

docker
ARG BASE_IMAGE="mappia/magento-php:v0.7.1-alpine8.4"

FROM ${BASE_IMAGE}

This Dockerfile uses the official Mappia Magento 2 PHP images as a base, but it allows you to swap out the base image to whatever you would like. This will be useful when we decide to switch between the cli and fpm bases.

TIP

The prebuilt Mappia images are base images which should work for most Magento 2 stores. However, you can replace them with your own image if you have other requirements or dependencies.

Putting the pieces in place

The next entries put your application into the /var/www/html folder in the container.

docker
WORKDIR /var/www/html

COPY ./ .

Installing dependencies

Next, we install dependencies, but importantly, we use an uncached env argument (composer.auth) for the composer authentication so that we don't accidentally store license keys in the final image.

docker
## Install Composer Dependencies
## Make sure that the composer auth.json file isn't stored in a temporary layer
RUN --mount=type=secret,id=composer.auth,target=/root/.composer/auth.json,required \
      composer install --no-dev --no-ansi --no-interaction --no-progress --no-suggest

Compilation

We compile the app.

RUN php bin/magento setup:di:compile &&  \

Improving Composer Performance

bash
    composer dump-autoload -o --classmap-authoritative \

Static-content deploy

bash
    && php bin/magento setup:static-content:deploy -f --theme $YOUR_THEME_HERE \

File Permissions

Finally, we set file permissions for the application runtime.

bash
    && find var pub/media -type f -exec chmod g+w {} + \
    && find var pub/media -type d -exec chmod g+ws {} + \
    && chown -R :www-data var pub/media \ 
    && chmod u+x bin/magento

Step 3: Build the images

Mappia requires two images to operate effectively. Firstly, the cli image, which is a php image without fpm, and secondly fpm which is the image that contains php-fpm which will ultimately process requests.

You can build these images using the docker cli:

bash
docker build . -f docker/Dockerfile -t my-magento2-image:cli-v0.7.1 \
    --secret id=composer.auth,src=auth.json \
    --build-arg BASE_IMAGE=mappia/magento-php:v0.7.1-alpine8.4 

docker build . -f docker/Dockerfile -t my-magento2-image:fpm-v0.7.1 \
    --secret id=composer.auth,src=auth.json \
    --build-arg BASE_IMAGE=mappia/magento-php:v0.7.1-alpine8.4

Step 4: Publish the images

Assuming that your images built successfully, you're now ready to publish these images to your registry of choice!

This process typically looks like:

bash
docker login $REGISTRY_NAME
docker push my-magento2-image:fpm-v1.0.0

Next Steps

You are now ready to deploy with Mappia! You can now proceed to: