We use cookies to make your viewing experience better. By accepting you consent, you agree to our Cookie policy

Improve your Craft CMS skills

How To Install Craft CMS On Docker - A Complete Guide

10 min read
Shape April 2022 HR 28

Running Craft CMS in Docker provides major advantages, but can be tricky to setup. This complete guide will walk through installing Craft on Docker from start to finish. You'll learn how to configure Docker, connect to a database, persist data, integrate a web server, and fully Dockerize a production-ready Craft CMS environment. Whether you're looking to develop Craft sites through containers or deploy them, this article covers the key steps for a smooth Docker workflow.

This guide covers key steps to fully Dockerize a production-ready Craft CMS environment, including configuring Docker, connecting to databases, persisting data, integrating web servers, and accessing the Craft backend and frontend. Following these core areas will prepare you to Dockerize your next Craft CMS project through containers.

Prerequisites for Docker and Craft CMS

Installing Docker

Docker installation is fairly straightforward across all major operating systems like Linux, Windows and MacOS.

The easiest way to get Docker up and running on Windows and Mac is to use Docker Desktop. This is Docker's official GUI tool that bundles Docker Engine, Docker Compose and Kubernetes all into one simple application.

To install Docker Desktop on Windows head over to Docker Hub and download the installer. Double click to run it, accept the license agreement and follow the on-screen prompts. That's pretty much it, Docker Desktop will now be installed and accessible from your start menu.

For Mac, again just go to Docker Hub but this time grab the Mac installer. Double click to open, drag the Docker icon into your applications folder to install and you'll find Docker Desktop in the launchpad. Simple as that, Docker is installed and ready to use on MacOS.

On Linux distributions like Ubuntu there are a few extra steps since you need to setup repositories and keys. Run the following commands in a terminal:

sudo apt-get update

sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

curl -fsSL https://download.docker.com/li... | sudo apt-key add -

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/li... $(lsb_release -cs) stable"

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.i

With those run, Docker CE is now installed. Check it's working with docker run hello-world.

Docker Compose Installation

Along with the Docker Engine we'll also need Docker Compose for managing our multi-container Craft CMS setup through a compose file.

For Linux you can install it via pip:

sudo pip install docker-compose

Or download the binary directly from the Github releases page.

For Mac and Windows it's already bundled with Docker Desktop so you get Compose automatically. Verify it's installed with docker-compose --version.

With Docker and Docker Compose ready, we can move onto getting the Craft CMS codebase.

Obtaining Craft CMS Files

There are a couple of ways we can get Craft CMS - directly downloading it or cloning it from GitHub.

Downloading the zipped Craft CMS files provides a quick way to get up and running. Head to https://craftcms.com/latest-v3-zip and grab the latest stable release. Unzip it and we'll have the complete Craft CMS folder structure ready to copy across to our Docker containers shortly.

For keeping things up to date, we'd be better off cloning the Craft CMS repository from GitHub. We'd then just need to pull down the latest commits rather than re-downloading entirely each time.

Browse to https://github.com/craftcms/cms and clone the repo:

sudo pip install docker-compose

With our Craft CMS codebase obtained through either method, we've now got all the prerequisites sorted to start our Docker setup.

Using the Official Craft CMS Docker Image

Finding the Docker Image

When setting up Craft CMS with Docker, we're in luck because there is an official Docker image available. This provides a ready-made image that has Craft CMS preinstalled, saving us time and effort.

You can find the official Craft CMS image by browsing to Docker Hub and searching for craftcms/craft. The image is popular with over 200 stars and 10K pulls, so it's reliable and up-to-date.

The details show it's the official image maintained by Pixel & Tonic themselves. It has Craft CMS along with PHP extensions and tools like Git installed. The README confirms it's optimised for running Craft CMS in Docker environments.

Selecting the Right Tag

When pulling a Docker image, it's important to use the correct tag to get the specific version you need. Tags allow multiple variants of an image to coexist.

The Craft CMS Docker Hub page shows all available tags. Most are in the format 3-php7.4-apache denoting the Craft 3 and PHP versions.

