Developing With Magento Using An Alpine Docker Cluster

June 7, 2019
Jarett Ehas

Introduction

Set up an easy to use local Magento development environment with JetRails’ custom Docker containers. This project allows for an out of the box deployment of any version of Magento utilizing tools like Docker Compose, Docker Sync, and our very own MageRepo.

We built Docker containers that can run any version of Magento. We chose Alpine Linux to be our base image for our containers, because it is lightweight and fast.

Disclaimer: The Docker containers referenced in this article were build for development purposes only and should NOT be used in production. The source code to the Docker containers are licensed under the MIT LICENSE and comes with no warranty. Use at your own risk.

Software dependencies

There are some requirements that are needed to run a Docker environment on your local development machine. In order to spin up a Magento development cluster on your local machine, you will need to install Docker and Docker Compose. Additionally, you may want to install Docker Sync if your local machine is not running Linux. For the remainder of this article, we are going to focus on running Docker on macOS.

  • Installation instructions for Docker can be found here.
  • Installation instructions for Docker Compose can be found here.
  • Installation instructions for Docker Sync can be found here.

If you are running Docker on macOS or Windows, then utilizing a tool like Docker Sync is almost a requirement. Docker Sync is an open-source project that can be found on their GitHub repository. Installing Docker Sync will allow us to utilize Docker to it’s full potential. This is extremely important when developing for Magento because Magento alone is heavily reliant on the file system. Docker Sync isn’t as necessary if you are on Linux because Docker volume performance is greater.

Setting up project

When setting up a working environment for your project, consider the following file structure:

$ tree -L 1

.
├── docker-compose.yml
├── docker-sync.yml
├── public_html

1 directories, 2 files

The docker-sync.yml file will contain the following:

version: "2"

syncs:
    app-sync:
        src: "./public_html"
        sync_userid: 1000
        sync_groupid: 1000

We are setting up a volume sync endpoint called app-sync. We will then reference this endpoint in our docker-compose.yml file. An example compose file for a Magento 2 deployment looks like the following:

version: "2"

volumes:
    database:
    app-sync:
        external: true
networks:
    default:
        driver: bridge
        ipam:
            config:
                - subnet: "192.168.7.0/28"
services:
    php-fpm:
        image: jetrails/magento-alpine:php-fpm-7.1
        volumes:
            - app-sync:/var/www/html:rw
        networks:
            default:
                aliases:
                    - php-fpm.docker.internal
        links:
            - mysql
            - redis
    php-cli:
        image: jetrails/magento-alpine:php-cli-7.1
        volumes:
            - app-sync:/var/www/html:rw
        networks:
            default:
                aliases:
                    - php-cli.docker.internal
        links:
            - mysql
            - redis
    php-cron:
        image: jetrails/magento-alpine:php-cron-7.1
        volumes:
            - app-sync:/var/www/html:rw
        networks:
            default:
                aliases:
                    - php-cron.docker.internal
        links:
            - mysql
            - redis
    nginx:
        image: jetrails/magento-alpine:nginx
        volumes:
            - app-sync:/var/www/html:rw
        networks:
            default:
                aliases:
                    - nginx.docker.internal
        environment:
            - VERBOSE=true
            - MAGENTO_VERSION=2
        links:
            - php-fpm
        ports:
            - "443:443"
    mysql:
        image: jetrails/magento-alpine:mysql
        volumes:
            - database:/var/lib/mysql
        networks:
            default:
                aliases:
                    - localhost
                    - mysql.docker.internal
        environment:
            - MYSQL_ROOT_PASSWORD=magento
            - MYSQL_USER_NAME=magento
            - MYSQL_USER_PASSWORD=magento
            - MYSQL_DATABASE=magento
    varnish:
        image: jetrails/magento-alpine:varnish
        networks:
            default:
                aliases:
                    - varnish.docker.internal
        links:
            - nginx
        ports:
            - "80:80"
    redis:
        image: jetrails/magento-alpine:redis
        networks:
            default:
                aliases:
                    - redis.docker.internal

For the remainer of this article, we will assume that the above compose file is used. Whilst the redis and varnish containers are attached into our cluster, they are not actively caching anything. This needs to be configured seperatly; we will not go over this process in this article.

Some more sample compose files for running Magento 1 and Magento 2 can be found here.

The public_html directory will contain Magento’s source code and is the directory that is used for our app-sync volume endpoint. For this reason, it is required to exist. We have a CLI tool that can aid in downloading any Magento release. It is discussed in further detail in the Downloading Magento with MageRepo section of this article.

Downloading with MageRepo

MageRepo is a tool built by the JetRails team to make it easier to download and install any version of Magento for development purposes. Any community edition starting from 1.0.0 all the way to the latest can be installed at will. Using our MageRepo Command Line Interface (CLI) Tool makes this even easier. On macOS, this can be installed using Homebrew. For enterprise versions of Magento, there is an authorization process that is required to distribute these releases.

Running the command below will tap our MageRepo repository with brew. After tapping this repository, you can then install formulas that are contained within it.

$ brew tap magerepo/tap
$ brew install magerepo

Working with magerepo is extremely simple. Running magerepo -h from your terminal will output the following help information.

A sample command to download the latest Magento 2 release, extract it into the public_html folder and then delete the archive looks like this:

$ magerepo release -e ce -r 2.x -c -d -x public_html

More information about the different ways of installing our CLI tool and working with it can be found here. Additional information about working with the MageRepo RESTFUL API can be found in the aforementioned article.

Cluster setup and teardown

Now that everything is good to go, we can start with our deployment process. You can spin up the development cluster using the following sequence of commands.

$ docker-sync start
$ docker-compose up -d

Shutting them down is just as easy.

$ docker-compose down
$ docker-sync stop
$ docker-sync clean # only if not starting again

The whole process (spinning up and then down) will look like the following:

When the cluster is up, you can access the contents of public_html on localhost:80.

Attach CLI container on demand

When working with Magento, it is very common to use their magento CLI binary. A CLI container can be spun up and attached to your cluster by running the following command:

$ docker-compose run php-cli

Once you are done with the shell, you can simply exit it.

Override configuration files

At some point in your development process, you may need to override some files that are baked into our images. If you want to actively change those values while the cluster is up and running, then a new volume endpoint might be the way to go. On the other hand, if you would like to override a single config file, it might be better to just mount it using Docker’s native method. For the sake of example, lets assume you want to override the Varnish config that lives on the varnish container. Lets also assume that this new config file is located at conf/default.vcl relative to your project directory. Consider the following modified snippet from the compose file:

varnish:
    image: jetrails/magento-alpine:varnish
    volumes:
        - ./conf/default.vcl:/etc/varnish/default.vcl
    networks:
        default:
            aliases:
                - varnish.docker.internal
    links:
        - nginx
    ports:
        - "80:80"

This will override the config file found in /etc/varnish/default.vcl on the varnish container.

Supported PHP versions

At the time of writing this article, we support the following PHP versions for cli, cron, and fpm containers:

  • PHP 5.6
  • PHP 7.1
  • PHP 7.2

Every Magento release is able to run on one or more of the above listed versions. When authoring your custom composer file, please take into account Magento’s compatibility with the PHP versions listed above.

Additional resources

Our Docker images are publicly published at jetrails/magento-alpine on Docker Hub. Our jetrails/docker-magento-alpine Github repository is also publicly available. We would appropriate any feedback and pull requests that come in. Issues regarding the containers can also be deligated to our Github repository’s issue management system.

Information about customizing the containers using environment variables along with a full list of tags that are published and available for use can be found at the resources stated above.