Help us understand the problem. What is going on with this article?

DockerのGitLab Runnerを使ってローカルでCI/CDを動かす

概要

ローカルのDockerコンテナ上にGitLabにてCIを動かすためのセッティングをします。
単純にGitlab Runnerの使用方法の記事はわかりやすいものがたくさんありますが、docker for macだと特殊なハマりポイントもあるので改めてまとめました。
(そもそもGitlabをローカルで使うゴリゴリ使うことはあまりないかもしれないですが)

今回のゴール

GitLabでコミットを検知したらDockerコンテナが起動し、コンテナの中でphpファイルの構文チェックが走るようにする

環境

version
ホストOS MacOS 10.14.6
Docker 19.03.5, build 633a0ea
gitlab-ce Image gitlab/gitlab-ce:12.6.4-ce.0
gitlab-runner Image gitlab/gitlab-runner:v12.7.1

※Imageのバージョンは2020/2/10時点でのlatest

GitLab Runnerとは

Gitlabと連携し、プロジェクトのコミットを検知して動作するジョブの実行環境です。
GitLab上にはGitlab CI/CDという管理ツールがあり、ジョブの実行ログなどを管理できます。
公式ドキュメント

Runnerの種類

Runnerには共有範囲が3種類あります。

  • Shared : 全プロジェクトで共有
  • Group : 同一グループ内で共有
  • Specific : プロジェクト占有

Runner自体はあくまで実行環境なので、ジョブの中身はプロジェクト毎に記載することになります。
特化した環境ならSpecific、汎用的ならShared、といった使い分けになると思われます。

Executor

ジョブの実行方法(Executor)にはいくつか種類があり、ジョブ毎に設定することができます。
簡単なものであればサーバ内で実行するShell Executor、実行環境を気にするジョブの場合はコンテナを個別に起動させるDocker Executorを用いるなど、臨機応変に使い分けることができます。
(Executor一覧はこちら)

Dockerコンテナの構築

まずはdocker-composeを用いてコンテナを作ります。
今回は172.20.10.1/24のネットワーク内にgitlab本体とrunnerのコンテナを作ります。

version: '3.5'

services:
  gitlab:
    container_name: gitlab
    image: gitlab/gitlab-ce:latest
    hostname: 'gitlab-local'
    restart: always
    networks:
      gitlab_net:
       ipv4_address: 172.20.10.2
    environment: 
      GITLAB_OMNIBUS_CONFIG : |
        external_url 'http://gitlab'
        unicorn['socket'] = '/opt/gitlab/var/unicorn/gitlab.socket'
        gitaly['internal_socket_dir'] = '/var/opt/gitlab/gitaly/soc'
    ports:
      - '1080:80'
      - '1443:443'
      - '1024:22'
    volumes: 
      - './gitlab/config:/etc/gitlab'
      - './gitlab/logs:/var/log/gitlab'
      - './gitlab/data:/var/opt/gitlab'
  gitlab_runner:
    container_name: gitlab_runner
    image: 'gitlab/gitlab-runner:latest' 
    hostname: gitlab-runner
    restart: always
    networks: 
      gitlab_net:
        ipv4_address: 172.20.10.3
    volumes:
      - ./gitlab-runner/config:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
networks: 
  gitlab_net:
    name: gitlab_net
    driver: bridge
    ipam: 
      driver: default
      config:
        - subnet: 172.20.10.1/24

コンテナ作成上の注意

  • GITLAB_OMNIBUS_CONFIGの下2つの設定はdocker for macでgitlabを使う場合に起こる問題への対策です。詳しくはこちら
  • docker-composeのバージョン3.5以降の記法でしかnetworksに固定名称を与えられません。(公式のリリース情報)

Runnerの登録

コンテナを立ち上げてgitlab自体にアクセスできたら、続いてRunnerの登録をしていきます。
なお、今回はプロジェクト占有型のSpecificで設定を進めます。

トークンの取得

登録にはGitlab CIのトークンが必要になります。
「対象のプロジェクト」>「Settings」>「CI/CD」と進み、「Runner」の項目を開くと以下のような画面が表示されるので、トークンをコピーしておきます。
スクリーンショット 2020-02-22 15.49.21.png

