Gitlab-CIを用いてDockerfileを自動更新
目的
Railsの実行環境・デプロイ環境を整えてみたい。
今後やりたいこと
- Railsを動かすコンテナイメージを自力で作成する。
- KubernetesのManifestを作成して、Railsを動かすPodを立ててみる。
- Railsのコードに更新が入ると、Pod上のスクリプトに自動で更新される。
文献を漁る
- GitlabCIを用いて、のコードに更新が入ると、Pod上のスクリプトに自動で更新される
- GitlabCIで
kubectl
コマンドを叩いて自動デプロイ!をやろうとした。
しかし、こちらの記事を読んでいる感じだと、よくないらしい。
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とは
- ビルドやデプロイのコマンドを手動で叩くのは面倒...
- 自動化できるならしたい!という話。
以下のメリットがある。
- コミットしたときに、自動実行してくれることで、開発効率が高まる。
- 人間が気づきにくいミスや作業漏れ防止につながる。
- テスト、本番環境へのデプロイ基準の明確化。
今回やること
- Dockerfileを修正すると、Gitlab Runnerがイメージビルドを実行。
- Gitlabのコンテナレジストリにコンテナイメージをプッシュする。
Gitlab Runnerを活用する
.gitlab-ci.yml
を作成すれば、Gitlab Runnerが自動で.gitlab-ci.yml
を読み込んで、パイプラインを実行してくれる。つまりGitlabにリポジトリにコミットを投げるだけで、簡単にCI/CDを実現してくれるわけだ。
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
結果
パイプラインは問題なく実行完了。
おまけ:カスタム変数の設定で注意
Protected ... 保護されたブランチ(一般的にはmainもしくはmaster)や保護されたタグ以外では設定されません。これらのブランチやタグのプッシュはMainteinerロール以上でしかできないため、それ未満のロールの開発チームのメンバーから値を隠す効果があります。
開発用ブランチから.gitlab-ci.yml
を修正したコミットをプッシュして、CIの動作を検証していました。しかし、CI変数のProtectedにチェックをつけていると、mainやmasterブランチなど保護されているブランチ以外では設定されないようです。
clone自体はどのユーザーでもできるし、そこからPushは可能が自由なブランチからだったので、秘匿情報を保持するCI変数の公開範囲を守ってくれていたのかもしれません。
Discussion