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
.