DockerイメージをビルドしてECRにpushするshell script


いちいちビルドしてタグ付けしてecrにログインしてpushするのが面倒だったので、1コマンドでやってくれるスクリプト書きました。

普段そんなに書かないのでShell書くときのConventionみたいなの知らなくて、変な書き方してる部分もあるかも。
気が向いたらご指摘いただけると嬉しいです。

書いたやつ

#!/bin/sh

# Returns boolean indicates whether designated tagged-image exists.
  # arg1: repository name
  # arg2: tag name
function image_exists() {
  image=$(docker image ls -a | grep $1 | grep $2)

  if [ "$image" ]; then
    return 0;
  else
    return 1;
  fi
}

# Builds new image.
  # arg1: tag in the form like ${repository}:${tag}
  # arg2: Path to Dockerfile
function build_image() {
  docker build -t $1 -f $2 .
}

# Work on master branch
git checkout master

# Get latest master revision
revision=$(git rev-parse --short HEAD)

echo "Current master revision is ${revision}\n"

# Set constants
readonly repository=your-repository-name
readonly ecr_repository=************.dkr.ecr.<region>.amazonaws.com
readonly revised_repository=$repository:$revision
readonly ecr_revised_repository=$ecr_repository/$revised_repository
readonly path_to_dockerfile=<relative-path-to-dockerfile>

echo "local-repository: ${repository}
ecr-repository: ${ecr_repository}
local-revised-repository: ${revised_repository}
ecr-revised-repository: ${ecr_revised_repository}\n"

# Build current source if revision not exists
if image_exists $repository $revision; then
  # Do nothing.
  echo "local-revised-repository already exists. Skip build.\n"
  true;
else
  echo "Start building local-revised-repository."
  build_image $revised_repository $path_to_dockerfile;
fi

# Generate ecr-repository-tagged image if not exists
if image_exists $ecr_repository $revision; then
  # Do nothing.
  echo "ecr-revised-repository already exists. Skip tagging.\n"
  true;
else
  docker tag $revised_repository $ecr_revised_repository;
fi

# 必要に応じてこのへんでAWSの認証情報を設定する

# Login to ECR
aws ecr get-login-password --region <region> \
  | docker login --username AWS --password-stdin $ecr_repository

# Push new image to ECR
docker push $ecr_revised_repository

echo "Done.\n"

実装要件

  • latestっていうタグ付けをすると、あとから見た時にいつのビルドなんだか分からなくなるので、リリース時点のgitリビジョンを利用する
    • 注意点: リリースブランチのリビジョンを取るべきなので、必要に応じてmaster部分を変更してください
  • 指定されたリビジョンがタグ付けされたイメージがまだ存在していなければビルドする
    • 存在していればビルドをスキップする
  • 指定されたリビジョンがタグ付けされたECR向けのイメージがまだ存在していなければタグ付けする
    • 存在していればタグ付けをスキップする
  • ECRにログインする
    • 注意点: ECRログインする前に、そのECRが存在するAWSアカウントを操作できる認証情報を取得しておくこと。
    • profileがあるならそれを読み込む。
    • 自分の場合、MFAで一時的な認証情報を取得する必要があるため、その部分を書いてある
  • ビルドされたイメージをECRにpushする

おまけ: MFA認証

これはこれでめんどくさかったので、誰かの役に立てば。

# 標準入力からmfaコード入力を受け付ける
read -p "Input mfa code: " mfaCode

result=$(aws sts assume-role \
  --role-arn arn:aws:iam::************:role/<role-name> \
  --role-session-name <session-name> \
  --serial-number <mfa-serial> \
  --token-code $mfaCode --profile <profile-name>)

export AWS_ACCESS_KEY_ID=$(echo $result | jq ".Credentials.AccessKeyId" -r)
export AWS_SECRET_ACCESS_KEY=$(echo $result | jq ".Credentials.SecretAccessKey" -r)
export AWS_SESSION_TOKEN=$(echo $result | jq ".Credentials.SessionToken" -r)