Runnerのセットアップ

トークンを取得できたらRunnerにトークンをセットします。
これによって、Gitlab本体とRunnerが連携され、ジョブを実行できるようになります。
なお、今回はphpのインストールが必要ということもあり、Docker Executorを採用します。

セットアップにはRunnerのコンテナを立ち上げた状態で以下のコマンドを実行します。

docker exec -it gitlab_runner gitlab-runner register \
 --url "http://gitlab" \
 --registration-token "コピーしておいたトークン" \
 --name "docker_php" \
 --tag-list "docker_php" \ 
 --executor "docker" \
 --docker-image "php:7.4.3-apache" \
 --docker-network-mode "gitlab_net" \
 --docker-pull-policy "if-not-present"

ポイントは、必ずdocker-network-modeでGitlab本体と同じネットワークを指定することです。
docker for macの場合、私の知る限りSocksプロキシなどを使わないとホストOSからドメインで当たれないので、こうしないとジョブ実行時に立ち上がるコンテナからGitlab本体にアクセスができず詰みます。

このコマンドを実行すると、対話形式で各設定項目について確認されますが、オプションで指定してあればそれがデフォルトになるのでEnterを連打していればOKです。
(逆にオプション1つもつけず対話形式で設定を入力する方法もあります)

設定が成功すると先ほどの画面に有効なRunnerとして表示されます。

スクリーンショット 2020-02-23 0.41.36.png

ジョブの作成

実行環境となるRunnerの登録が完了したので、いよいよ実際に実行するジョブを作成します。
.gitlab-ci.ymlという名前のファイルを実際に使用したいプロジェクト直下にを配置することでジョブの定義を行います。

なお、プロジェクトのTOPに表示されるSet up CI/CDを押すと.gitlab-ci.ymlの作成画面が表示されます。
スクリーンショット 2020-02-23 22.55.37.png

いくつかテンプレートも用意されていますが、今回はただコマンドラインで構文チェックできればいいので手で作ります。

lint:
    tags:
        - docker_php
    script: 
        - pwd
        - echo 'start lint'
        - php -l ./test.php

lintはジョブの名前で、自由に命名することができますし、複数のジョブを定義することもできます。
scriptにはジョブの中で実行するコマンドを記載します。今回はほぼlintを走らせているだけです。
tagsにはRunnerの登録時に記入したタグを記載します。これによって、1つのプロジェクトでもジョブによって実行環境を変えることができます。
※もっと色々設定できるので興味ある方は公式ドキュメントへどうぞ

実行結果の確認

以上でジョブの設定は完了しました。
肝心なtest.phpを用意していなかったので、以下のファイルをpushして実行結果を確認していきます。

<?php
echo 'Hello World!';

実行結果は「CI/CD」>「Pipeline」または「CI/CD」>「Jobs」から確認できます。
スクリーンショット 2020-02-23 23.56.37.png

ここで今回の結果を選択し、さらにジョブを選択すると実行内容の詳細を確認できます。
スクリーンショット 2020-02-24 0.00.54.png
スクリーンショット 2020-02-24 0.03.07.png

今回は問題のない記述だったので普通に成功しています。
次に、問題があるファイルをpushしてみます。

<?php
echoooo 'Hello World!';

すると、先ほどはPassedだったのがFailedになりました。
スクリーンショット 2020-02-24 0.09.59.png

さらに実行の詳細をみてみます。
スクリーンショット 2020-02-24 0.12.39.png

しっかりシンタックスエラーが出ています。
これで問題のある記述がある場合は簡単に検知することができますし、どこに問題があるのかもわかります。

感想とまとめ

mac特有の問題で何度かくじけかけましたが、なんとか無事lintを走らせることができました。

実用的にするにはもっと.gitlab-ci.ymlを作りこむ必要がありますが、ひとまずここで切ります。
今後はユニットテストやデプロイ的なことも含め、複数のジョブを走らせたり色々試してみたいと思います。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした