【GitLab CI】パイプラインのジョブでイメージをあらかじめ作って高速化
前置き
GitLab CI パイプラインのジョブで、毎回イメージを生成しなおしていると、ジョブの実行時間が非常に遅いです。
1ジョブに対して、毎回Dockerイメージをpullして起動しなおすので、非常に非効率です。
事前に作っておけたら最高だよねということで、今回はコンテナレジストリという機能を使って、ジョブを高速化します。
さらに、手動でやるのも面倒なので、コンテナレジストリ自体もジョブで自動化します。
設定
.gitlab-ci.yml
stages:
- build_gitlab_runner_image
- build_deploy
# GitLab Runnerイメージのビルド
build_gitlab_runner_image:
stage: build_gitlab_runner_image
image: docker:28.5.2-cli
services:
- name: docker:28.5.2-dind
rules:
- if: '$CI_COMMIT_BRANCH == "develop"'
when: on_success
changes:
- runner/develop/**/*
script:
# GitLabコンテナレジストリへ接続
- docker login --username $CI_REGISTRY_USER --password $CI_REGISTRY_PASSWORD $CI_REGISTRY
# 軽量イメージからビルド
- docker build --tag $CI_REGISTRY_IMAGE/alpine_ssh -f ./runner/develop/alpine_ssh/Dockerfile .
# GitLabコンテナレジストリへプッシュ
- docker push $CI_REGISTRY_IMAGE/alpine_ssh
# ビルドデプロイ
build_deploy:
stage: build_deploy
# GitLabコンテナレジストリへプッシュしたイメージを指定
image: registry.gitlab.example.com/root/test-project/alpine_ssh:latest
script:
# ビルド・デプロイを良しなに…
Dockerfile
FROM alpine:latest
RUN apk update && \
apk upgrade && \
apk add --no-cache curl && \
apk add --no-cache wget && \
apk add --no-cache grep && \
apk add --no-cache openssh-client
Dockerfileはビルドに必要な形で、各々調整ください。
コンテナレジストリ
上記ジョブを実行できると、コンテナレジストリにこんな形でpushされます。

このイメージを.gitlab-ci.ymlで指定することで、いちいち作り直さなくても同じイメージを使ってくれます。
注意点
dind(Docker in Docker)
.gitlab-ci.ymlのservicesにdind(Docker in Docker)を指定して、Dockerの中でDockerを使用します。
これによりパイプラインのジョブの中からDockerを操作できます。
注意点としては、imageとservicesに指定しているタグ(バージョン)を一致させる必要があります。
どうも最新同士で使うと実行タイミングによっては一致しなくて、依存関係でエラーになることがあるので、絶対指定をおすすめします。
・NGパターン
build_gitlab_runner_image:
stage: build_gitlab_runner_image
image: docker:latest
services:
- name: docker:dind
・OKパターン
build_gitlab_runner_image:
stage: build_gitlab_runner_image
image: docker:28.5.2-cli
services:
- name: docker:28.5.2-dind
まとめ
GitLabのコンテナレジストリを使って、ジョブを高速化できました。
毎度長い時間待っていたストレスから解放されました。
ビルドとアプリのDockerイメージバージョンが一致してないと、いろいろ問題も出てきますし、
コードで管理出来て自動化できたので、一石二鳥です。
以上、ここまで見ていただきありがとうございます。
皆さまの快適な開発ライフに、ほんの少しでもお役に立てれば幸いです。