One of the reasons I moved to GitLab is that it provides free private repos as well as free CI. It’s CI is based around Docker images which makes it dead easy to build any sort of project from GitLab.
I thought I’d share with you here the simple configuration I use to build things (such as this blog) and put it on to my web-hosting.
To tell GitLab you want to use their CI, you create a file .gitlab-ci.yml
in the root of your
repo. If this file starts with image:
then GitLab knows it’s a Docker build and will use the
appropriate runner. However, this is a general file and you can use any the various runners for
doing your builds (see
GitLab’s documentation
but Docker is as general as it gets.
You must specify a Docker image from The Docker Hub although you can also use a local GitLab repo with your own images if you want. As the example I’m showing here is for this Jekyll-based blog (which is Ruby-based), we use a Ruby image:
image: ruby:2.3
The next section contains some script-wide variables that can be used for keeping your scripts tidy. So, I ensure that Jekyll is going to be in production mode:
variables:
JEKYLL_ENV: production
Next comes some bigger sections. The build
section tells GitLab how to build your code after it has
checked out your repo into the container. The deploy
section tells GitLab how to deploy your code
after it has checked it out into a container. Each of these sections runs as a separate docker process
in GitLab and they do not share the same container.
So, the first section is this:
1
2
3
4
5
6
7
8
9
10
11
build pages:
stage: build
before_script:
- bundle install
script:
- bundle exec jekyll build
artifacts:
paths:
- _site
only:
- master
We give the build a name: pages
and it’s the build
stage. In the before_script
section (line 3), each
line gives a shell command to run before we do the build. Here’s we’re ensuring we have all our gems.
Each line in the script
section (line 5) performs the build.
One of the most important parts here is the artifacts
section (line 7) which allows us to pass the result of
the build on to another stage of the pipeline. If we don’t do this, when the Docker container shuts down
we lose everything. Here we tell it to remember the contents of _site
, which is where Jekyll outputs
the fixed HTML to.
So that’s the build done. Now we need to deploy that to my hosting. If you’re hosting on GitLab or GitHub,
moving this output to public
and committing the result is enough.
However, I need to SSH to my own hosting provider to put my blog up there. Doing that requires us to set some SSH keys in the server and GitLab to ensure that the container can talk to my hosting.
To do this, generate a key-pair on your server (on the hosting box) with:
ssh-keygen -t rsa -C "your.email@example.com" -b 4096
Grab the contents of the ~/.ssh/id_rsa
file and in GitLab’s settings for your project,
under Settings > Pipelines
add a new variable called SSH_PRIVATE_KEY
and paste the contents of
that file as the value. The environment can stay *
. This lets GitLab log into your host without
requiring a password; but only if the server is trusted.
To allow the server to be trusted, you also need to generate a value for SSH_SERVER_HOSTKEYS
and
add that as a variable. You can do that with:
ssh-keyscan <YOUR-SERVER>
Paste the result of that command as the value of the new variable.
Alone, these two variables do nothing, but in our deploy script we update the container with these keys so that it has access to the host. These keys are stored securely in GitLab, behind your username and password, and the Docker container is only running for the duration of the build.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
deploy to site:
stage: deploy
variables:
GIT_STRATEGY: none
before_script:
# Install ssh-agent if not already installed, it is required by Docker.
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
# Run ssh-agent
- eval $(ssh-agent -s)
# Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
- ssh-add <(echo "$SSH_PRIVATE_KEY")
# In order to properly check the server's host key, assuming you created the
# SSH_SERVER_HOSTKEYS variable previously, uncomment the following two lines
# instead.
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts'
script:
- scp -r _site/* <username>@blog.dupplaw.uk:<path in my hosting>
dependencies:
- build pages
There is more about the SSH process on GitLab’s documentation.
Once all the SSH keys are set up, a simple scp
(line 21) is all that’s needed to get the files on to my hosting.
One interesting variable in the deploy script, is the GIT_STRATEGY
variable defined on line 4. This tells
GitLab not to bother checking out your repo into the container. The deployment is only using the result
of the previous stage, so it doesn’t need the repo. This saves time during the build.
GitLab’s CI is incredible. It’s free and easy to use and supported by Digital Ocean, one of the big Docker hosting suppliers. I’m using it for lots of my personal projects now. How are you using it?
Comments: