まえがき
インフラエンジニアの 冨田(@komitta)です。今回はデプロイのお話です。
弊社で運用しているエキテンでは一部EC2の構成も稼働していますが、コンテナを使った環境も存在しています。今回はこのコンテナでのデプロイについてお話します。
これまでのコンテナのデプロイ方法
エキテンではEC2上で構築したGitLabサーバーのGitLab CIを使ってデプロイを行っています。GitLab CIを動かす runnerはスポットインスタンスで起動したEC2のdocker+executorで実行しています。
EC2へのファイルデプロイやビルドコンパイル、テストCIの実行であれば特に問題はないのですが、Dockerイメージのビルドをこのdocker runner 上で動かすには通常のDockerイメージでは実行できないので、検討が必要になります。
これまでdocker runner 上でのDockerイメージビルドにはDocker in Docker (以下dind) *1を使用していました。
dindの仕組みとしてprivileged オプションを使うことでホストOS側の権限を開放してDockerコンテナ上でDocker デーモンを操作しているため、コンテナからホストOSに影響を与えることからセキュリティの面で望ましくないです。
そのため、Dockerデーモンを使わないビルドツールのkaniko *2を使用してみました。
kaniko を使ったDockerイメージビルド
GitLabのマニュアルページにkanikoを使用したDockerイメージビルド*3があるのでそれに沿って行いました。
以下設定においてハマった部分を紹介します。
独自ドメインで自前の証明書を使用する場合
弊社のGitLabサーバーはEC2上に構築しており、証明書も自前で用意しています。
自前の証明書を使っている場合、ビルド時に以下のエラーが出力されます。
error building image: getting stage builder for stage 0: Get https://***********/v2/: x509: certificate signed by unknown authority
そのため、証明書本文をGitLabの環境変数に記載し /kaniko/ssl/certs/additional-ca-cert-bundle.crt
ファイルに追記することでエラーを回避しています。
image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - echo "$REGISTRY_CERT" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt
上記は設定でREGISTRY_CERT という名前でGitLabの環境変数の値に証明書本文を登録しているときの例です。
GitLab Container RegistryとAWS ECRの併用する場合
エキテンで使用するDockerレジストリは、GitLab Container Registry と AWS ECRを使用しています。
用途の使い分けとしてローカル開発環境上で使用するDockerイメージはGitLab Container Registryを使用し、サービス側で使用するDocker イメージはAWS ECRを使用しています。
ビルド実行コマンド実行前に /kaniko/.docker/config.jsonにauths 情報を記載することで認証することができます。
- GitLab Container Registryの認証方法*4
image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - echo "$REGISTRY_CERT" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - echo "$REGISTRY_CERT" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt - echo "{\"auths\": \"credHelpers\":{\"<aws_account_id>.dkr.ecr.<region>.amazonaws.com\":\"ecr-login\"}}" > /kaniko/.docker/config.json
また、エキテンではマルチステージビルド*6を用いて、GitLab Container Registryに配置されたイメージ(ミドルウェア情報等を格納)をベースとし、アプリを含んだサービスで公開するイメージについてはAWS ECRにPushする運用を取っているため、ビルド時にはGitLab Container RegistryとAWS ECRに対して2つの認証がされている必要があります。
その場合は、以下の記載をすることで2つのレジストリに対して認証することができます。
image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - echo "$REGISTRY_CERT" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}},\"credHelpers\":{\"<aws_account_id>.dkr.ecr.<region>.amazonaws.com\":\"ecr-login\"}}" > /kaniko/.docker/config.json
まとめ
kaniko を 使ったGitLab Container RegistryとAWS ECR の認証方法について 紹介しました。
レジストリ単体の設定方法についてはよく事例にあげられますが、今回のように同時に認証が必要な場合の設定方法について情報が少なかったので少し苦労しました。
kanikoを使用する場合の参考になれば幸いです。
おわりに
仲間を募集しております
募集中の職種については以下を御覧ください。
*1:https://esakat.github.io/esakat-blog/posts/docker-in-docker/
*2:https://github.com/GoogleContainerTools/kaniko
*3:https://docs.GitLab.com/ee/ci/docker/using_kaniko.html
*4:https://docs.GitLab.com/ee/ci/docker/using_kaniko.html
*5:https://github.com/awslabs/amazon-ecr-credential-helper
*6:https://docs.docker.jp/develop/develop-images/multistage-build.html