I’m a fan of containerisation! It feels much cleaner and systems don’t age that quickly.
Latest project that I am supposed to maintain is a new Contao website. The company who built the website of course just delivered files and a database. The files contain the Contao installation next to Contao extensions next to configuration and customised themes.. All merged into a blob… Thus, in the files it is hard to distinguish between Contao-based files and user generated content. So I needed to study Contao’s documentation and reinstall the website to learn what files should go into the Docker image and which files to store outside.
However, I finally came up with a solution that is based on two Contao images :)
A general Contao image
The general Contao image is supposed to contain a plain Conato installation. That is, the recipe just installs dependencies (such as curl, zip, and ssmtp) and downloads and extracts Contao’s sources. The Dockerfile looks like this:
The first block
apt-get installs necessary stuff from the Debian repositories.
The second block downloads a Contao 3.5 from
https://download.contao.org/3.5/zip, extracts it to
/var/www/, and links
/var/www/html to it.
It also creates the
cron.txt (see github.com/contao/core/pull/8838).
The third block installs a few required and/or useful PHP extensions.
And finally the fourth block retrieves and installs Composer to
/var/www/html/composer, where the Contao-composer-plugin expects it.
A personalised Contao image
Besides the plain Contao installation, a Contao website typically also contains a number of extensions.
Those are installed through composer, and they can always be reinstalled.
As we do not want to install a load of plugins everytime a new container is started we create a personalised Contao image.
All you need is the
composer.json that contains the information on which extensions and which versions to install.
This json should be copied to
/var/www/html/composer/composer.json, before composer can be run to install the stuff.
Here is an example of such a Dockerfile:
This image can then be build using:
The resulting image tagged
contao-personalised will contain all extensions required for your website.
Thus, it is highly project specific and shouldn’t be shared..
How to use the personalised Contao image
The usage is basically very simple. You just need to mount a few things inside the container:
/var/www/html/files/should contain files that you uploaded etc.
/var/www/html/templates/may contain your customised layout.
/var/www/html/system/config/FILE.phpshould contain some configuration files. This may include the
Optionally you can link a MariaDB for the database.
Tying it all together using Docker-Compose
Probably the best way to orchestrate the containers is using Docker-Compose.
Here is an example
This assumes that your personalised Dockerfile is located in
path/to/personalised/Dockerfile and your website files are stored in
Docker-Compose will then build the personalised image (if necessary) and create 2 containers:
contaobased on this image, all user-based files are mounted into the proper locations
contao_dba MariaDB to provide a MySQL server
To make Contao speak to the MariaDB server you need to configure the database connection in
$PATH/system/config/localconfig.php just like:
Here, the database should be accessible at
contao_db:3306, as it is setup in the compose file above.
If you’re running contao with “Rewrite URLs” using an .htaccess you also need to update Apache’s configuration to allow for rewrites.
Thus, you may for example mount the follwoing file to
This tells Apache to allow everything in any .htaccess file in /var/www.
When everything is up running the Conato install will be available at port
ports definition in the compose file) of the machine hosting the Docker containers.
The image above comes with sSMTP installed. If you need support for email with your Contao installation, you just need to mount two more files into the container:
Tell PHP to mail through sSMTP
The following file tells PHP to use the
ssmtp binary for mailing. Just mount the file to
The sSMTP configuration is very easy. The following few lines may already be sufficient, when mounted to