Quite late to the game: when I got a new Mac last Summer, I thought it’s the perfect moment to install Docker for local development of my spare time web projects – instead of continue using MAMP with its built-in Apache, MySQL, and PHP stack. One can «just install Docker Desktop, spin up a LAMP stack – and get going, right?» Well… little did I know what it means to get a project running with Docker!
So I wen’t down quite a rabbit hole to figure it out.

Let me share the results with you here. And please note: this is for a one-to-one replacement of MAMP on macOS for local web development, not how to deploy a Docker solution to a production environment.

P.s.: for this post, a customised WordPress blog project will be used to demonstrate the migration of such from MAMP to Docker. The reason is, that the tech-stack for WordPress is what I am most used to.

TL;DR – Docker instead of MAMP on a Mac

Foreword: think different with projects on Docker vs. MAMP

While an all-in-one solution like MAMP offers all the tools you (may) need for your web project, Docker is different: YOU have to define which services / tech-stack you need to make your web project run.

The good thing is, that this is always project dependent: allowing you to build a completely different tech-stack for each project – and hence scale it perfectly to what is actually needed.

Another advantage that I like with Docker: by including a single configuration file in your project, you can easily spin up the project on another Mac – rather than a complicated cross-device sync for MAMP.

One container for one service (aka Application)

Containerisation means that each service of your project has its own instance running within Docker. So each project runs multiple services (aka Containers).

Good thing: you can group these containers under a project name!

All roads lead to rome… and everybody takes another.

For beginners like myself, I felt that Docker is very badly documented. I had a hard time finding helpful «how-to’s» for first time Docker users – not even on YouTube. The official documentation is

  • a) either very technical,
  • and b) targeted at people who already know their way around Docker.

In addition to this, there are thousands of examples online – but often they use very specific adaption of official software images (each with their custom commands, settings, etc.). And of course everybody is solving one specific case, which most likely won’t match to what you need. Worst of all: many examples I found only don’t work at all on macOS or Macs on the new Apple Silicon ARM architecture.

Be ready for a steep learning curve: not a 1-click setup & run!

Indeed I had to go through a very, very steep learning curve with Docker. There was lots of try and error on this road to my projects work on Docker.

One of the most frustrating situations I encountered: despite following an official example, it just didn’t work on my Mac. In the end, I fixed my local issue accidentally by deleting & reinstalling the image Docker needed to run a container. Who would think an auto-downloaded image could be the culprit?…


Getting started with Docker on macOS

Docker installation

Docker is free to get and install – so this is very straight forward. Everything your projects will need later*, will be installed automatically added through the Docker application.

Download and install Docker Desktop for Mac from the official site:

Note: upon installing Docker Desktop, make sure to launch the application – so all additional setup and installations will be properly completed. And keep the App running in the background.

* except the following (optional) extensions for Docker:

«docker-sync» for faster file synchronisation

As stated above, synched files from macOS to a Docker container have very slow read & write speeds. This shows particularly with database files, at least in my use cases. So I decided to fix this using «Docker Sync»: download and install it as instructed on the linked website:

Recommended: Logs Explorer extension (from the Docker Hub)

This is a very helpful extension for me, aggregating log files across all Docker containers in one place – for debugging and such. It’s like the macOS Console.app. The extension can be installed directly from the Docker Hub within Docker Desktop » Extensions.

Preparing your web project to run on Docker

Local hosts configuration: can be reused with Docker

Good to know: if you have modified your local hosts-file with custom domains for your web projects, they will continue to work with Docker.

For example: I use the Gas Mask hosts manager for macOS – and it does a wonderful job also for accessing my projects running from Docker services.

IMPORTANT: obtain an SQL-dump of your project!

Note that you won’t be able to run your existing database, e.g. from the MAMP setup, by “just moving” the corresponding database files into the new «./mariadb» folder! An import of an SQL-dump will be required.

So obtain such database backup (SQL-dump) before starting with the Docker setup, if you don’t have it at hands already…

Make your project’s structure «Docker compatible»

Depending on how your project is set up, you may or may not need to update its folder structure.

The following comparison shows one of my projects where I had to adjust the «project web root» to make it work with Docker:

