Speed up GitLab CI by using custom Docker images
So, we have:
- GitLab server, up and running.
- GitLab runner, registered and ready for some action.
- Built-in Docker registry is configured.
- A project hosted on that GitLab server, with some custom
.gitlab-ci.yml
that might look like this (minimal example just to show the context):
stages:
- buildbuild_job:
stage: build
image: alpine:latest
script:
- |
apk add openssl curl bash git ...
# some build commands follow
See that apk add …
thing? It installs tools essential for your building process, but it takes time every time the job is executed. It might not be a problem if the list is short, but in case a custom build of OpenJDK or PHP interpreter or anything else like that is needed, optimization is due.
One way to optimize this is to build custom image: we have that image: alpine:latest
, and then apk add …
— why not combine all of that into a Dockerfile
:
FROM alpine:latest
RUN apk add openssl curl bash git ...
Now, we have full GitLab up and running, and we can use it to build that Dockerfile into nice image, automatically:
- Create new project.
- Add this Dockerfile to its root.
- Ensure Auto-DevOps are enabled for the project (by default it’s true for new projects), and runner is able to pick it up.
- Probably you should also add
TEST_DISABLED
andCODE_QUALITY_DISABLED
variables in CI/CD settings to skip these stages for our custom image to reduce noise in GitLab pipelines.
At this point first build of the custom image probably has passed, and you can find resulting artifact in Docker registry tagged as latest
: in Packages & Registries (left-side menu) you should be able to find one registry for your builder project, and there should be two tags that point to the same image, one equals to git commit hash, the other one is latest
. Clicking clipboard icon next to the tag will result in something like this:
registry.your-gitlab-domain.com/your-group/your-builder-project:latest
And that’s it! Now we can modify.gitlab-ci.yml
:
stages:
- buildbuild_job:
stage: build
image: registry.your-gitlab-domain.com/your-group/your-builder-project:latest
script:
- |
# some build commands follow
So, all required tools are baked into automatically built image hosted on the same GitLab server, and that should decrease build time by fair amount.
One caveat, though: user who triggers build (e.g. by pushing new commit) should have read access to builder project, otherwise GitLab runner won’t be able to download builder image.