Setting up GitLab, GitLab-CI, and your builds on Docker
With the inception of Docker, and the availability of an amazing amount of predefined images, setting up services on your server never was easier. A while ago I decided to start installing everything I want to use on my server using Docker. At the same time, I wanted to install GitLab and use the CI functionality provided – also running on Docker. In this article I’ll try to explain how to set up GitLab, GitLab-CI, and your builds on Docker 1.12.
Prerequisites
It should not come as a surprise that you should have Docker installed on your machine. In case you haven’t done so yet, please follow the getting started guide on the Docker website. Note that I am running Docker on a Linux environment.
Setting up a network
Before we start running images, we’ll have to set up a Docker network. The reason for this is that we’ll be running multiple containers that have to talk to eachother. Using a new Docker network makes our life easier, since we’ll be able to refer to our container names instead of hardcoded ip addresses. Docker will resolve this to the proper ip address for us.
To set up a new network called ‘mynetwork’, we’ll execute the following command:
docker network create mynetwork
By default the network type created by Docker will be a ‘bridge’ network, which in this single-server set-up fits the requirements perfectly.
Starting the GitLab container
Next we start with starting GitLab. GitLab maintains an image on Docker Hub, which we can use to start. I have used the following container creation script:
docker run --detach \
--network mynetwork \
--publish 80:80 \
--publish 2222:22 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
As you can see, we set the network option to ‘mynetwork’, linking our newly created
container to the new network. The --publish arguments will publish the specified ports on
the host. In case of port 22, we’ll use port 2222 on the host, since there’s already a service
listening on port 22. The --name argument gives the container a name that we can use to
identify the container. The --restart argument tells Docker to restart the container when it
hasn’t been manually stopped (like a container failure, or system reboot). The --volume
arguments map directories on the host to directories inside the container. The very last
argument is the name of the image to run, in this case gitlab/gitlab-ce:latest.
After running this command, running docker ps should show you a running container named
‘gitlab’. Opening a browser to the host that’s running the container, should show GitLab.
Starting the GitLab Runner container
To make use of GitLab’s CI functionality, it is required to have a runner installed. GitLab fortunately also comes with an image for that. I have used the following container creation script:
docker run --detach \
--network mynetwork \
--name gitlab-runner \
--restart always \
--volume /srv/gitlab-runner/config:/etc/gitlab-runner \
--volume /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
As you can see, this container will also run on network ‘mynetwork’. There are no new options
here, however we’ll pay special attention --volume /var/run/docker.sock:/var/run/docker.sock.
Since our runner will be running Docker containers for the builds, it needs to be able to
control the host’s Docker daemon. This is done by mapping the host’s Docker socket to the
container.
After running this command, running docker ps should show you a new container with the name ‘gitlab-runner’.
Linking the runner to GitLab
So now we have GitLab itself running, and alongside of it we have a runner. Now it’s time to link these two together. We’ll have to initialize the runner only once, and we can do that by executing a command inside of the container. Note that you need to copy the runner initialization token from the GitLab admin interface.
docker exec gitlab-runner gitlab-runner register \
--non-interactive \
--url http://gitlab/ci \
--registration-token TOKEN \
--description "Docker runner" \
--tag-list "docker" \
--executor docker \
--docker-image "ubuntu:latest"
Let’s understand what will happen here. We are about to initialize the runner, and a runner
runs a specific executor. In this case we have selected the Docker executor, because we want
to run our builds using Docker. The --executor argument is selecting the Docker executor,
and the --docker-image selects the default image to run your builds with. The --tag-list
argument is a space delimited list of tags we want to apply to the executor, so GitLab can
select the right runner for you. Finally, the --url argument refers to the GitLab instance.
Since we are running in a Docker network, we can use the name of the GitLab container as a
hostname, and Docker will resolve the correct ip-address for you.
The initialization script should register the runner to the GitLab, and it should now show up in the admin interface.
Setting up .gitlab-ci.yml
Now that we have a Docker runner available, we can set up a GitLab project to use it. This
is done through the .gitlab-cy.yml file in the root of your Git repository. The availability
of this file enables CI in your project.
Since your project might want to run on a different image during the build process, we simple need to define this image in the YML file. In my case for example I’m running on Maven 3 and JDK 8, defining it as follows:
image: maven:3.3.9-jdk-8
stages:
- build
buildMaven:
script: "mvn clean package"
stage: build
tags:
- docker
As you can see, the selected image is maven:3.3.9-jdk-8. It runs on the Docker runner
because the build uses the docker tag, which was linked to the runner when we were setting
it up.
Conclusion
You should now be able to run your builds using Docker containers. As you can see, it’s quite easy to set up. Hopefully the combination of running GitLab on Docker and simultaniously running your CI builds on Docker will be better documented in the future.