Dockerized Lambda deployments with CloudFormation

When you deploy a Lambda using a tagged docker image, updating the tagged image and redeploying the Lambda (using CloudFormation) doesn’t actually update the code running in the Lambda. This happens because neither CloudFormation nor Lambda know that the tag now points somewhere else.

The solution is actually pretty simple: instead of referring to the docker image by its tag, refer to it by its digest instead.

Old way, using a tag:

# Part of a CloudFormation template in yaml format:
LambdaFunction:
  Type: AWS::Lambda::Function
  Properties:
      PackageType: Image
      Timeout: 120
      MemorySize: 512
      Code:
        ImageUri: !Sub ${DockerRegistry}/image-name@latest

New way, using a digest:

# Part of a CloudFormation template in yaml format:
LambdaFunction:
  Type: AWS::Lambda::Function
  Properties:
      PackageType: Image
      Timeout: 120
      MemorySize: 512
      Code:
        # Reference the digest (sha hash) instead of tag here, since Lambda won't pick up the new image if we just re-tag it.
        # Doing it this way ensure lambda pulls the new image.
        ImageUri: !Sub ${DockerRegistry}/image-name@${LambdaDockerDigest} 

The digest comes into the template as a parameter (LambdaDockerDigest), which ultimately comes from my build step and looks something like sha256:94a00394bc5a8ef503fb59db0a7d0ae9e1110866e8aee8ba40cd864cea69ea1a.

In hindsight, using the sha is probably better anyway: it’s the most unambiguous and immutable way of referring to a given image version.