👻

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

2023/05/25に公開約3,400字

目的

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

今後やりたいこと

  • Railsを動かすコンテナイメージを自力で作成する。
  • KubernetesのManifestを作成して、Railsを動かすPodを立ててみる。
  • Railsのコードに更新が入ると、Pod上のスクリプトに自動で更新される。

文献を漁る

  • GitlabCIを用いて、のコードに更新が入ると、Pod上のスクリプトに自動で更新される
  • GitlabCIでkubectlコマンドを叩いて自動デプロイ!をやろうとした。

https://www.weave.works/blog/why-is-a-pull-vs-a-push-pipeline-important

しかし、こちらの記事を読んでいる感じだと、よくないらしい。

The reason you don’t want to use your CI system as the basis for your deployments is because of the potential to expose credentials outside of your cluster. While it is possible to secure your CI scripts.

どうやらcredintialsな情報を外部へ公開してしまうリスクがあるようです。

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

ログインするとコメントできます