ghcr2ecr is a terraform module that sets up the tooling you need to push Docker images from GitHub Container Registry (GHCR) to Amazon Elastic Container Registry (ECR).
ghcr2ecr sets everything up within GitHub and AWS. It can be run once and forgotten if that's how you roll.
The module will configure an API Gateway that receives webhook notifications from GitHub every time a new image is published to your organisation's container repositories. The API Gateway triggers a Lambda function, that in turn triggers CodeBuild. The build finds all the images in GHCR that don't exist in ECR. If fetches the missing images and pushes them into ECR.
The flow is triggered when GitHub Actions pushes a new image in GHCR. The project relies on the (as yet undocumented) organisation level package v2 events emitted by GitHub.
Here is a high level overview of the full flow from creating a git commit to the image being pushed to ECR.
I know some of your are probably wondering why I’m not doing this another way. The short answer is, because I think this is the most secure way to do it. One of the biggest benefits of this approach is that we avoid having write credentials for one system stored on another platform. There are no long lived credentials with ECR write permissions floating around in your GitHub Actions.
For the longer version read my blog post A Rube Goldberg Machine for Container Workflows.
The easiest way to set this project up is to add the following configuration to your existing project:
module "ghcr2ecr" {
source = "git@github.com:skwashd/ghcr2ecr.git"
aws_region = "us-east-1"
github_org = "my_org_name"
github_token = "ghp_EXAMPLE_TOKEN"
}
For this to work you have to configure your AWS credentials.
Next up you need to generate two GitHub tokens. Do not use the same token for both purposes. The access will be over provisioned for both use cases.
The first GitHub token is the one used in the module configuration above.
Thistoken needs to have read:package
scope.
The second token is used by terraform to configure the webhook. This token needs
the admin:org_hook
scope. This
should be used as an environment variable for
authentication.
Now you should be set to run terraform apply
. A minute or so after you
approve the changes everything should be provisioned.
The next time an image is pushed to GHCR it should be synced to AWS ECR.
In case you're wondering why the script executed by CodeBuild is fetched from
GitHub each time, this was primary done as I couldn't find a way to inline the
Python code in the buildspec.yml
file. We use a sha256 integrity check to
ensure it hasn't been tampered with. If this makes you uncomfortable you can
override the build_script_sha256
and build_script_url
variables to use your
own buildscript hosted elsewhere.