What Kamal actually does

Free preview 3 min to read

Kamal is a deployment tool that assumes you have servers and Docker, and nothing else. There's no Kubernetes, no control plane and no managed platform, just SSH and containers. That's a smaller set of moving parts than most alternatives, and it's why Kamal fits a single VPS.

The whole model in one paragraph

Kamal builds a Docker image on your machine, pushes it to a registry, connects to your servers over SSH, pulls the image there and starts containers from it. A reverse proxy in front routes traffic to whichever container is currently healthy.

That's the entire model. Everything else in config/deploy.yml is detail on top of those five steps.

What this application's file says

service: newbieonrails
image: gxolivei/nor

servers:
  web:
    hosts:
      - <%= ENV.fetch("NOR_SERVER_IP") %>

There's one server, named by an environment variable instead of being written into the repository. ENV.fetch with no default means a missing variable fails loudly at deploy time, before anything deploys somewhere unexpected.

That works because the file is ERB: Kamal renders it before parsing the YAML.

flowchart TB
  L["your machine"] --> B["docker build"]
  B --> R["push to ghcr.io"]
  R --> S["ssh to the server"]
  S --> P["docker pull"]
  P --> C["start the new container"]
  C --> H["health check on /up"]
  H --> X["proxy switches traffic. old container stops"]

The registry step people skip past

registry.server: ghcr.io means the image travels through GitHub's container registry, and not directly from your laptop to the server.

That indirection does real work. The server never needs your source code or a build toolchain. Each image is tagged with its git commit, so rolling back means pulling a previous tag instead of rebuilding.

builder.arch: amd64 forces the build target, which matters on an Apple Silicon machine. Without it, you'd build an arm64 image, and the server couldn't run it.

Why this instead of a platform

A managed platform does all of this and more. What Kamal offers instead is that every piece is visible: the containers are Docker containers, the proxy is a process you can inspect, and the server is one you can SSH into.

The trade is operational responsibility in exchange for legibility and cost. For a single application on a single VPS, that trade is usually favorable, and it's the one this project made.

Key takeaways

  • Kamal builds an image, pushes it to a registry and starts containers over SSH.
  • config/deploy.yml is ERB, so the server address can come from the environment.
  • ENV.fetch without a default fails loudly instead of deploying somewhere wrong.
  • The registry means the server needs no source code or build tools, and a rollback is a tag.
  • The trade is operational responsibility in exchange for legibility and cost.
Lesson 1 of 7 · free

Keep going with lesson 2

The proxy and the swap

How kamal-proxy checks a new container's health on /up and switches traffic without a gap.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...