For example, to get Craft 3 with PHP 7.4, use the 3-php7.4-apache tag. Or for the latest Craft 4 beta use 4-php8.0-apache. Review the tags to determine the one matching your required Craft CMS and PHP versions.

You can also use version tags like 3.7.0, 3.7.5 etc for an exact Craft release. Check the Craft CMS changelog when selecting.

Tags like latest or stable point to the newest stable releases so those can be used for always staying up-to-date.

Pulling the Image

With the tag identifier chosen, pulling the image locally is as simple as:

docker pull craftcms/craft:3-php7.4-apache

Replace the tag with your desired one. This will download the image to your machine ready for running the container.

If you have a private Docker Hub account, first log in so the pull works:

docker login

# then provide your Docker Hub username and password

With the official Craft CMS image pulled, we've got our base image sorted. When it comes time to configure the containers, we'll launch them using this prebuilt image.

The next steps will cover creating a Docker Compose file and defining our Craft CMS services within it. The compose file will orchestrate and link together our containers.

By leveraging the official Craft CMS image, it saves us time and gives our setup a solid foundation to build on top of. We get Craft CMS fully installed out of the box without needing to manually configure it ourselves in the container.

Configuring Docker Compose for Craft CMS

Compose File Sections

The docker-compose.yml file defines our Docker services and container configurations. It allows declaratively specifying containers, networks, volumes etc.

The main sections are:

  • services - Defines the individual containers to run such as Craft, database, cache etc.

  • volumes - Persistent storage mount points accessible across containers.

  • networks - Networks for communication between containers.

  • environment - Environment variables accessible within services.

These provide full control over the Docker environment and its services. The compose file is used with docker-compose commands to launch the configured system.

Defining Services

The services section is the core component. Here we define each required service/container such as:

  • craft - The primary Craft CMS container

  • db - Database server container like MySQL or PostgreSQL

  • cache - Redis or Memcached caching service

  • web - The web server container e.g Nginx or Apache

Under each service we configure parameters like:

  • image - The Docker image to base the container on.

  • ports - Expose ports to the host system.

  • volumes - Mount storage volumes inside the container.

  • depends_on - Define start order dependencies between services.

This fully configures each container according to its specific needs. For example the Craft service will use the craftcms/craft image and expose port 80.

Service Environment Variables

We can provide environment variables to our services through the environment section.

For Craft CMS, useful variables are:

  • DB_SERVER - Database hostname

  • DB_USER - Database username

  • DB_PASSWORD - Database password

  • DB_DATABASE - Craft database name

  • DB_SCHEMA - Schema name

These allow injecting runtime configuration like database credentials securely into the services.

In total, the Docker Compose file gives us an easy way to fully define our complete Craft CMS Docker infrastructure ready for deployment.

The next step will cover using docker-compose commands to build and launch our configured system using the compose file.

Database Setup and Configuration

Container Database Options

For the database server, we have a few options when it comes to Docker container images. The two most common choices are MySQL and MariaDB which are fully compatible with Craft CMS.

The official mysql and mariadb images available on Docker Hub provide optimized production-ready bases for the database containers. These leverage the standard MySQL/MariaDB distributions and include useful tools like mysqldump.

Other alternatives like PostgreSQL also work with Craft, so we could use the postgres image instead. For simplicity, we'll focus on MySQL/MariaDB here as those are the typical pairings.

Linking the Database

With the database image chosen, we need to link it to our Craft CMS container so Craft can communicate with the database.

This is achieved by placing both containers on the same Docker user-defined network. Networks provide private internal communication between containers.

In our docker-compose.yml, we can define a network called craft-network for example:



Then under the Craft and database services, specify they connect to this network:




- craft-network



- craft-network

Now the Craft and database containers can talk over the craft-network, with hostnames like craft and db available.

Craft can then connect to the database at db:3306 using the hostname. The port mapping exposes the database port 3306 onto the network.

Database Persistence

With the database connected, we need to consider data persistence across container restarts and rebuilds.

