How to Use Apko: The Beginner’s Guide to Dockerfile-Free Container Images

CodexFuse Team · 2026-11-02T01:04:39.775Z · 12 min read min read

Apko is Chainguard’s open-source tool for building minimal, reproducible container images from YAML — no Dockerfile, no daemon. This beginner’s guide covers install, melange keygen, your first apko.yaml, your first build, and the melange hand-off.

Search for "how to use apko" in 2026 and you will trip over Hindi grammar lessons first: "aapko" (आपको) is the Hindi word for "to you." Lowercase apko is something entirely different — an open-source tool from Chainguard that builds container images from a YAML file, with no Dockerfile, no daemon, and no build scripts. This apko tutorial teaches the tool, not the pronoun.

The mental model is one sentence: apko builds images, and its sibling tool melange builds packages. You declare the final image in a YAML file, and apko assembles it from APK packages into a minimal, reproducible OCI image. If you want the engine-lane foundation first, the Docker beginner guide covers it — this guide is the Dockerfile-free lane, and the two are complements, not rivals.

Apko is Apache-2.0 open source, its name riffs on Google’s ko builder, and it is genuinely current: version 1.4.15 was released on 2026-11-02, the same day this guide was written. Here is the whole arc ahead of you: install apko, generate signing keys with melange keygen, write your first apko.yaml, build your first image, and hand custom packages off to melange when you outgrow public packages.

What Is Apko, Exactly?

Apko is an open-source container-image builder from Chainguard that turns a declarative YAML configuration into a minimal, reproducible OCI image by assembling APK packages — with no Dockerfile, no container daemon, and no RUN commands. Chainguard’s own Academy calls it "solely a composition tool" focused on producing lightweight, "flat" base images that are fully reproducible.

The problem it solves is real: a typical Dockerfile image inherits a base OS, then layers on shells, package managers, and build tools that become CVE surface in production. An apko image contains exactly the packages you list and nothing else, which is why the output is often dramatically smaller than a comparable Dockerfile image and why security scanners find far less to complain about.

The trade is explicit in the official docs: "Unlike Dockerfiles, there is no support for running arbitrary Unix commands (i.e. there is no equivalent of RUN statements)." If your build needs to compile code or run scripts, that work belongs in melange pipelines or in a Dockerfile layered on top of the apko base — the FAQ confirms layering Dockerfiles over apko images is a supported use case.

How Is Apko Different From a Dockerfile?

A Dockerfile is a script of imperative steps that produces image layers; an apko configuration is a declaration of the final state that produces an image from packages. The apko vs dockerfile question comes up constantly, and that single distinction drives every other difference.

AspectDockerfileapko
Build instructionsRUN, COPY, and other imperative commandsA package list in YAML — no RUN equivalent exists
Base imageFROM a base layer (often a full OS)No base image at all — the image is exactly the packages you declare
Build daemonNeeds the Docker daemon (or BuildKit)Daemonless — runs as a plain binary or container
ReproducibilityDepends on layer caching and base-image driftPackage-locked and fully reproducible by design
Attack surfaceOften ships shells and package managersMinimal by construction — often shell-free
Package ecosystemsAny — apt, apk, dnf, whatever the base hasOne APK ecosystem per build (you cannot mix Wolfi and Alpine packages)

The practical takeaway: use Dockerfiles where you need arbitrary build steps, and use apko where you want a declared, minimal, signed image. Many teams now do both — an apko-built base for the CVE-free floor, with traditional tooling for the final application step, exactly as Chainguard’s README recommends.

How Do You Install Apko?

Install apko with your platform’s package manager, Go, or mise — or skip installing entirely and run it as a container. The official install methods, verbatim from the Chainguard apko README, are:

brew install apko
mise use -g apko@latest
go install chainguard.dev/apko@latest
docker run cgr.dev/chainguard/apko version

The container route is a legitimate first choice: the Academy tutorial describes cgr.dev/chainguard/apko as the distroless apko image rebuilt every night, so you always get the current release without managing upgrades. Run apko version to confirm — you should see v1.4.15, published 2026-11-02 per the GitHub releases API.

If you follow official docs, the Chainguard Academy’s "Getting started with apko" — last updated 2026-10-02 — is the freshest vendor walkthrough. Treat anything written before 2024 as archaeology: the popular 2023 guides pin apko v0.9.0, and the configuration schema has moved on since.

Why Must You Generate Keys Before Building?

Apko images are signed artifacts, so signing keys come first: run melange keygen before your first apko build, then hand the public key to the build with -k. Teach this order as a rule, not a footnote — it is the single most common beginner stumble.

