Sometimes I need to spin a Docker container really quick so I can test stuff locally and the quickest way (for me) is to keep a project template somewhere on the disk so I can quickly copy it, add the web app and test it. Ofc there are other alternatives. Ofc some are better. Ofc some are faster. But this one is mine.

The container will be configured with:

  • latest Apache web server with SSL and mod_rewrite.
  • PHP 7.4 with bz2, iconv, intl, gettext, mbstring, mysqli, pdo_mysql, soap, zip, gd, exif.
  • MySQL database server version 8.0

The directory structure of the project template is the one below:

.
├── Dockerfile
├── certs
├── config
│   └── default-ssl.conf
├── db
├── docker-compose.yml
└── www
	└── index.html
  • Server SSL certificate and key goes into certs.
  • Apache vhost configuration into config.
  • MySQL database into db.
  • The actual web application into www, keep in mind that it can be a symlink to any source directory outside.

Certificate

Install mkcert and use it to generate a locally-trusted development certificate.

$ brew install mkcert nss
$ mkcert -install
$ cd certs/ && mkcert mysite.test
Created a new certificate valid for the following names
 - "mysite.test"

The certificate is at "./mysite.test.pem" and the key at "./mysite.test-key.pem"

It will expire on 15 March 2023

And you should have two new files in the certs directory, mysite.test.pem and mysite.test-key.pem, first is the SSL certificate and second one is the certificate key.

Note

Remember to replace mysite with the name of your app.

Dockerfile

The Dockerfile will import a PHP 7.4 for Apache image, configure it with various PHP extensions, enable mod_rewrite and SSL.

FROM php:7.4-apache
LABEL maintainer="sizeof(cat)"
COPY certs/mysite.test.pem /etc/apache2/ssl/server.crt
COPY certs/mysite.test-key.pem /etc/apache2/ssl/server.key
COPY config/default-ssl.conf /etc/apache2/sites-available/default-ssl.conf
RUN buildDeps="\
		default-libmysqlclient-dev\
		libbz2-dev\
		libsasl2-dev\
	"\
	runtimeDeps="\
		curl\
		git\
		libfreetype6-dev\
		libicu-dev\
		libjpeg-dev\
		libpng-dev\
		libpq-dev\
		libxml2-dev\
		libzip-dev\
	"\
	&& apt-get update\
	&& DEBIAN_FRONTEND=noninteractive apt-get install -y $buildDeps $runtimeDeps\
	&& docker-php-ext-install bz2 iconv intl gettext mbstring mysqli pdo_mysql soap zip\
	&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/\
	&& docker-php-ext-install gd\
	&& docker-php-ext-install exif\
	&& apt-get purge -y --auto-remove $buildDeps\
	&& rm -r /var/lib/apt/lists/*
RUN a2enmod rewrite
RUN a2enmod ssl
RUN a2ensite default-ssl
RUN service apache2 restart

docker-compose.yml

The docker-compose.yml file is the configuration file for docker-compose; the structure is easy to understand, replace the image name (sample_webapp), the MySQL root password (root) and the MySQL database name (sample_webapp_database).

version: '2'

services:
  server:
	build: .
	image: sample_webapp
	ports:
	  - "80:80"
	  - "443:443"
	volumes:
	  - ./www:/var/www/html
	links:
	  - db

  db:
	image: mysql:8.0
	ports:
	  - "3306:3306"
	volumes:
	  - ./db:/var/lib/mysql
	environment:
	  - MYSQL_ROOT_PASSWORD=root
	  - MYSQL_DATABASE=sample_webapp_database

default-ssl.conf

There is nothing special in the Apache vhost configuration file, basically we disable SSLv2 and SSLv3 and set the ServerName directive to the domain we requested the SSL certificate for.

<VirtualHost *:80>
	ServerName mysite.test
	DocumentRoot /var/www/html
</VirtualHost>

<VirtualHost *:443>
	ServerName mysite.test
	DocumentRoot /var/www/html
	SSLEngine on
	SSLProtocol all -SSLv2 -SSLv3
	SSLCertificateFile /etc/apache2/ssl/server.crt
	SSLCertificateKeyFile /etc/apache2/ssl/server.key
	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

DNS resolution

Add a new line in your /etc/hosts file:

127.0.0.1 	mysite.test

Build and run the container

That’s it, cd into the project root (the directory with the docker-compose.yml file), run docker-compose and depending on your download speed container should be up in seconds and serving the contents of the www directory.

$ docker-compose up

Open your favorite web browser and point it to https://mysite.test.