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. 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, you can use bin/magento app:config:dump
to generate these values. For our purposes, we really only need the scopes
and themes
key, however you can include whatever else you think is useful cross-environment.
Be aware that by moving the scopes and themes into app/etc/config.php
, you will be preventing business users from adding new stores in the admin panel. Consider this carefully.
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.
Below is an example of what a sample config.php
should look like.
<?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.
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:
ARG BASE_IMAGE="mappia/magento-php:8.1-fpm-alpine-v0.4.0"
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
Let's break down what's going on:
Setting the stage
ARG BASE_IMAGE="mappia/magento-php:8.1-fpm-alpine-v0.4.0"
FROM ${BASE_IMAGE}
This Dockerfile uses the official Graycore 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 Graycore 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.
Putting the pieces in place
The next entries put your application into the /var/www/html
container.
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.
## 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
composer dump-autoload -o --classmap-authoritative \
Static-content deploy
&& php bin/magento setup:static-content:deploy -f --theme $YOUR_THEME_HERE \
File Permissions
Finally, we set file permissions for the application runtime.
&& 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:
docker build . -f docker/Dockerfile -t my-magento2-image:cli-v1.0.0 \
--secret id=composer.auth,src=auth.json \
--build-arg BASE_IMAGE=mappia/magento-php:8.1-cli-alpine-0.4.0
docker build . -f docker/Dockerfile -t my-magento2-image:fpm-v1.0.0 \
--secret id=composer.auth,src=auth.json \
--build-arg BASE_IMAGE=mappia/magento-php:8.1-fpm-alpine-0.4.0
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:
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:
- Provision your infrastructure
- Set up a CI Pipeline (TODO)
- Deploy to an existing Kubernetes Cluster