Please consider installing Docker Compose as well.
It greatly simplifies managing sets of containers.
Gitlab
I would recommend installing Gitlab as Docker containers. There is docker-compose.yml that
creates fully integrated Gitlab environment in seconds.
Here is the installation guide.
Gitlab Runner
If you installed Gitlab as a Docker container, best will be to do the same with runner.
Here
is complete instruction how to install it
Privileged runner configuration
We need to configure properly our runner to allow it to create fully functional Docker images.
Build have some requirements:
It needs to execute docker command. To accomplish that it needs to see
/var/run/docker.sock file from host.
It will create database images that contain actual backup state. In this post I assume
backup files are somewhere in /opt directory on host. It would be better to
retrieve backup files via wget, but we will leave this part at the moment.
At the end sample runner configuration (/etc/gitlab-runner/config.toml) contains
this part:
So here first runner configuration is able to run any container with any services.
Second configuration is able to use docker and build images.
I’ve tagged them in Gitlab as:
mvn, general (for first),
dind (for second).
So in build configuration (.gitlab-ci.yml) I’m able to choose what capabilities
are required to finnish the job.
Nginx reverse proxy
Nginx reverse proxy is used to provide simple
host names for multiple environments placed on single server.
To start proxy you may use docker or docker-compose.
With raw docker:
If you want to use docker-compose:
Remember that you have to configure your dns to point to your server. That means
something like:
Create Docker Images
Now we want our build to create images for testing purposes.
Database and application images should be configurationless - for ease of starting
new environments.
Database image
Database image will contain all data inside. That way each start and stop
of new container will create new clean copy of database.
To create this container I’ve used mysql:5.6 Dockerfile as a starting point.
But as I’ve said we don’t want to save state so we have to remove volume
declaration from it.
I’ve created new Dockerfile that:
Removes volume declaration
Adds gzip utility - as I want to extract database backup file at the build time.
Copies backup file from host to image.
Runs script that will restore database state from backup file into image.
And the script initializing database looks like this:
Warning: you need to copy docker-entrypoint.sh file from mysql:5.6 to
you image project.
CI Build for image
Last thing we need to have to make it work is .gitlab-ci.yml that will define
how to build our database image.
If everything is ok, build will finnish with success and new Docker image
will be ready for use.
What’s important, you don’t need to configure this image anyhow.
It contains data, it will leave no dangling volumes after removal.
But remember it is not transient. So after removal all changes
made to database are lost.
Beware: Today it is possible that the command from .gitlab-ci.yml
will produce so much output, that Gitlab will reject getting it from runner.
I found that after adding something like find /var to script
part of yml.
Application image
Application image will contain all the data needed to start the application.
Dockerfile
Ok, you will have to do this part on your own, because this strongly
depends on specific application. I’ve was making my research basing
on PHP application.
There are some important things to remember:
Image should be totally stateless and working properly without any parameters.
If you need params, default values (when nothing was passed in env) should
be provided.
No volumes. So if you are using existing image then check for volumes declared.
I’ve started from php:5.6 image, but in the end I’ve created new Dockerfile
based on it. I’ve removed all volumes and added custom things needed for my app.
In particular my application used php-http library to get some data from other
servers. So I had to add building this lib into Dockerfile.
This configuration assumes that
you have all php:5.6 helper files are placed with Dockerfile,
your application is placed in html subdirectory.
CI Build for image
This script builds image with application and after that start simple test.
This file tells docker-compose what are components and connections
between them in integrated environment.
Environment startup: setup.sh
This script has to create unique readable name for newly created
environment.
After that new environment is availible under link http://$BUILD_ID.example.com.
Environment shutdown: teardown.sh
This script has to shutdown environment after finnishing tests.
It extracts name that was created for environment instance.
UAT environments on demand
Last goal is to provide environment that persists for some time.
We don’t know how long will it be, but:
State should persist server restarts
After removing environment, no data persists.
Basically we use same scripts that were provided for integration test project.
The only change is that teardown.sh shouldn’t be runned without direct
manual command.
To accomplish that we start new environment using same project but with
manual script execution.
Remember that commands described below should be executed from integration
project directory as root.
To start new environment we need to run setup.sh script with additional
env parameter:
Script will look for CI_BUILD_REF variable, so we need to configure it
manually as above. Only first 8 chars from CI_BUILD_REF are taken into
account when creating environment name.
After running script web server is accessible at address
http://uat001.example.com.
To remove our integration after tests we need to run teardown.sh:
End
This configuration works well providing tools for use cases described in goals
section.