Developing with Docker, PHP, Apache and MariaDB

Written by Vincent Bruijn

Oh Docker…

It took me quite some time before I got on the Docker boat (pun intended), but since last few weeks, I’m totally in. This article describes a way to set up a MAMP development environment with Docker, Apache, PHP and MariaDB (i.e. MySQL).

I was cleaning up my laptop as I had only 6Gb left on my 2013 MacBook Pro. I had both Macports and Homebrew installed… Why? I can’t recall actually. But I found out both use an aweful lot of diskspace. I deleted both and wrote a docker-compose.yml with about 50 SLOC that’s easier to maintain and easy to set up.

Docker for MAMP development

I was fed up with dealing with a lot of administration with regard to running MacPorts and Homebrew: clean up, update, upgrade… Besides they took up a lot of disc space and I regularly had to clean up my MacBook in order to retain enough room for other applications.

I had heard about Docker a couple of years ago but I never had used it. I thought the learning curve was too steep, but that wasn’t actually true. I learned Docker from Nana. She has a great course on YouTube which lasts about 3 hours (2 hours on 1.5 the speed) digging deep into all features of Docker. Her video, and a couple of results from Google, say the better tutorial blog post on Docker, resulted in the following setup and configuration.

It took me quite some time before I got on the Docker boat 🚢

Basically I have a subdirectory in my ~/Sites directory which contains all Docker configuration. It uses Docker Compose which is basically a Yaml file with all we need. I copied over the Apache configuration file from the former setup and only had to change all directory paths which map to the volumes directive in the Docker configuration.

<VirtualHost *:80>
  DocumentRoot "/var/www/html/"
  ServerName localhost
  # before: /Users/vincentb/Sites/
  # after:
  <Directory "/var/www/html">
    Options FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all

With one command the compose file starts up three Docker containers. One running Apache with Php74 and one with MariaDB, the real open source alternative to MySQL and one with PhpMyAdmin.

version: '3'

    image: php74:latest
      - '80:80'
      - /Users/vincentb/Sites/_docker/apache:/etc/apache2/sites-enabled
      - /Users/vincentb/Sites:/var/www/html
      - /Users/vincentb/Sites/_docker/php/php.ini:/usr/local/etc/php/php.ini
      - mariadb
      - 'ax710.test:'
      # - 'some-other-host.test:'
      - dev-env
    image: phpmyadmin:latest
      - 8080:80
      - PMA_HOST=mariadb
      - mariadb
      - /Users/vincentb/Sites/_docker/php/php.ini:/usr/local/etc/php/php.ini
      - dev-env
    image: mariadb:latest
    restart: always
      MYSQL_ROOT_PASSWORD: 'secret'
      MYSQL_USER: 'vincentb'
      MYSQL_PASSWORD: 'secret'
      MYSQL_DATABASE: 'vincentb'
      - mysqldata:/var/lib/mysql
      - 3306:3306
      - dev-env
  mysqldata: {}
  dev-env: {}

As you can see I also have a php.ini file outside of the docker to persist PHP-specific configuration. Also, to persist the MariaDB databases, I’ve configured a Docker volume in order to keep my databases after a turn down of the container.

One could do the same with the configuration file of phpmyadmin: store it in the _docker directory and map it to a path in the container.

├── apache
│   └── httpd-vhosts.conf
├── docker-compose.yml
├── php
│   └── php.ini

I use this setup for websites I develop for clients, which are usually WordPress websites. Be aware that since WordPress is running in the PHP-Apache container, it should use the Docker runtime host for the MariaDB to connect to the database. In this case that is plain mariadb as you can reference the one container from the other when they’re configured in one compose file.

From a wp-config.php:

/** MySQL hostname */
define('DB_HOST', 'mariadb');

If I would want to switch PHP version, that would only be a matter of changing the docker-compose.yml file and let Docker do the job, instead of needing to build from source using Xcode command line tools and wait for brew or port to finish.

In conclusion: Docker helped me save disk space and administration time I would otherwise spend using brew or port. It’s also more clear where data lives and although Docker needs a cleanup once in a while too, I do not get bloated with many source packages which sleep somewhere on my disk. I’m happy with this setup and I hope you can benefit from this article.