【发布时间】:2018-12-04 08:04:21
【问题描述】:
如果 AWS ECR 存储库尚不存在,我该如何创建它?
【问题讨论】:
标签: amazon-ecs docker-registry aws-ecr
如果 AWS ECR 存储库尚不存在,我该如何创建它?
【问题讨论】:
标签: amazon-ecs docker-registry aws-ecr
如果不存在,则创建一个 repo:
aws ecr describe-repositories --repository-names ${REPO_NAME} || aws ecr create-repository --repository-name ${REPO_NAME}
【讨论】:
AWS 仅在它不存在的情况下创建存储库。
如果存在相同的存储库,您可以使用|| true 简单地忽略错误和失败:
aws ecr create-repository --repository-name <repo_name> || true
【讨论】:
你可以这样做,但你需要先检查 repo 是否存在。我一起破解了这个 bash 脚本,它可以满足我的需要:
#!/bin/bash
aws ecr describe-repositories --repository-names $1 2>&1 > /dev/null
status=$?
if [[ ! "${status}" -eq 0 ]]; then
aws ecr create-repository --repository-name $1
fi
参数将是一些 repo 名称。为使其在 CodeBuild 中正常工作,该作业将需要一个 IAM 角色以允许其创建 ECR 存储库。如果您需要在代码构建作业中获取 AWS CLI 凭证,请查看此 AWS 博客文章:
我们正在按照“创建构建规范”中的描述使用 JQ 来提取 AWS 凭证。
【讨论】:
到目前为止,几乎所有的答案都在调用describe-repositories,如果出现错误,他们会假设 repo 不存在。
这是错误的,因为还可能出现其他类型的错误(没有互联网连接、没有权限 (AccessDeniedException)、错误的仓库名称......)。
这意味着如果describe-repositories 调用以错误结束,那么我们需要检查错误是否为RepositoryNotFoundException。只有在这种情况下,我们才应该调用create-repository。
这就是 bash 代码的样子:
output=$(aws ecr describe-repositories --repository-names ${REPO_NAME} 2>&1)
if [ $? -ne 0 ]; then
if echo ${output} | grep -q RepositoryNotFoundException; then
aws ecr create-repository --repository-name ${REPO_NAME}
else
>&2 echo ${output}
fi
fi
逐行解释:
output=$(aws ecr describe-repositories --repository-names ${REPO_NAME} 2>&1) -
这会调用describe-repositories 并将输出存储到名为output 的变量中。
if [ $? -ne 0 ]; then - 此行检查最后一个命令 (aws ecs describe-repositories ...) 是否不成功。如果退出代码 ($?) 不是 0 (-ne 0),那么我们需要检查错误是什么。如果成功则无事可做(成功意味着 repo 已经存在)。
if echo ${output} | grep -q RepositoryNotFoundException; then - 在这一行中,我们正在检查是否出现错误,因为 repo 不存在。如果是,那么我们需要创建 repo:
aws ecr create-repository --repository-name ${REPO_NAME} - 创建 repo,我们知道它不存在。
else - else 情况意味着describe-repositories 由于其他原因引发错误然后不存在 repo。
>&2 echo ${output} - 在这种情况下,我们不应该尝试创建 repo,而只是在 stderr 上输出错误 (>&2)
【讨论】:
如果您希望在 Jenkins 脚本化管道中自动执行此操作,只需使用以下代码-sn-p:
def ensureRegistry(accountId, region, repoName) {
Logger log = new Logger(this)
def accId = shell.output("aws --region ${region} ecr describe-repositories --repository-names \"${repoName}\" | jq .repositories[].registryId | tr -d '\"'")
if (accId == accountId) {
log.info("Docker repository ${repoName} exists for account ${accId}")
} else {
log.info("Docker repository ${repoName} doesn't exist for account ${accId}")
shell.status("aws --region ${region} ecr create-repository --repository-name \"${repoName}\"")
log.info("Docker repository ${repoName} was just created for account ${accId}")
}
}
shell.groovy 是:
def output(cmd) {
sh(script: cmd, returnStdout: true)
}
def status(cmd) {
sh(script: cmd, returnStatus: true)
}
【讨论】:
除了有条件地创建 repo,如果你还想提取 repo URI,考虑这个多行 bash 命令:
REPO_URI=$(aws ecr describe-repositories --repository-names "${REPO_NAME}" --query "repositories[0].repositoryUri" --output text 2>/dev/null || \
aws ecr create-repository --repository-name "${REPO_NAME}" --query "repository.repositoryUri" --output text)
repo URI 对于tag 和push 操作很有用。
部分归功于:answer 来自 JS
【讨论】:
export ECR_REPO=`aws ecr describe-repositories --repository-names $REPO_NAME 2>/dev/null | jq .repositories[0].repositoryUri | tr -d \\\" && aws ecr create-repository --repository-name $REPO_NAME --region us-east-1 2>/dev/null | jq .repository.repositoryUri | tr -d \\\"`
这适用于 buildspec.yml 文件,用于始终获取 repo 名称并将其存储在 ECR_REPO var 中。如果它已经存在,它将创建 repo 或静默失败。如果它确实存在,它将获取 repo 名称,如果不存在,它将静默失败。
【讨论】:
要检查 ECR 存储库是否存在,您可以使用 double。首先检查描述存储库(如果不存在)然后创建存储库始终使用有助于审计的标签。
- aws ecr describe-repositories --repository-names ${ECRImage} || aws ecr create-repository --repository-name ${ECRImage} --tags Key=Domain,Value=$Domain Key=AppEnv,Value=$AppEnv Key=ApplicationCI,Value=$ApplicationCI Key=Owner,Value=$Owner Key=Requester,Value=$Requester Key=CostCenter,Value=$CostCenter
【讨论】: