Develop, Dockerize & Deploy Contao 4: Part 2

Learn how to start a local development container and manage your source code via GitLab.

Florian Vick
May 10, 2020 · 7 min read

In the last part I walked you through the steps to set up your development environment and how to build our container for the first time. This time we are setting up a container for local development purposes and see how we can utilize Git & GitLab.com to manage our source code.

A local development container

To avoid having to build our container every time we change our code, we will build a local development container to which we directly mount our source directory. Furthermore we will spin up a MariaDB-Container to serve as our MySQL server. To do all of this with one simple command, we will be using Docker Compose, a tool to create and manage a complete stack of containers including volumes and Docker networking.

Thinking back to the last article where we explored which containers and volumes we need, we can derive the components we need for local development:

  1. Our PHP-Container with PHP and the Caddy Webserver
  2. A MySQL Container
  3. A volume for the MySQL data
  4. Our code inside the PHP container

Docker compose is controlled by a YAML file which contains the information on how to start the application container and what values those need. We start by creating one called ‘docker-compose_dev.yml’ in a subfolder called ‘docker’.

The docker-compose.yml for local development

We start out with the version level — it is the version of the instruction set the docker-compose command needs to support in order to work with our configuration file. The current version at the time of writing (05/2020) is 3.8.

Next we define the volumes we will need: In this case only a data volume for the MariaDB/MySQL container to store its database.

After that, we can define a network for our database container. This is a good practice for security reasons it ensures only the containers added to that network can access the database.

With volume and network defined, we can add the two containers under the services section. Starting with the MySQL container — its options were taken straight out of the README file on DockerHub, defining user, password and database as well as connecting the volume defined earlier and where to mount it. Finally the container is attached to the db network defined in the networks section in the beginning.

Now we have all the prerequisites for defining our Contao 4 container. Note the ports definiton: The left side of the colon contains the port on our host machine and the right side the port inside the container — in our case it is the same but we still need to explicitly tell docker compose that we want this happening, otherwise it will get assigned to a random port on our host machine. In the environment section you notice the variable DEVMODE set to True, this will perform a couple extra things to make our development life easier (setting up a user, aliases and running composer install in our mounted source code directory).

The most important thing though is in the volumes section of the contao4 container: We instruct the Docker daemon to mount the complete source code directory inside the container, so that changes to the PHP code we make in our local directory are immediately available in our container. Remember that this breaks the “disposability” concept of containers so we will only use this method of mounting our source code directly during our local development to speed things up.

The updated boostrap.sh file

At this point you should be able to change into the docker directory inside our project and run docker-compose -f docker-compose_dev.yml up -d and see docker-compose creating the network, volume and containers.

Screenshot showing the successful completion of docker-compose
docker-compose creating the stack

Setting up Contao

Let us now create a simple site that serves as a demonstration to deploy. Currently we have an empty Contao 4 installation with nothing but a database configured.

First we should set or disable the Contao Install password. To do that, create a file config.yml in the folder /config of our Contao 4 Installation and fill it with the following:

Basic config.yml for Contao 4

This replaces the file /system/config/localconfig. Notice the lines beginning with %env(. These take the values from environment variables stored in a file called .env in the root directory of your Contao 4 installation. To override values for local development, you can create a file called .env.local that overrides everything found in it for your local machine (for example, setting APP_ENV=dev will enable debug mode permanently on your local machine regardless what was specified in the .env file).

Now we have two options:

  1. Disable the Install-Password altogether and use the command line way of executing migrations
  2. Set the install password in the .env file and use the install tool normally

As we are going to deploy our finished container automatically later on, we should go with option 1. To disable the Install-Tool, you can set the variable INSTALL_PASSWORD to blank with INSTALL_PASSWORD=.
If you try to set the password now via the install tool, it will loop forever in the enter password screen as it can not write to neither the config.yml nor the .env file — thus effectively disabling the install tool.

However — we do not have an administrative user account yet. Unfortunately Contao 4 does not provide a command for creating a user account via command line, you can only change passwords of already existing users. So we are going to take option 2 for now. Go to the Bcrypt Generator site and generate a hash of a password of your choice. Copy the generated hash and put it in the .env file like so: INSTALL_PASSWORD='myhashstring'(remember to put it in single quotes).

The second thing you will notice is that the MySQL connection string is also combined from values set in the .env. This means we only need to provide values in one place when we deploy our application later. We should set our database credentials like we configured them in the docker-compose file earlier:

Our .env file

Running the initial setup

Now that we have configured the necessary credentials we can run our initial migration to have contao setup a blank database. To do this we are going to connect to the running Contao 4 container via command line and run the contao migration command just to see how this works. We will later run this command everytime a container starts on the production server, so the database gets updated to eventual schema changes.

Connect to the container by running the docker-compose -f docker-compose_dev.yml exec contao4 /bin/ash command inside the ‘docker’ directory. You will see a new command prompt appear. You will already be in the application directory as we set the working directory in our Dockerfile.

You can now run vendor/bin/contao-console contao:migrate. This will show you the migrations that will be executed. Confirm them by hitting the number 0 key. Contao should now apply the initial database schema.

Screenshot showing the completion of the contao:migrate command
Successful command line migration

After this you can create the initial admin user via the install tool. After that you should be able to login into the Contao backend.

Creating a Git repository and initial commit

At this point we have a basis to develop our application, therefore it is now time to think about version control. The most common version control used today is Git. To create a git repository in our project directory, open or reuse a command prompt inside our project and simply run git init. This will create a Git repository in the current directory.

Git Logo and slogan

With the local Git repository created we can add all of our files by using the command git add .. The dot here stands for everything and the command will now add all files except those mentioned in the .gitignore file created in Part 1 to the staging queue for a new commit. If you do not know much about source control, you can think of a commit as a snapshot of the repository at a specific point in time which you can later come back to if you want (or find out between which commits a file has changed). Finish off the commit by typing git commit -m "Initial commit" — the m-Option standing for ‘message’. This message will be saved for this specific commit and should give another developer a short overview of what you changed in this commit.

In order to enable continuous automatic building of our image and deployment we need a server or service that does this independently of our development machine. This is where GitLab comes in. Like GitHub it allows you to host your Git remote repository there but it also features a docker image registry and its own build pipeline we both can use to build and store our docker image. Plus it’s generous free plan is more than enough for most smaller projects.

Start by setting up a new account if you don’t already have one and create a new, blank repository. I chose the same name as the folder I created the Dockerfile in ‘contao-on-docker’ (You can find it here).

After you have created the new repository you can push your local repository to it by using the command git remote add origin https://gitlab.com/<your username>/contao-on-docker.git to connect the repositories and then running git push origin master. This will copy all your local commits on the master branch to the GitLab.com server.

Now you have your projects source code and history available anywhere!

This is it for today! Stay tuned for the next part, where we get to the most interesting bits: Using the GitLab CI pipeline to build our Docker image, storing it in the GitLab registry and then deploying it to a server! You will find a link here as soon as it is released!

The Startup

Get smarter at building your thing. Join The Startup’s +725K followers.

Florian Vick

Written by

Software Developer, avid reader, curious human

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +725K followers.

Florian Vick

Written by

Software Developer, avid reader, curious human

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +725K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store