はじめに
皆さんは「kaniko」をご存じでしょうか?何やら某プロレタリア文学を彷彿とさせる名称1をしていますが、これは Docker in Docker (以下DinD) を使わずに Docker Image をビルドしてくれるとっても便利なソフトウェアです。なお開発元は Google のようです。DinD を使わないおかげで、よりセキュアに Docker Image をビルドすることができます。また、キャッシュもサポートしているため、ビルド時間の短縮効果も見込めます。
この記事では、そんな kaniko を GitLab CI で動かして、各種 Docker Registry に全自動でプッシュする方法をご紹介します。
れっつ GitLab CI
今回は以下の4種類のプッシュ先における .gitlab-ci.yml
の書き方をご紹介します。それぞれお作法が違いますので、その点に注意しつつ解説します。
- Docker Hub
- GitLab Container Registry
- AWS ECR
- GCP GCR
大まかなビルドの流れ
基本的に docker image build
するときと同様で、以下のような順序でビルドならびにプッシュをします。ただし、いつもと違ってビルドとプッシュが1コマンドで行えるように変更されています。
- kaniko-project/executor イメージの取得
- Container Registry へのログイン
- image のビルド & プッシュ
なお、kaniko-project/executor
の ENTRYPOINT
が /kaniko/executor
に設定されている都合上、このイメージ自体を使ってビルドを行う際に不都合が生じる2ため、シェルが含まれる debug
タグのついたイメージを使った上で、entrypoint
を強制的に上書きします。つまり、ビルドしたいステージで指定する Docker イメージは少し長くなりますがこのように記述することになります。
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
また、ビルドとプッシュは kaniko-project/executor
イメージに含まれる /kaniko/executor
というバイナリを使って行います。このとき、--context
オプションに $CI_PROJECT_DIR
を、 --dockerfile
オプションに $CI_PROJECT_DIR/Dockerfile
をセットすることで、どのディレクトリでビルドを行うのかをこのコマンドに伝えなければなりません。なお、ここで使われている環境変数は GitLab CI によってデフォルトで提供されているものなので、自分で設定する必要がありません。
さらに --destination
でイメージ名とタグ付けを行うようにしましょう。この --destination
オプションは複数渡すことができますので、latest
と dev
など同じイメージに対して複数のタグ付けを同時に行う際に活用してください。
$ /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination IMAGE_NAME:latest --destination IMAGE_NAME:TAG
Docker Hub
まずは Docker Hub へのプッシュ方法です。先に Docker Hub へのユーザー名とパスワードをコロンで繋いだものを base64 エンコードした文字列を用意しておきます。これを DOCKERHUB_TOKEN
として GitLab CI の variable に保存しておいてください。.gitlab-ci.yml
へのベタ書きは危ないのでやめておきましょう。
$ echo -n USER:PASSWORD | base64
続いてこのトークンを使って Docker Hub にログインする設定を /kaniko/.docker/config.json
に書き込みます。今回は echo
コマンドを使って流し込んでしまいます。あとは上で説明したとおりに executor
コマンドを走らせてあげればビルドとプッシュを行ってくれます。
stages:
- build
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- echo "{\"auths\":{\"https://index.docker.io/v2/\":{\"auth\":\"${DOCKERHUB_TOKEN}\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination IMAGE_NAME:TAG
GitLab Container Registry
こちらも認証情報を echo
コマンドで /kaniko/.docker/config.json
に書き込んでいますが、GitLab CI が認証情報をあらかじめ環境変数に詰めてくれているので、特別な設定は不要になっています。
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
AWS ECR
まず ECR にプッシュできる権限を持った IAM ユーザーを作り、その Access Key ID
と Secret Access Key
を取得しておきます。次にそれらの値をそれぞれ AWS_ACCESS_KEY_ID
ならびに AWS_SECRET_ACCESS_KEY
の名前をつけて GitLab CI の variables として保存しておきます。kaniko は内部に amazon-ecr-credential-helper
を含んでいるため、AWS CLI を導入しなくても、以上の環境変数から自動的に認証を行ってくれます。
ただし、AWS の認証を行うための設定を /kaniko/.docker/config.json
に書き込む必要がありますので、以下のように echo
コマンドで流し込みます。蛇足ですが、ECR のアドレスは長くなりがちなので、適当な環境変数に切り出しておくと取り回しが良いと思います。
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
variables:
ECR_URL: 0000111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/image_name
script:
- echo "{\"credsStore\":\"ecr-login\"}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination ${ECR_URL}:TAG
GCP GCR
こちらも AWS と似た手順となります。まず GCR にプッシュできる権限を持ったサービスアカウントを発行しておき、その json キーファイルの中身をまるごと GCP_TOKEN
などの名前で GitLab CI の variables に保存しておきます。CI の中でこの環境変数から適当な場所に JSON ファイルを書き戻し、GOOGLE_APPLICATION_CREDENTIALS
環境変数にそのパスをセットしてあげることで、認証が自動で行われます。ここは Google 謹製なだけあって簡単に行えるように作られています。
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
variables:
GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcloud-service-key.json
before_script:
- mkdir /tmp
- echo ${GCP_TOKEN} > /tmp/gcloud-service-key.json
script:
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination "asia.gcr.io/${PROJECT_ID}/image_name:TAG"
おわりに
この記事では Container Registry ごとの認証周りを中心に kaniko を使った Docker Image のビルド方法について解説してきました。公式ドキュメントでは Kubernetes 環境を前提とした利用方法を中心に紹介されていて、Gitlab CI を含む各種 CI でどのように kaniko を使えば良いのかという資料が掲載されていませんでしたので、まとめてみた次第です。皆さんも kaniko を使ったセキュアな Docker Image ビルド環境を作ってみてください!
参考資料
- GoogleContainerTools/kaniko: Build Container Images In Kubernetes
- Building images with kaniko and GitLab CI/CD