By default, the database data would only exist inside the container's writable storage layer. If the container stops, the data would be lost.

To make the data persist, we can mount a volume at the database's data directory:






- dbdata:/var/lib/mysql

This maps the dbdata volume to /var/lib/mysql where MySQL stores its files. Now data will be saved on the volume, outside of the container lifecycle.

Even if the database container is rebuilt, the volume will retain the data so it simply reattaches. This gives us persistent storage for our Craft CMS database.

With the database linked and persistently storing Craft's data, we've now got the supporting services configured. Next we'll look specifically at the Craft CMS container and web server.

Configuring Persistent Storage

When running Craft CMS in Docker, we need to consider how to provide persistent storage for things like uploads, logs, caches etc. By default containers have ephemeral writable storage, so we need to use volumes to mount external persistence.

Read-Write Volumes

For all writable data like user uploads or logs, we’ll need read-write volumes that can be mounted into the Craft container.

In our docker-compose.yml we can define named volumes:




Then mount them under the Craft service:




- craftuploads:/craft/storage

- craftlogs:/craft/storage/logs

This persists the /craft/storage and /craft/storage/logs directories to the craftuploads and craftlogs volumes. They'll now exist outside of the container's filesystem.

Even if the container is rebuilt, the volumes will retain their data. We get durable storage for Craft's dynamic writable data.

Read-Only Volumes

Some directories like caches or plugins need to persist but be read-only within the container.

We can still mount volumes but mark them read-only:






- craftcache:/craft/storage/runtime/cache:ro

The :ro sets the cache directory as read-only inside the container. This is useful for directories that only need to be written to during image build.

Craft CMS Official Volumes

Looking at Craft's official Dockerfile, it defines two main volumes:

  • /craft/storage - For uploads, logs, caches etc.

  • /craft/config - Configuration files and database.php

It sets appropriate permissions and ownership on them.

We can utilize these same standard volume mounts for Craft's dynamic and config data.

For example our compose file may define:




- craftstorage:/craft/storage

- craftconfig:/craft/config

Using the official volumes as guides, we can ensure proper persistence for Craft CMS.

With storage configured via volumes, our data will persist across container rebuilds and restarts. Next, we'll look at options for the web server to proxy requests to the Craft container.

Setting Environment Variables

Critical Variables

Some environment variables are critical for Craft to function correctly:

  • DB_SERVER - Database host name or IP

  • DB_USER - Database username

  • DB_PASSWORD - Database password

  • DB_DATABASE - Craft database name

  • DB_PORT - Database port (default 3306)

Without these database credentials set properly, Craft won't be able to connect and errors will occur on startup.

Other essential settings include:

  • CRAFT_ENVIRONMENT - Environment name like production, staging etc.

  • DEFAULT_SITE_URL - Base URL for the primary site.

So the first step is ensuring these core variables are configured in the .env file.

Base URL Variable

The APP_URL or BASE_URL variable needs to be set to Craft's correct external hostname. This ensures links and resources generate with the proper URLs.

For example in development:


Or in production:


Without the correct external base URL, links can be broken and issues like missing CSS or 404s occur.

Control Panel Triggers

Additional variables like ADMIN_URL allow setting a custom control panel trigger word.

For example:


Then visiting http://mywebsite.com/mycraftad... will load the control panel rather than the default /admin path.

This improves security by using an obscure, hard to guess URL for the control panel rather than a common path like /admin.

Other useful settings include:

  • SECURITY_KEY - System security key for encryption

  • CRAFT_LICENSE_KEY - Craft CMS license key

So in summary, critical settings like database credentials must be set, along with key variables like the base URL. Additional configuration like admin URL triggers and license keys help tune the environment.

Storing these in a .env file keeps them secure compared to baking into images. And Compose can automatically read the .env so variables are available to containers.

This allows managing configuration externally through Docker Compose rather than scattered through images. Next, we'll look at how to launch our configured system.

Running and Accessing Craft CMS

