👻

Gitlab-CIを用いてDockerfileを自動更新

2023/05/25に公開

目的

Railsの実行環境・デプロイ環境を整えてみたい。

Gitlab Runner初心者なので、一旦、CI/CDの基礎から触ることに。

CI/CDとは

  • ビルドやデプロイのコマンドを手動で叩くのは面倒...
    • 自動化できるならしたい!という話。

以下のメリットがある。

  • コミットしたときに、自動実行してくれることで、開発効率が高まる。
  • 人間が気づきにくいミスや作業漏れ防止につながる。
  • テスト、本番環境へのデプロイ基準の明確化。

https://www.redhat.com/ja/topics/devops/what-is-ci-cd

今回やること

  • Dockerfileを修正すると、Gitlab Runnerがイメージビルドを実行。
  • Gitlabのコンテナレジストリにコンテナイメージをプッシュする。

Gitlab Runnerを活用する

.gitlab-ci.ymlを作成すれば、Gitlab Runnerが自動で.gitlab-ci.ymlを読み込んで、パイプラインを実行してくれる。つまりGitlabにリポジトリにコミットを投げるだけで、簡単にCI/CDを実現してくれるわけだ。

https://gitlab-docs.creationline.com/ee/ci/introduction/

https://gitlab-docs.creationline.com/ee/ci/yaml/

.gitlab-ci.yml
image: docker:20.10.7
services:
  - name: docker:20.10.7-dind
    alias: docker
default:
  script:
    - echo "hello"
    - docker run -itd --name tmp alpine:latest
    - docker run -itd --name tmp2 alpine:latest
    - docker container ls
  only:
    - master

stages:
  - build
  - test
  - commit

before_script:
  - docker login -u  $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

# 開発用イメージを検証
build_container_image:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE/myapp:dev .
    - docker run --rm -p 3001:3000  $CI_REGISTRY_IMAGE/myapp:dev /bin/bash
    - docker push $CI_REGISTRY_IMAGE/myapp:dev
  rules:
    - changes:
       - Dockerfile
       
# なくても良い
test_container_image:
  stage: test
  script:
    - echo $CI_REGISTRY_IMAGE
    - echo $CI_REGISTRY_USER
    - echo $CI_PIPELINE_IID

# テストが通れば、本番用にプッシュ
commit_container_image:
  stage: commit
  script:
    - docker pull $CI_REGISTRY_IMAGE/myapp:dev
    - docker tag $CI_REGISTRY_IMAGE/myapp:dev $CI_REGISTRY_IMAGE/myapp:$CI_PIPELINE_IID
    - docker push $CI_REGISTRY_IMAGE/myapp:$CI_PIPELINE_IID
  rules:
    - changes:
       - Dockerfile

苦戦ポイント

ビルドとコンテナ実行を別ジョブで定義すると、コンテナ実行時にローカルでコンテナイメージがありません、と言われた。

なぜなら、各ステージで実施されるジョブのプロセスは独立している。
そこで、ビルドで生成したイメージを受け継いでコンテナ実行をするには、同ジョブで実行するようにした。途中でイメージレジストリにイメージをPush/Pullなどして、ローカルにコンテナイメージを取得するなどしても良いかもしれない。

# 怒られた例
- job1: Build
- job2: Run x (ローカルにイメージがない)

# 結局同ジョブにまとめた
- job1: Build -> Run -> Push

https://stackoverflow.com/questions/76044199/gitlab-runner-can-not-find-docker-image-after-build

結果

パイプラインは問題なく実行完了。

おまけ:カスタム変数の設定で注意

Protected ... 保護されたブランチ(一般的にはmainもしくはmaster)や保護されたタグ以外では設定されません。これらのブランチやタグのプッシュはMainteinerロール以上でしかできないため、それ未満のロールの開発チームのメンバーから値を隠す効果があります。

https://www.gitlab.jp/blog/2022/12/12/ci-cd-variables/#ciジョブで環境変数として利用する

開発用ブランチから.gitlab-ci.ymlを修正したコミットをプッシュして、CIの動作を検証していました。しかし、CI変数のProtectedにチェックをつけていると、mainやmasterブランチなど保護されているブランチ以外では設定されないようです。

clone自体はどのユーザーでもできるし、そこからPushは可能が自由なブランチからだったので、秘匿情報を保持するCI変数の公開範囲を守ってくれていたのかもしれません。

Discussion