The keygen command writes two files, as the melange README documents: it generates a 4096-bit keypair, writing the private key to melange.rsa and the public key to melange.rsa.pub. The private key signs your packages; the public key is what apko needs to trust them.

melange keygen
apko build apko.yaml image:tag image.tar -k melange.rsa.pub

The -k flag is shorthand for --keyring-append, which the current CLI source documents as "path to extra keys to include in the keyring." Chainguard’s own tutorials use exactly this form, so it is the canonical spelling, not a shortcut that will disappear. Guard melange.rsa like any private key — it never belongs in a git repository.

What Goes Inside apko.yaml?

An apko.yaml declares three things and nothing else: contents (where packages come from and which ones), entrypoint (what the container runs), and archs (what it runs on). Here is the verbatim minimal Wolfi example from the Academy tutorial:

contents:
  keyring:
    - https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
  repositories:
    - https://packages.wolfi.dev/os
  packages:
    - ca-certificates-bundle
    - wolfi-base
entrypoint:
  command: /bin/sh -l
archs:
  - x86_64

Wolfi, for the uninitiated, is Chainguard’s community Linux "undistro" built for the container era on the proven APK package format — it is the default package source most apko beginners reach for. The full field reference, verified against the current docs, is:

FieldWhat it declares
contents.repositoriesAPK repositories the image is assembled from, e.g. https://packages.wolfi.dev/os
contents.keyringSigning keys trusted for those repositories, including your own melange.rsa.pub
contents.packagesThe exact contents of the image — nothing else ships
entrypoint.commandWhat the container executes (shell-fragment and s6 service modes exist too)
archsTarget architectures: 386, amd64, arm64, arm/v6, arm/v7, ppc64le, riscv64, s390x
environmentEnvironment variables baked into the image, such as PATH
pathsExtra directories, files, symlinks, and permissions (recursive supported)
accountsUsers, groups, and the run-as account for non-root images
layeringLayering strategy — currently only "origin" is valid
include, annotationsReusable config includes and OCI annotations

Notice what is absent: there is no way to run a command, download a tarball, or copy a file from your laptop. If you catch yourself wanting one, that is your cue that the work belongs in a melange pipeline, which produces a proper signed APK package you then list under packages.

How Do You Build, Load, and Run Your First Image?

Build with apko build apko.yaml image:tag image.tar, load the tarball into Docker with docker load, and run it like any other image — apko container images are OCI-compliant. The full first-build arc, end to end:

  1. Generate keys. melange keygen — do this once per project, before anything else.
  2. Write apko.yaml. Use the Wolfi example above, with your packages and your melange.rsa.pub in the keyring.
  3. Build. apko build apko.yaml image:tag image.tar -k melange.rsa.pub — the canonical usage is apko build <config.yaml> <tag> <output.tar|oci-layout-dir/>. A directory output writes an OCI image layout; anything else bundles into a self-contained tarball index. SBOMs are generated by default (--sbom is true, SPDX format).
  4. Load. docker load < image.tar imports the image into your local daemon.
  5. Run. docker run -it image:tag — the Academy confirms the images run with Docker or any other OCI-supporting runtime.

That is the whole beginner loop. The images you get are small because they are honest: every byte in them is a package you named, and the SBOM apko generates per build tells your security tooling exactly what is inside.

How Do You Publish an Apko Image to a Registry?

Use apko publish <config.yaml> <tag...> — it builds one image per architecture, assembles the multi-arch index, pushes it to the registry, and prints the digest. It is the same build pipeline as build plus the push steps.

apko publish examples/alpine-base.yaml myrepo/alpine-apko:test

Two flags matter in practice: --arch limits which architectures get built (handy when you only deploy amd64), and --local loads the result into your local Docker daemon instead of pushing to a registry. Because apko is daemonless, apko publish is also the command your CI pipeline calls — the runner needs no Docker daemon at all, which is exactly what the GitHub Actions beginner guide workflow pattern assumes.

One naming trap: Chainguard’s commercial product Custom Assembly (customers customize Chainguard Containers via chainctl images repos build apply) is a different product from the open-source apko CLI. This guide covers the OSS tool you run yourself.

Where Does Melange Fit In?

Melange builds APK packages from source; apko assembles OCI images from packages. That is the handshake, and it is worth saying exactly once: use melange when you need a custom package that no public repository ships, and use apko alone whenever public Wolfi or Alpine packages are enough.