With our Docker Compose file configured, we can now launch our Craft CMS environment. A simple docker-compose up command will spin everything up.

Initial Compose Up

Inside the directory containing the docker-compose.yml, run:

docker-compose up -d

The -d launches in detached mode, running the containers in the background.

This will spin up the configured services like the Craft container, database, web server etc.

Output logs will show each starting up and once ready, our Craft CMS Docker environment will be running.

To follow the logs, add -f to the docker-compose up command. Ctrl+C will exit the log output.

Initial loads may take some time as containers are built for the first time. On subsequent runs they'll startup much quicker using cached layers.

Accessing Craft Backend

With containers running, we should be able to access the Craft CMS control panel using the configured ADMIN_URL variable.

For example, if we set:


Then visiting http://mywebsite.com/craftadmi... should load the Craft backend (replace with your real URL).

The first visit will trigger the Craft setup process. Follow the prompts to set admin details, create our first section and entry, and do any config needed like connecting email settings.

Once completed, the control panel will be usable for managing content, settings, plugins and everything we love about Craft!

Frontend Access

To view the frontend site, we need to enable a public template in Craft's settings which controls the homepage.

Under Settings > Sites, set an Entry template to the Homepage or create a Single.

Now visiting the frontend URL like http://mywebsite.com will load the public facing site, showing our example entry content.

The homepage loads more quickly on the first visit as it gets cached. The control panel is secure behind the admin URL path.

With just a few steps, our Docker setup allows accessing both the Craft CMS backend to manage content, and the frontend to view our published site - all running through containers.

We've covered the core areas needed to get a complete Craft CMS environment running on Docker. Next we'll wrap up with some final thoughts.

Docker Tips and Tricks for Craft CMS

When running Craft CMS with Docker, there are some useful tips around rebuilding, debugging, and optimization. Here are some key areas for a smooth Dockerized Craft experience.

Container Rebuilding

During development changes often require rebuilding containers, such as modifying the Dockerfile or mounted volumes.

Rather than a full re-up, we can rebuild specific services. For example:

docker-compose build craft

This rebuilds just the Craft container so new changes are included. To also restart it:

docker-compose up -d --no-deps craft

The --no-deps prevents restarting linked containers.

For a full rebuild and restart:

docker-compose build

docker-compose up -d

So selective rebuilds save time over completely re-upping the whole stack.

Accessing Logs

Logs provide visibility into containers, handy when issues occur. View the logs with:

docker-compose logs -f

The -f follows the output. Adding a service name shows just that container e.g. docker-compose logs -f craft.

Error messages indicating why a container crashed are surfaced here. Database connection issues or missing environment variables are common culprits.

Search the Craft CMS logs for hints when encountering problems. The logs are invaluable for diagnosing Docker environments.

Performance Optimization

There are a few areas to tune for optimal Craft CMS Docker performance:

  • Use bind mounts for local development volumes to avoid disk I/O lag.

  • Enable PHP OPcache in the Dockerfile for faster PHP execution.

  • Set the devMode and debug Craft config settings to false in production.

  • Use a cache like Redis for boosting frontend performance.

  • Configure Nginx for best practices like gzipping, caching, buffers etc.

Also set Craft's environment variable to production for performance optimizations.

Doing Docker builds on robust hardware like cloud servers avoids slowdowns. Leverage multi-stage builds to keep final images lean.

So while containers abstract environments, standard tuning still applies for a speedy Craft CMS.

In summary, utilize selective rebuilds for faster iterations. Check logs to troubleshoot issues. And apply performance best practices for Docker. This ensures a slick and optimized Craft CMS environment.

We've now covered core areas around Dockerizing Craft CMS. With the major points in place, you'll be prepared to Dockerize your next Craft project.

Shape April 2022 HR 202
Andy Golpys
- Author

Andy has scaled multiple businesses and is a big believer in Craft CMS as a tool that benefits both Designer, Developer and Client. 

Show us some love
Email Us
We usually reply within 72 hours
Agency Directory
Submit your agency
Affiliate Partners
Let's chat