Kamal is a great tool for deploying web applications to the server of your preference, and it’s an excellent choice to ship web projects, especially side projects. However, it does have its shortcomings for people who want to begin using it for the first time. One of the main barriers to adopting Kamal is that it would require you to have access to a remote Docker container registry.
When deploying your app using Kamal, it builds the image from the Dockerfile in your repository, pushes it to the remote container registry, and then pulls that image into the server where you’re deploying. While services like GitHub, GitLab, and Amazon Web Services all offer container registries, each requires configuration, permissions setup, and sometimes additional costs.
Thankfully, starting from Kamal 2.8.0, you can now spin up a local Docker container registry on the machine that’s deploying the app. If you set the registry server to localhost in the configuration file, Kamal creates a local registry using the official Docker registry image, along with port forwarding to allow the remote hosts to pull your app’s image.
Using the local registry in your system simplifies the Kamal setup and deployment process since you won’t need to configure a third-party service for storing Docker images. In addition, it’s often much faster to build and push updates to your servers because it avoids the extra overhead of connecting to a remote registry during deploys.
Making the switch from remote to local registry
This example uses a Ruby on Rails app called Airport Gap that’s deployed to a Hetzner Cloud server using Kamal. Currently, it uses the GitHub Container Registry service to store the built Docker images for deployment. Here’s the relevant portion of the configuration in config/deploy.yml:
registry:
server: ghcr.io
username: dennmart
password:
- KAMAL_REGISTRY_PASSWORD
This configuration requires a valid access token in the user’s or organization’s GitHub account to authenticate to the container registry and set it up in the KAMAL_REGISTRY_PASSWORD environment variable. Creating the access token just takes a couple of minutes to do, but it’s still an extra step that you need to take before using Kamal. There’s also some additional management needed since it’s a sensitive piece of information that you need to keep secure. On top of that, some container registries set an expiration date for these tokens, which seem to expire at the most inopportune moment.
Switching from a remote registry to a local one couldn’t be simpler. First, make sure to update Kamal to version 2.8.0 or later. For example, in the Airport Gap app, the repository’s Gemfile includes Kamal as a dependency, so I’ll update it to grab the latest version, which is version 2.8.2 as of this writing, and run bundle install.
gem 'kamal', '~> 2.8.2'
After setting up the latest version of Kamal, all you need to do in the config/deploy.yml configuration file is update the registry section to use localhost:<port> as the server and remove the authentication credentials since they’re no longer needed:
registry:
server: localhost:5555
This change tells Kamal to spin up a local registry on port 5555, which it uses to push and pull images automatically via SSH. Kamal pushes your app’s image to this local registry after it’s built and establishes an SSH connection to open the registry’s port and allow the remote server to pull the image. This entire process happens automatically and works the same as if you were using a remote registry as before.
After updating the configuration, you can continue using Kamal to deploy as usual, running kamal deploy to deploy the latest version of the app. During the process, you’ll see some messages showing the local Docker registry spinning up and Kamal using it to push the image and have it pulled from the remote host.
With these simple changes, you can now avoid dealing with external services for storing your app’s Docker images just for deployments.
Reasons to keep using a remote registry
While using the local registry makes using Kamal even simpler, there are still some cases where you might consider using a remote container registry instead of a local one.
Use a remote registry when you need consistency and speed when deploying to new servers
You might need to deploy the app on a new server after a deployment. When using the local registry, you lose the image used to deploy to your older servers. That means you’ll need to rebuild the image and redeploy to both the old and new servers if you want to ensure consistency across the board. Using a remote registry helps avoid inconsistencies and speed up deployments since you and your team can skip the rebuild and use existing images instead.
Use a remote registry when you have slow or capped Internet connectivity
When deploying using the local registry, the remote servers pull the Docker image from your system. The upload speed of your Internet connection determines how fast your deployments finish. Many Internet providers only offer slow upload speeds or place caps on the amount of data you can upload in a given period. This can make deployments from the local registry take longer than necessary or fail, especially if deploying to multiple servers. With a remote registry, you’ll just need to push the image once for all your servers, reducing the reliance on your Internet speeds and data caps.
Use a remote registry when you need to scan your images for security
Some container registry services, such as Docker Hub, can scan your images and detect security vulnerabilities automatically. These automated processes help alert you and your team of potential issues as soon as you deploy. Using the local registry for deployments won’t provide these services out of the box, so you’ll need to make sure your Docker images pass any security checks before deploying to production.
Conclusion
Kamal keeps getting better with each release, and Kamal 2.8.0 keeps the useful improvements coming with the ability to use a local Docker registry. A common issue I’ve seen developers mention when considering Kamal for their projects is the need to set up and manage access to a remote container registry. This extra step could be a significant barrier to getting started with Kamal. Now, you no longer need to spend time on setting up access to a remote container registry, making the initial configuration easier and helping you ship your apps faster.
That said, remote container registries still have their place with Kamal. If you’re working in a team environment that needs to manage deployments to multiple servers or you have concerns about your Internet connectivity, a remote registry might still be a better choice for you. But if you’re a solo developer shipping a side project or on a team working on smaller-scale apps, you’ll appreciate this new feature.
Need help getting your Kamal deploys set up the right way?
I help developers and teams configure production-ready Kamal deployments that fit exactly to their needs. Whether you're looking to begin using Kamal or your existing deployments aren't working as expected, I can help you get things right. Get in touch, and let's talk about your project.



