I'm going to assume you have some basic knowledge of docker. I also assume you have installed docker and docker-compose locally. You can read more about docker here. I'm going to be doing this for an example Laravel site however this should work if you're using Drupal or some similar framework.

What we need

We're going to build a local stack for development, so we're going to need Apache, PHP, and MariaDB database.

Setup

I've generated an example project called mysite it's a typical composer based PHP site, with a public web root.

Generic Laravel template

In the root of your project we're going to want to create some files and folder structures, run the following command.

mkdir -p docker/php-apache2 && touch docker-compose.yml docker/php-apache2/Dockerfile

This will create the following:

docker-compose.yml
docker
docker/php-apache2
docker/php-apache2/Dockerfile

The Web/PHP container

First up we'll get the web container configured as it's the only one we'll need a Dockerfile for. In your favourite editor open up docker/php-apache2/Dockerfile and paste in the following.

# Base image
FROM php:7.2-apache

# Fix debconf warnings upon build
ARG DEBIAN_FRONTEND=noninteractive

# Run apt update and install some dependancies needed for docker-php-ext
RUN apt update && apt install -y apt-utils sendmail mariadb-client pngquant unzip zip libpng-dev libmcrypt-dev git \
  curl libicu-dev libxml2-dev libssl-dev libcurl3 libcurl3-dev libsqlite3-dev libsqlite3-0

# Install PHP extensions
RUN docker-php-ext-install mysqli bcmath gd intl xml curl pdo_mysql pdo_sqlite hash zip dom session opcache

# Update web root to public
# See: https://hub.docker.com/_/php#changing-documentroot-or-other-apache-configuration
ENV APACHE_DOCUMENT_ROOT /var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

# Enable mod_rewrite
RUN a2enmod rewrite

There's a lot going on in there however, the key points to know are, we're using the official PHP-Apache2 docker images as a base (found here), we also install some other packages needed for enabling some PHP extensions.

We're not going to customise the database container so we're ready to put it all together.

...and the rest

In your editor of choice open the docker-compose.yml file we created earlier. Paste the following into it.

version: "3.1"
services:
  database:
    image: mariadb:10.1
    container_name: mysite-mariadb
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=mysite
      - MYSQL_USER=mysite
      - MYSQL_PASSWORD=password
    ports:
      - "8083:3306"
  web:
    build: docker/php-apache2
    container_name: mysite-web
    volumes:
      - .:/var/www/html
    ports:
      - "8080:80"

This uses the off-the-shelf MariaDB docker image and specifies the build directory for the web container. docker/php-apache2. The environment section in the database service specifies the credentials we want MariaDB to start up with.

Lets start it up

Now we've put it all together, lets start up our stack and see what we have. Run the following to build and start up the containers.

docker-compose up -d

It might take a while to build, especially if you have to download the base images but ones completed you should be able to run docker ps and see something like the following.

So we now have an Apache2 webserver running mod_php listening on http://localhost:8080 if you navigate there now you'll likely get an error, cause we still have to tell Laravel about the correct database settings. Open up the .env file in your editor and update the database settings to read:

DB_CONNECTION=mysql
DB_HOST=mysite-mariadb
DB_PORT=3306
DB_DATABASE=mysite
DB_USERNAME=mysite
DB_PASSWORD=password

These are the environment values provided to the MariaDB container in the docker-compose.yml file. Now if we navigate to http://localhost:8080 we should see the default Laravel homepage.

Some final thoughts

Having this setup makes it pretty easy to update software versions like PHP and MariaDB. Try it. Update the version of MariaDB in the docker-compose.yml to 10.2 and rebuilding. Or even changing the base image in the Dockerfile from php:7.2-apache to php:7.3-apache. It's nice not having to upgrade distributions or VirtualBox images in order to see if your site will work on a newer software. It also makes adding things like Redis, Memcache, Mailhog etc a lot easier.

Now this is a pretty cut back version of what I'd use normally as I wanted to keep this post as simple as possible. Normally in my PHP/Apache Dockerfile I'd install some extra things I find useful for development like Xdebug, PHPUnit, NodeJS, Composer etc. Let me know in the comments if you have any questions.