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

GitLab CI で kaniko を使って Docker Image をビルドしてみる

はじめに

皆さんは「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コマンドで行えるように変更されています。

  1. kaniko-project/executor イメージの取得
  2. Container Registry へのログイン
  3. image のビルド & プッシュ

なお、kaniko-project/executorENTRYPOINT/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 オプションは複数渡すことができますので、latestdev など同じイメージに対して複数のタグ付けを同時に行う際に活用してください。

$ /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 IDSecret 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 ビルド環境を作ってみてください!

参考資料


  1. Issueはあるのですが名称の由来は依然不明です。 

  2. そのままだとコマンドが一瞬動いてすぐコンテナが終了してしまいます。 

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