DOCS LLMs

Kamal - Configure a container registry

Kamal uses your local development machine as a Docker container registry by default.

This means that, after the Docker image containing your app is built, it's stored in your local computer and needs to be uploaded from your computer to the production server for deployment.

If your internet connection is not the best, this may slow down your total deployment time from the time you hit kamal deploy until the time everything is live in production. Also, you may be filling up your local machine with big stale Docker images.

TIP

Using a remote container registry usually speeds up deployment times.

There are many remote container registry options: Docker Hub, ghcr.io, GitLab container registry, etc.

Some are paid, some are free (but always public, which is not supported on RailsFast).

What I found to be easiest to configure and integrate with Kamal (RailsFast) is AWS ECR.

How to use AWS ECR with Kamal as container registry

AWS ECR costs close to nothing (I paid $0.32 –yes, 32 cents– last month), and it's very straightforward to integrate with Kamal using the AWS CLI. And since we're already using AWS for storage (S3) and emailing (SES) in RailsFast, it makes sense to also leverage their container registry.

Install and configure the AWS CLI

First, install and configure the AWS CLI.

Then, at the end of the Kamal secrets file under .kamal/secrets, uncomment this line:

AWS_ECR_PASSWORD=$(aws ecr get-login-password --region us-east-1 --profile default)

Make sure to change the us-east-1 for the region you're using in ECR, or leave it like that if you're fine with us-east-1.

INFO

This is a secure way of sharing your AWS ECR credentials with Kamal for deployment. No password, API token or anything sensible ever gets commited or made public. Upon every deployment, Kamal will call the AWS CLI on your local computer to get a temporary login password for ECR, and will load that token as the AWS_ECR_PASSWORD ENV var in the containers that need it.

Create a private registry on AWS ECR

Go to your AWS console and navigate to ECR (Elastic Container Registry).

Click on the [ Create repository ] button.

Give your registry a name with a username in front. Example: use myusername/myproject, not just myproject. This is because Docker container registries require username namespacing (a container must belong to a username). Tip: just use the same username you use on GitHub and the same project name you use on GitHub.

Keep the rest of the settings default and click on [ Create ]

Since we're at it, let's do a couple more clicks to limit how many versions of our Docker images the registry is going to store (saving us storage money!)

Select your recently created repository from the list of private repositories. On top, click [Actions â–¼] and then Lifecycle policies. Click on [Create rule] to create a new rule, and in the new screen leave everything by default but where it says: Image tag status (select: Any). Then, under Match criteria, I suggest you select Days since image created or Image count. In the box below, you can specify for how many days you want to store each version, or how many version (images) in total you want to storage.

I personally just select Image count, and set it to only save the last 30 images. Click [Save] and [Confirm] and you won't be storing old, stale versions forever.

Edit deploy.yml

Now that we have everything configured in ECR, in your config/deploy.yml let Kamal know which container registry you're using:

  • Change your image name to match the name you gave it in AWS ECR. Example, if before you had something like:
image: myproject

Edit it to make it match what you had on ECR:

image: myusername/myproject
  • Remove the localhost:5555 server under the registry section and uncomment the placeholder remote container registry options (server, username, password), to end up with something like this:
registry:
  server: 1234.dkr.ecr.us-east-1.amazonaws.com
  username: AWS
  password:
    - AWS_ECR_PASSWORD

Replace the placeholder 1234.dkr.ecr.us-east-1.amazonaws.com with the actual repository URI you can see on ECR in your private repositories list.

IMPORTANT

If you're using a remote builder, make sure to pass the AWS_ECR_PASSWORD ENV var to the builder too, under the secrets section of the builder key:

builder:
  secrets:
   - RAILS_MASTER_KEY
   - AWS_ECR_PASSWORD

And you're done!

You can check the remote Docker container registry in AWS ECR is set up correctly in Kamal by running:

kamal registry setup

And seeing that it logs in correctly.

The next time you deploy using kamal deploy, Kamal will push and pull the Docker images from ECR instead of from your local computer registry.


You can learn more about Kamal and container registries in the official Kamal docs