Example structure of a WordPress blog project with classical simple structure for MAMP or webserverExample structure of a WordPress blog project with Docker files
Comparison of a web project structure with MAMP (left) vs. with Docker (right).

Explanation of the structural project changes

  1. Project root vs. «public web root»
    All files what will be served through the webserver (e.g. index.php) are now in a dedicated folder WITHIN the project’s root.

    For me it meant moving all files from /blog/* to ➝ /blog/public/*
     
  2. New home: bye-bye to MAMP’s «htdocs»
    The project folder no longer needs to reside within MAMP’s «/MAMP/htdocs» in order to access it from – obviously MAMP’s – local webserver. Docker is going to serve it through a container, for this the project root folder can reside basically anywhere in macOS…
     
  3. Added Docker files: «.env», «docker-compose.yml», and «docker-sync.yml»
    These additions for Docker are detailed below ⤵

Containerise your project

Some things I learned along the way

«Docker Compose YAML» and «Dockerfile» — what’s the difference and are both needed?

I managed to pack everything I need for my smaller projects within a single docker-compose.yml file – and refrained from using an additional DOCKERFILE. However, it might sometimes be a bit trickier to apply certain commands to configure Docker services, and/or for more complex solutions.

This Stack Overflow-answer is a recommend read on the difference and use cases for Docker Compose and Dockerfiles.

Is the Docker YAML configuration files’ extension «.yml» or «.yaml» – and does that matter?

Both are officially supported – however, the docs suggest to even use «compose.yaml».

In the end, any filename can be used, but it won’t be supported for “auto-discovery” by the docker compose command; and needs to be passed manually through an additional command parameter. Example:

docker compose -f /path/to/any-docker-compose.yml

Does the Docker YAML configuration need to start with «version: "3.1"»?

Although this first line is in examples all over the web, it is outdated and no longer needs to be the first line of the Docker configuration file. Refer to the official docs and specification.

MySQL database on Docker: how can I access it?

There are at least 2 very convenient ways to work with Databases on Docker:

  1. you can run a web-based Database-Manager service from Docker, e.g PhpMyAdmin (used in my WordPress setup below) or Adminer;
  2. or use your default Database Management-Application, like e.g. «Sequel Ace» and connect to the Docker database service directly.

Adding required Docker files (and folders) to your project

As mentioned and illustrated before, containerising a project for Docker requires – at least one – new configuration file. For better operate ability and portability, additional configurations may come in handy.

The «.env» dotEnv file

A dotEnv file is not absolutely necessary – but it may be easier to add / change certain settings, e.g. for cross-platform compatibility or (PHP-)version switches.

  • Here’s an example Gist giving you an idea of this approach using a .env with Docker.

What I like about the dotEnv: in combination with the PHP library «PHP dotenv» it can serve to purposes, Docker & the web application itself – from one file.

The «docker-compose.yml» YAML file

Add this file and use it do configure all services required to make your web application run on Docker!

In addition, you can also use it to configure a virtual «network» between all services of a Docker container – so PhpMyAdmin / Adminer can auto-connect to the MariaDB database, for example.

P.s.: the official Docker documentation hosts an extensive overview of all possible configuration options.

For the WordPress Docker service «wp-config.php» must be re-created

Make sure to rename / backup the existing WordPress config file «wp-config.php» – such will be re-created automatically by the WordPress Docker service.

Remember: you will need to adapt its values later, once the wp-config was created through Docker!

(Optional) The «docker-sync.yml» YAML file for docker-sync

If you are using docker-sync, add this configuration file to define the local folders that you want to sync to your Docker services, and which «synchronisation strategy» to use for each. The default configuration file name for docker-sync is «docker-sync.yml» (= auto-discovered).

Note: you will need to adapt the «volumes:»-configuration within the Docker compose YAML.

(Optional) The «/mariadb» database folder

Use a folder like this to permanently store and update the database files from Docker to the host machine (your Mac) – to not risk any data loss due to a database reset, e.g. when deleting a Docker container. And hence also for portability across multiple Macs with a Docker setup.

So I highly recommend this – but of course you can also leave this away; aware of the risk of data loss.

Docker configuration file examples

First, for exemplary purposes, below a very simple Docker configuration file for static website files is provided – before showcasing an already more complex setup for a full fledged WordPress blog.

Example 1: docker-compose for a webserver serving static files only

Quickly need a simple configuration for serving a few PHP or HTML-files? Here’s an example Docker Compose YAML for this:

Example 2: full docker-compose setup for a dynamic web app (WordPress)

Here is a setup using the official WordPress Docker image, that I successfully used to containerise my WordPress blog with Docker on Mac.

Use a .env file for Docker Compose

Configure Docker using a Docker Compose YAML config file

Note: it includes – yet disabled – configuration options for synching the database directory using «docker-sync» (see below docker-sync YAML).

For docker-sync add additional configurations

This configuration is optional, and only works if Docker Sync was properly installed.

Last but not least: define local hosts entries

With the previously WordPress configuration (see the .env-file), two entries to your local hosts file are needed:

Spinning up your web project’s Docker services

First things first: validate your Docker Compose configs

If there’s anything wrong or missing (like empty environment variables), this command will tell you:

docker compose build

Finally: bringing your Docker services up

ℹ️ When using «docker-sync»: start it before docker compose

If you use docker-sync for volumes connected from the Host (your Mac) to Docker, start it using:

docker-sync start

Starting the Docker container using «docker compose»

There are 3 ways to manage your Docker containers. I usually do this via the «Terminal» app, because this works best for a completely new Container and Services: modes can be attached to the Terminal session; detached using -d param (= in the background); or via the «Docker Desktop» app.

docker compose up

…or detached from the Terminal session (my preferred approach):

docker compose up -d

Or use the Docker Desktop app to start/stop individual Services or a whole Container.

Switch existing Web Projects from MAMP to Docker - WordPress running from Docker

And stopping/restarting a Docker container or services: vice-versa

Stop a whole container using «docker compose»:

docker compose stop

And again – if you’re using «docker-sync» – stop it’s file sync containers and daemon:

docker-sync stop

Migrating an existing MySQL database to the Docker db service

To complete a migration of something like WordPress to Docker, it should work with an available database and data contents.

In order to bring your previous MySQL-database onto the Docker database service:

  1. Make sure the Docker database service is successfully running
     
  2. Have ready the the SQL-dump obtained earlier
     
  3. Now either connect to the «wordpress» database using PhpMyAdmin via web (http://phpmyadmin:8080); or use your DB-Manager app to connect to the «wordpress» database.
     
  4. Select the empty wordpress-database, and import your SQL-dump onto it.
  5. Note: you may want to check & adjust the settings in the «wp_options»-table!

Important: adjust the WordPress options, to make your database work on Docker!

This is the most common culprit if you see an error when accessing the Docker WordPress site
«There has been a critical error on this website.»

Open the «wp_options»-table and adjust these values:

  • siteurlhttp://wordpress/
  • homehttp://wordpress/
  • active_plugins → Disable plug-ins like «Jetpack»; or clear whole field.

Inspecting details of a Docker container or service

I recommend using the Docker Desktop app on macOS to inspect your Docker container and each service: with a single click on the entry, you can see the logs, all service details, and even access a Shell command within the service.


Share:
  • 2
  • 2

2 thoughts on “Make the switch from MAMP to Docker: how to migrate existing web projects”

  1. Hello !

    Did you ever notice any performance improvement using Docker instead of Mamp ?

    I’m often generating big PDF files from custom post types using PHP. Generating them is often very long on local, but quicker on preproduction / production.

    I was wondering if using docker would make it faster on my dev environment.

    Thank you ! Nicely explained by the way.

    1. Hi Richard and thanks for your feedback.

      Yes indeed there is a performance difference with Docker over MAMP, which caused me quite some headaches & I plan to give some dedicated tips in a follow-up blog post: Docker was actually way slower – which showed particularly when reading from the database and related page load times.

      I was first able to address this by incorporating docker-sync. Then Docker Desktop improved itself with better file Synchronisation methods on macOS. However, in the meantime I found a much better solution over both: instead of using Docker Desktop, I switched to the Docker-based application «OrbStack» altogether, as it just works with regular docker configuration files and brings a feeling of almost „native“ file read/write performance to my Docker services.

      Hope that helps in your use case as well!

Questions? Suggestions? Let us know with a comment!

This site uses Akismet to reduce spam. Learn how your comment data is processed.