Docker image を ECR にプッシュするのが微妙に面倒なので、最新の (一番新しく作られた) イメージをプッシュするシェルスクリプト/バッチファイルを作りました。
ローコード開発ツールからコンテナイメージを作ったけれども、イメージ名が自動で振られてプッシュが面倒だったときに作ったものです。
docker images
の並び順で先頭に来るものを使う形になっているので、作成するたびにイメージ名が変わっても問題ない、というものです。複数のコンテナを作成している場合には注意が必要ですが。
ついでに terraform から出力するためのコードも載せています。
コード本体
awscli
が使えるようになっている前提で、リージョン、プロファイル名、ECRのURLをセットして使う形です。
.bat
REM ecr push command
setlocal
aws ecr get-login-password --region ${region} --profile ${profile} | ^
docker login --username AWS --password-stdin ${ecr_url}
for /f "usebackq delims= tokens=*" %%a IN (`docker images --format "{{.ID}}"`) DO SET LATEST_TAG=%%a & goto break
:break
docker tag %LATEST_TAG% ${ecr_url}:latest
docker push ${ecr_url}:latest
.sh
#!/bin/bash
aws ecr get-login-password --region ${region} --profile ${profile} | \
docker login --username AWS --password-stdin ${ecr_url}
docker tag $(docker images --format {{".ID"}} | head -n 1) ${ecr_url}:latest
docker push ${ecr_url}:latest
変数
- ${region}
- リージョン名
- ap-northeast-1 とか
- ${profile}
- プロファイル名(アカウントや権限を切り替えるために使用)
-
--profile ${profile}
を省略するとデフォルトプロファイルが使われる
- ${ecr_url}
- ECR の URL
-
https://<aws_account_id>.dkr.ecr.<region>.amazonaws.com
みたいな形式
terraform から出力
ECR の ID も長いし取得が面倒なので、
terraform からプッシュコマンドを出力するようにしています。
ECR も terraform で作っているので、url の具体的な形は気にせずに書いています。
resource "local_file" "format_commands" {
# 複数ファイルをまとめて処理する形にしている
# for_each のパスに先ほどのファイルが入るようにして使う
for_each = fileset("${path.module}/data", "**/*{.sh,.yaml,.bat}")
filename = "./outputs/commands/${each.value}"
content = templatefile("${path.module}/data/${each.value}", {
profile = var.aws_profile,
region = var.aws_region,
ecr_url = aws_ecr_repository.ecr_repository.repository_url,
})
}
${変数名}
のところを content
の変数名で置換して出力してくれます。
上記のECRプッシュ用のコマンドはそのまま使うことができます。
ECR からプルするコマンド
プルする方はこんな感じにしています。.bat は使っていないので .sh だけです。
#!/bin/bash
aws ecr get-login-password --region ${region} | \
docker login --username AWS --password-stdin ${ecr_url}
docker pull ${ecr_url}:latest
こちらも terraform 実行時にフォーマット済みファイルを出力させています。
s3 にアップロード
ついでにこんな感じで s3 にもアップしています。s3 sync
でフォルダごと同期する形です。
resource "null_resource" "upload_commands" {
provisioner "local-exec" {
command = "aws s3 sync outputs/commands/ s3://${aws_s3_bucket.s3_bucket.id}/commands/ --profile ${var.aws_profile} --delete"
}
triggers = tomap({
for k, f in local_file.format_commands : k => f.content_md5
})
}