使用docker_registry_image (kreuzwerker/docker)在Terraform中“强制”创建Docker镜像

4

我正在开发一系列使用Docker镜像的Lambda函数。第一步是创建它们并在AWS ECR中注册(不确定我所做的一切是否正确,欢迎任何建议 :-)):

terraform {
  ...
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = ">= 2.12"
    }
  }
}

resource aws_ecr_repository lambda_repo {
   name = "lambda"
}

resource docker_registry_image lambda_image {
  name = "<account_id>.dkr.ecr.<region>.amazonaws.com/lambda:latest"

  build {
    context    = "./code/lambda"
  }

  depends_on = [
    aws_ecr_repository.lambda_repo
  ]

  keep_remotely = true
}

resource aws_lambda_function lambda {
  ...
  image_uri = "<account_id>.dkr.ecr.<region>.amazonaws.com/lambda:latest"
  source_code_hash = docker_registry_image.lambda_image.sha256_digest
  ...
}

使用以下代码:

  • docker_registry_image > lambda_image:构建图像并将其上传到AWS
  • aws_lambda_function > lambda:如果图像“lambda:latest”已更新,则更新Lambda中的新代码

我的问题是如何“强制”docker_registry_image > lambda_image重新构建图像并在Dockerfile或app.py(添加到文件中的主要代码)更改时更新“lambda:latest”。另外,我不确定这是否是构建图像的方法。

谢谢!


通常人们在管道中构建图像而不是无服务器函数。这对您来说可能会更容易。 - Matt Schuchard
谢谢Matt。我正在构建的镜像中包含lambda的代码(因为所需库的大小)。我理解你的观点,但在这个阶段,我还没有设置管道,而且镜像是使用TF代码构建的。 - islegmar
1个回答

4

我曾经遇到了完全相同的问题,很失望地发现您的问题还没有得到解答。我苦苦挣扎了一段时间,但是今晚晚些时候我终于成功了。

问题出在错误的思考方式上,这是由于糟糕的Docker习惯造成的(我也有同样的问题):

  1. latest是一个不好的习惯:它基于标签的可变性,这不是Docker的设计初衷,而且拉取latest是不确定的-你永远不知道你会得到什么。通常,latest会拉取最近版本的docker pull
  2. 更多关于标签不可变性的信息:作为开发者,当遇到小问题时,我们经常快速重建并用相同的标签覆盖现有的映像,因为“没有人会知道,而且只是一个小修复”。
  3. 将Lambda代码文件视为应该触发Terraform替换的具有状态的东西-代码文件不是资源,而是创建Lambda的资产。

以下是更好的思考方式:

  1. docker_registry_imagekreusewerker/docker提供程序都基于标签不可变性。
  2. docker_registry_image在Terraform状态中“被替换”(当您尝试时,您会在Terraform计划中看到它),但是在您的ECR存储库中的效果是添加一个带有下一个连续标签号的新映像,而不是像通常在Terraform中想的那样替换实际映像。
  3. 每次更改Lambda源代码文件都需要使用新的标签号构建新的映像。
  4. 如果您发现映像堆积在您身上,那么您需要一个生命周期策略来自动管理它。
  1. 创建一个名为image_tag的新变量:
variable "image_tag" {
  default = 1
}
  1. 修改你的docker_registry_image,使其使用image_tag变量(同时也要修改docker_registry_image名称,以免进行过多容易出错的字符串构建):
resource docker_registry_image lambda_image {
  name = "${aws_ecr_repository.lambda_repo.repository_url}:${var.image_tag}"

  build {
    context    = "./code/lambda"
  }

...
}
  1. 修改您的aws_lambda_function。将image_uri更改为docker_registry_image的名称,以使这两者永远不会失步:
resource aws_lambda_function lambda {
 
  image_uri = docker_registry_image.lambda_image.name
  source_code_hash = docker_registry_image.lambda_image.sha256_digest
  
}
  1. 每次更改Lambda源文件中的代码时,将image_tag变量增加1。然后尝试terraform plan,您会发现docker_registry_imageaws_lambda_function将被替换。一个好的练习是在执行此操作时查看控制台中的ECR存储库和Lambda函数。您将看到图像出现在ECR存储库中,并且Lambda函数的镜像URI已更新为新的image_tag
  2. 如果您不喜欢ECR存储库中堆积的图像版本,可以考虑实施ecr_lifecycle_policy

希望这可以帮助您。我今晚感觉好多了!


我认为你所说的正是关键,必须创建一个新的图像版本。我完全同意使用“最新版本”并不是一个好主意。非常感谢! - islegmar
这真是太有帮助了,谢谢你!! - Zach Munro
这真是太有帮助了,谢谢你! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接