Gitlab Runner で実行するジョブのイメージを Amazon ECR から Pull する方法(ジョブの中で docker pull
という話ではなく)。
要するに .gitlab-ci.yml
で下記のように ECR のイメージを指定できるようにするということです。
test:
stage: test
image: 999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/oreore:latest
script:
- make test
前提として Gitlab Runner が docker-credential-ecr-login (amazon-ecr-credential-helper) の Credentials store を使って ECR にログインできるようにする必要があるため、Gitlab Runner のイメージに docker-credential-ecr-login
を追加したイメージを作成しました。
手順
# ディレクトリを準備
mkdir -p /opt/gitlab-runner/{ecr,runner}
# 環境変数で AWS 認証情報を指定
cat <<'EOS'> /opt/gitlab-runner/.env
AWS_ACCESS_KEY_ID=AKI...
AWS_SECRET_ACCESS_KEY=abc123...
EOS
# Gitlab Runner を開始
# --env-file で環境変数ファイルを指定
docker run --detach \
--name gitlab-runner \
--env-file /opt/gitlab-runner/.env \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume /opt/gitlab-runner/runner/:/etc/gitlab-runner/ \
--volume /opt/gitlab-runner/ecr/:/root/.ecr/ \
ngyuki/gitlab-runner:alpine
# Gitlab に Runner を登録
# DOCKER_AUTH_CONFIG で Credentials store を指定
docker exec gitlab-runner gitlab-runner register \
--non-interactive \
--url 'http://gitlab.example.com/' \
--registration-token "${REGISTRATION_TOKEN:?}" \
--name 'docker-runner-with-ecr' \
--executor 'docker' \
--docker-image 'alpine:latest' \
--env 'DOCKER_AUTH_CONFIG={"credsStore":"ecr-login"}'
# docker-credential-ecr-login get で ECR 認証情報を `~/.ecr/cache.json` に保存
echo 999999999999.dkr.ecr.ap-northeast-1.amazonaws.com | docker exec -i gitlab-runner docker-credential-ecr-login get
詳細
Docker の Credentials store の指定
Docker の Credentials store は Gitlab のプロジェクトの CI のDOCKER_AUTH_CONFIG
変数に以下のような JSON の内容をそのまま指定できます。
{
"credsStore": "ecr-login"
}
もしくは gitlab-runner register
で --env 'DOCKER_AUTH_CONFIG={"credsStore":"ecr-login"}'
のようにコマンドラインオプションを指定すれば、この Gitlab Runner が実行するすべてのジョブの変数に自動的に追加されるので、プロジェクトで個別に指定する必要はなくなります。
DOCKER_AUTH_CONFIG
はもともとは次のようなプライベートレジストリの認証情報を指定するためのものですが、
{
"auths": {
"registry.example.com:5000": {
"auth": "b3JlX25vX2hpbWl0dQo="
}
}
}
ECR の場合 aws ecr get-login
で取得したトークンは12時間で有効期限切れになるため、上のようにベタで指定することはできません。
Add support for credentials store (!501) · Merge Requests で Gitlab Runner で Credentials store がサポートされるようになったので、前述のように ecr-login
が指定できます。ただし、Docker CLI と同等ではないので下記のような credHelpers
とかは対応していません。
{
"credHelpers": {
"999999999999.dkr.ecr.ap-northeast-1.amazonaws.com": "ecr-login"
}
}
credsStore
のみがベタで対応されているようです。
- https://gitlab.com/gitlab-org/gitlab-runner/blob/master/helpers/docker/auth_config.go#L114
- https://gitlab.com/gitlab-org/gitlab-runner/blob/master/vendor/github.com/docker/cli/cli/config/configfile/file.go#L37
ただ、ひとつのプロジェクトで複数のレジストリで Credentials store を使い分けるとかでも無い限りは問題なさそうです。
なお、~/.docker/config.json
に記述しても有効なので、DOCKER_AUTH_CONFIG
の代わりに ~/.docker/config.json
を作成しても OK です。
ECR 認証情報の取得
Gitlab Runner が Credentials store を使用するとき、list
サブコマンドですべての認証情報を取得しようとします。
docker-credential-ecr-login list
は ~/.ecr/cache.json
に記録されている ECR の認証情報の一覧を返します。docker-credential-ecr-login get
で認証情報を取得すると ~/.ecr/cache.json
へキャッシュとして保存されるため、あらかじめ手動で認証情報を取得しておきます。
あるいは、~/.ecr/cache.json
がなければ docker-credential-ecr-login list
は AWS_REGION
環境変数で指定されたリージョンの ECR の認証情報を返すので、docker-credential-ecr-login get
を手で実行する代わりに AWS_REGION
環境変数を指定しておいても OK です。
# 環境変数でリージョンも指定
# (docker-credential-ecr-login get は不要)
cat <<'EOS'> /opt/gitlab-runner/.env
AWS_REGION=ap-northeast-1
AWS_ACCESS_KEY_ID=AKI...
AWS_SECRET_ACCESS_KEY=abc123...
EOS
もしくは、環境変数 AWS_SDK_LOAD_CONFIG=true
があれば ~/.aws/config
からでもリージョンを得られるので、AWS_REGION
環境変数の代わりに使用することもできます。
さいごに
Credentials store を使わなくても cron とかで定期的に $(aws ecr get-login --no-include-email)
して ~/.docker/config.json
の認証情報を更新すれば大丈夫だろうと思いますが、余分な処理が不要な分 docker-credential-ecr-login
を使うほうがよいでしょう。