Kaniko or GitHub Actions: where should the image be built?
Kaniko builds where the application runs. GitHub Actions builds where the code lives. Neither needs a Docker daemon, and both have a catch you only notice in production.

A deployment from Git needs an image, and an image needs a build. The old answer was a build server running Docker. The new answer is one of two: in the cluster with Kaniko, or outside it with GitHub Actions. Both work. Which one fits depends on three questions.
Kaniko: the build runs in the cluster
Kaniko is a tool from Google that builds a Dockerfile without a Docker daemon. It runs as a regular pod: it clones the repository, executes the Dockerfile’s instructions and pushes the result to the registry. No privileged container, no socket, no build server. A note on the current state: Google archived the original Kaniko repository in 2025, and it is no longer developed there. Chainguard maintains a continued version; if you introduce Kaniko today, use a maintained variant.
Pros:
- The build happens where the image will later run. Registry, network and credentials are already there.
- No third-party account, no runner minutes, no dependency on GitHub.
- The job reaches private repositories via a token that exists as a Secret only for the duration of the build.
Cons:
- The build consumes the cluster’s CPU and memory. A large build next to production pods can slow them down if the build job’s requests and limits aren’t set.
- No layer cache across builds unless you store it in the registry. Every build starts from scratch.
- A hung build is a hung pod that someone has to clean up.
GitHub Actions: the build runs at GitHub
The cluster triggers a workflow via workflow_dispatch, GitHub builds on its runners and pushes to the registry, and the cluster waits for the result and rolls out.
Pros:
- Zero load on the cluster. A build with eight gigabytes of memory costs no production resources.
- The GitHub Actions cache noticeably speeds up repeat builds.
- The workflow is part of the repository, and developers know it.
Cons:
- Runner minutes cost money, depending on your plan’s quota.
- A green workflow only proves that the workflow ran, not that the right image was pushed. A workflow with a hard-coded tag happily pushes somewhere else and reports success.
- The cluster needs a token with permissions on Actions, plus a dependency on GitHub’s availability.
We ran into the second drawback live: deploy green, pod running the old image. Since then, Clusterward checks before every rollout whether the expected tag is really in the registry, regardless of how it was built. Only a definite "not found" stops the deployment; a transient registry glitch must not block a working deployment. Details under Deployments.
The three questions
Question | Kaniko | GitHub Actions |
|---|---|---|
Does the cluster have headroom for builds? | Yes, with requests and limits on the job | Doesn’t matter, the build happens elsewhere |
May the code leave the cluster? | It doesn’t have to; the repository is cloned in the cluster | It’s at GitHub anyway |
How often do you build? | Rarely to moderately | Often, with cache |
If you want to stay sovereign and have few builds a day, go with Kaniko. If you build twenty times a day and are on GitHub anyway, go with Actions. Running both side by side in the same cluster is no contradiction: the choice is per build, not per cluster.
Requests for the build job
The most common Kaniko mistake is a build job without resource settings. Kubernetes schedules it anywhere, it takes whatever it can get, and a production pod on the same node gets less. Three values belong on every build: CPU request, memory request and, optionally, a node pool that builds are allowed to run on. A small dedicated pool for builds that scales to zero at night is the cleanest solution.
The token
Both approaches need a token for private repositories. For Kaniko, a read token that the job receives as a Secret and that is deleted after the build. For Actions, a token with permission to start workflows. In both cases, the token is stored encrypted in the control plane, is never displayed, and is scoped per application, not per organization.
The same principle applies to the push. A build in the cluster runs your repository’s Dockerfile right next to the key it pushes with. Clusterward therefore gives the Kaniko job a key of its own that may only use the project’s Container Registry – never the key that creates clusters and databases.
The third option: your own CI, Clusterward rolls out
Some teams already have their pipeline: tests, build and push run in GitHub Actions or GitLab CI, and the image sits in the registry. Then the only thing missing is the last step, the rollout. That’s what API tokens in Clusterward are for. Under System → API tokens you create a token with a role, application scope and expiry date, optionally with the "CI deploy" role, which may only roll out applications. The workflow triggers a deploy or restart via a bearer header and polls the status until the deployment is healthy. The token can’t manage users, roles or other tokens, and every one of its actions is recorded under its name in the audit log. More under Deployments.
An everyday example
An agency runs twelve customer projects on a cluster with two nodes. Each project is deployed once or twice a week. That’s about twenty builds a week, each taking two to four minutes. For this cluster, Kaniko is the right choice: the builds run at night or on the side, briefly use one vCPU and one gigabyte, and are gone. A GitHub account with runner minutes would be an extra dependency for twenty short jobs.
A SaaS vendor with one application and a team of eight developers deploys twenty times a day. Each build takes six minutes and four gigabytes because the frontend gets bundled. Here GitHub Actions is the right choice: with cache the build takes two minutes, the cluster notices nothing, and developers see the build where they already work.
The Dockerfile matters more than the tool
Both tools build the same Dockerfile, and most slow builds are slow Dockerfiles. Three rules that work for both:
- Copy dependencies before the code. First
package.jsonand the lockfile, then install, then everything else. That way the install step stays cached as long as the dependencies don’t change. - Multi-stage builds. Build in an image with a compiler, ship in a slim image without one. The final image is smaller, the push faster, the attack surface smaller.
- A `.dockerignore`. Without one,
node_modulesor.gitend up in the build context, and Kaniko clones and copies hundreds of megabytes nobody needs.
When the build hangs
With Kaniko, a hung build is a pod in the Running state that never finishes, usually because of a network call in the Dockerfile waiting for a timeout. A job therefore needs a deadline after which Kubernetes terminates it, and a way to cancel it from the cockpit. The same applies to the workflow run in GitHub Actions: a timeout per job, otherwise a hung build eats runner minutes and the deployment waits for a result that never comes.
Which image is really running?
A tag like latest moves with every build. That’s why Clusterward asks the registry before every rollout which image the tag currently points to, and rolls out exactly that one by digest. New builds also get a fixed sha-<Commit> tag that still points to the same image after the next build.
If a version goes wrong, “Restore this version…” in the deploy history brings back the exact image of an earlier healthy version – whether Kaniko or GitHub Actions built it. More under Deployments and Backups & recovery.
Conclusion
Kaniko when the cluster has headroom and the code should stay in your own network. GitHub Actions when you build often and the load should sit elsewhere. Either way: verify the image before rollout, set requests on the build, one token per application. The build path is a per-build setting, not a matter of faith.
Which build path fits your repository? Tell us how often you build and where your code lives. We’ll tell you whether Kaniko or GitHub Actions is the better fit. Ask about your build →
Sources and further reading
Frequently asked questions
- Kaniko builds in the cluster, where the application runs; GitHub Actions builds on GitHub’s runners, where the code lives. Neither needs a Docker daemon. Kaniko consumes the cluster’s CPU and memory, while GitHub Actions costs runner minutes and creates a dependency on a token and on GitHub’s availability.