The classic real-world handshake is a custom nginx build: melange compiles your nginx with your configure flags into a signed APK, and apko assembles the final image from that package plus its dependencies on a minimal base. A community thread on packaging nginx with melange and apko on Wolfi shows exactly this split working in the wild — the melange YAML holds the build logic, and the apko YAML holds the image assembly.

Melange is a cluster member of this page, never its own article: it exists here only where the package pipeline touches the image pipeline. If you never need custom packages, you will use melange for exactly one command — melange keygen — and that is fine.

How Do You Use Apko Without Dockerfiles in CI?

Run apko in CI as a container image and call apko build followed by apko publish — the runner needs no Docker daemon and no Dockerfile anywhere in the repository. This is the "build container images without dockerfile" pattern in its production form.

A minimal job looks like this: check out the repo, run the apko container against your apko.yaml, then publish. Because the image is declared rather than scripted, the same YAML builds identically on your laptop and in CI — that reproducibility is the whole point of the composition model. The GitHub Actions workflows guide covers the workflow scaffolding; apko slots in as the build step.

Where do these images go? Onto the servers or clusters you already run. If those servers are virtual machines you manage yourself, the VPS hosting guide covers the hosting layer, and the Kubernetes beginner guide covers the orchestration layer where these minimal images shine brightest.

7 Mistakes Every Apko Beginner Makes

These are the traps the current docs and community threads warn about, collected in one place so you can step around all of them on day one.

#MistakeWhat to do instead
1Writing RUN-style logic in apko.yamlThere is no RUN — design for packages, and push compile steps into melange pipelines
2Running apko build before melange keygenKeys first, always: the image is a signed artifact
3Following 2023-era tutorials verbatimThe v0.9.0 schema moved — verify flags and fields against current docs
4Mixing Wolfi and Alpine packages in one buildOne APK ecosystem per build, per the Academy docs
5Committing melange.rsa to gitTreat the private key like any secret — keygen output stays out of the repo
6Expecting apko to compile codeCompilation is melange’s job; apko only assembles finished packages
7Hand-rolling publish scripts in CIUse apko publish — it builds all archs, pushes, and prints the digest in one command

Sources

Every fact in this guide was verified against sources fetched on 2026-11-02: the GitHub releases API for chainguard-dev/apko (v1.4.15, published 2026-11-02T00:30:45Z); the apko README on GitHub (official install methods); docs/apko_file.md (current config schema; "no support for running arbitrary Unix commands"); the Chainguard Academy "Getting started with apko" tutorial (updated 2026-10-02; verbatim Wolfi apko.yaml; distroless container install route; "solely a composition tool"; OCI compliance; one-ecosystem-per-build rule); the Academy Wolfi overview (Wolfi as a community Linux undistro on the APK format); the melange README (melange keygen behavior); the apko CLI source internal/cli/build.go (canonical build usage, --keyring-append, --sbom defaults); Chainguard’s Custom Assembly announcement and chainctl docs (the commercial product, kept distinct from OSS apko); gsantoro.dev’s 2023 apko walkthrough (cited as the dated v0.9.0-era guide it is); and the NGINX community forum thread on packaging nginx with melange and apko on Wolfi (the real-world package-to-image handshake).

Frequently Asked Questions

Is apko a replacement for Docker?

No — apko replaces the Dockerfile, not Docker itself. Apko images are OCI-compliant, so Docker runs them happily; and Chainguard’s FAQ confirms layering Dockerfiles on top of apko images is a supported use case. Think of it as a different way to produce the images your existing Docker or Kubernetes workflow consumes.

Do I need melange to use apko?

No — apko is useful on its own with public Wolfi or Alpine packages, and its author has said exactly that. You do need melange for exactly one thing in the beginner arc: melange keygen, which creates the signing keypair your builds require. Reach for melange’s build pipelines only when you need custom packages no repository ships.

What is the difference between apko and melange?

Melange builds APK packages from source code; apko assembles OCI container images from those packages. One produces the bricks, the other builds the house. They are designed to work together but apko does not require melange beyond key generation.

Can I use apko with GitHub Actions?

Yes — this is one of its best fits. Run the cgr.dev/chainguard/apko container in the job, call apko build then apko publish, and you need no Docker daemon, no Dockerfile, and no privileged runner. The declared YAML builds identically on your laptop and in CI.

Why is my apko build failing on package signatures?

Almost always a keyring problem: pass your public key with -k (--keyring-append) and make sure the YAML’s contents.keyring lists the signing keys for every repository you pull from — for Wolfi that includes https://packages.wolfi.dev/os/wolfi-signing.rsa.pub. Unsigned or untrusted packages fail the build by design.

Featured on Twelve Tools Launch Llama Tools Launch your MCP