Documents
Utility Images: flatpak and flatpak-builder
Utility Images: flatpak and flatpak-builder
Type
Document
Status
Published
Created
Jun 4, 2026
Updated
Jun 4, 2026
Updated by
Dosu Bot

Utility Images: flatpak and flatpak-builder#

Overview#

The aetherpak/flatpak-containers repository publishes two utility container images — ghcr.io/aetherpak/flatpak and ghcr.io/aetherpak/flatpak-builder — that provide a self-contained Flatpak toolchain for building and distributing Flatpak applications .

Both images are built on top of registry.fedoraproject.org/fedora-minimal, with the base digest pinned for reproducibility . This means every build of these images — locally or in CI — starts from exactly the same upstream layer, eliminating "it worked on my machine" drift caused by upstream image updates.

They serve two primary purposes within the AetherPak ecosystem:

  1. Foundation for the AetherPak CLI images. The ghcr.io/aetherpak/cli:<version> and ghcr.io/aetherpak/cli:<version>-builder images are built directly on top of these utility images. Every tagged CLI release inherits its Flatpak toolchain from a specific flatpak-containers build .

  2. Local development of the AetherPak CLI itself. The images can be pulled directly to develop and test the aetherpak CLI source code in an environment that closely mirrors the AetherPak CI pipeline .

Runtime use of the AetherPak CLI. If you want to run a released version of the aetherpak CLI in a container, use the ghcr.io/aetherpak/cli images instead — NOT the utility images. The aetherpak/cli containers come in two variants: a vanilla variant based on aetherpak/flatpak and a builder image variant based on aetherpak/flatpak-builder. The key distinction: the utility images (flatpak and flatpak-builder) are for CLI development; the aetherpak/cli containers are for runtime/production use of the CLI.

A key design goal is parity with the Flathub GitHub Actions builder environment. The tool selection — including flatpak-builder-lint pulled directly from the flathub-infra GitHub organisation — is chosen to ensure that linting and build behaviour is consistent whether a package is built locally against these images or in Flathub's own CI .

Supported use cases. These images are designed and maintained for AetherPak's internal needs. While they can be used independently for general Flatpak development workflows, that use case is not explicitly supported.

Available Images#

ghcr.io/aetherpak/flatpak:latest — the base image#

This is the lighter of the two images. It installs the minimum set of tools needed to run most aetherpak commands (import, push-oci, build-site) and provides a pre-configured Flathub remote .

PropertyValue
Baseregistry.fedoraproject.org/fedora-minimal (pinned by digest)
Working directory/workspace
Default command/bin/bash

Included packages :

PackagePurpose
flatpakFlatpak runtime and CLI
ostreeOSTree library and CLI
ca-certificatesTLS root certificates
gitVersion control (manifest sources, submodules)
jqJSON processing
curlHTTP downloads
tar / gzipArchive utilities
gnupg2GPG signing and verification
shared-mime-infoMIME type database (required by Flatpak)

Packages are installed with --setopt=install_weak_deps=0 --nodocs to minimise image size, and the microdnf cache is cleaned immediately after .

The Flathub repository remote is pre-configured during the image build so that runtimes and SDKs can be resolved without any additional setup :

flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo

ghcr.io/aetherpak/flatpak-builder:latest — the builder image#

This image extends the base image via a multi-stage build and adds everything required to compile a Flatpak from a manifest . It is the image used whenever flatpak-builder needs to run — for example, during the build-manifest job in the AetherPak reusable workflow.

PropertyValue
Baseghcr.io/aetherpak/flatpak (via --build-arg BASE_IMAGE)
Working directory/workspace (inherited from base)
Default command/bin/bash (inherited from base)

Additional packages :

PackagePurpose
flatpak-builderFlatpak manifest build tool
elfutilsELF binary analysis (debuginfo extraction)
appstreamAppStream metadata validation
desktop-file-utils.desktop file validation
python3-pipPython package installer (required for lint tool)
gobject-introspectionGObject type introspection
cairo2D graphics library (dependency of lint tool)
patchApply source patches from manifests
unzip / bzip2 / zstdAdditional archive format support

flatpak-builder-lint is installed from source using pip3 :

pip3 install --no-cache-dir git+https://github.com/flathub-infra/flatpak-builder-lint.git

To compile this tool, a set of build-time dependencies (gcc, pkgconf, cairo-devel, cairo-gobject-devel, gobject-introspection-devel, python3-devel, glib2-devel) are installed, used, and then removed in the same RUN layer to keep the final image size lean .

Architecture Support#

Both images are published as multi-architecture OCI manifests covering linux/amd64 and linux/arm64 . Container runtimes (Docker, Podman) will automatically select the correct variant for the host machine when pulling the manifest-list tag.

Builds run on native runners for each architecture — ubuntu-latest for amd64 and ubuntu-24.04-arm for arm64 — avoiding the performance overhead of emulation . Each architecture produces an architecture-suffixed intermediate tag (sha-{SHORT_SHA}-amd64 / sha-{SHORT_SHA}-arm64). Once both architecture builds succeed, a merge-manifests job uses podman manifest create/add/push to combine them into a single manifest list under the final tag .

Single-architecture tags (e.g. latest-amd64, latest-arm64) are also promoted via skopeo copy for use cases where a specific architecture must be targeted explicitly .

Architecture limitations. Only x86_64 (amd64) and aarch64 (arm64) are supported. There is no cross-compilation support; each architecture is built natively .

Relationship to AetherPak CLI Images#

The flatpak-containers images are the foundation of the AetherPak CLI container images. The aetherpak/cli Containerfile defines two build arguments that reference them directly :

ARG BASE_IMAGE=ghcr.io/aetherpak/flatpak:latest
ARG BUILDER_IMAGE=ghcr.io/aetherpak/flatpak-builder:latest

The aetherpak binary is compiled separately (in a golang:1.26-alpine builder stage) and then copied into both images , producing two final stages:

CLI Image TagContainerfile StageBaseContents
ghcr.io/aetherpak/cli:<version>clighcr.io/aetherpak/flatpakaetherpak + full flatpak toolchain
ghcr.io/aetherpak/cli:<version>-buildercli-builderghcr.io/aetherpak/flatpak-builderaetherpak + flatpak-builder + lint tools

In practice, the AetherPak reusable workflow selects the appropriate CLI image based on the job type :

  • ghcr.io/aetherpak/cli:<version> is used by plan, prep-bundle, publish-oci, and publish-site jobs — steps that only need the Flatpak client, OSTree tooling, and the aetherpak binary.
  • ghcr.io/aetherpak/cli:<version>-builder is used by the build-manifest job — the step that actually compiles the Flatpak from a manifest using flatpak-builder.

This split keeps the non-build jobs fast by avoiding the overhead of pulling the heavier builder image when only the base toolchain is required.

Flathub Parity#

A core goal of these images is to closely mirror the GitHub Actions builder environment that Flathub uses for its own CI pipeline. This matters because:

  • Consistent lint results. Flatpak manifest linting is done by flatpak-builder-lint, a tool maintained by the flathub-infra organisation. Running the same version locally (via ghcr.io/aetherpak/flatpak-builder) ensures that any lint failures you see in the AetherPak CI will also surface when you run checks locally, and vice versa.
  • Reproducible builds. The package set in the builder image (elfutils, appstream, desktop-file-utils, gobject-introspection, cairo, etc.) mirrors the compilation toolchain expected by Flatpak manifests published to Flathub.
  • Pre-configured Flathub remote. The base image adds the Flathub OSTree repository as a remote during the image build . This means flatpak-builder can resolve runtimes and SDKs from Flathub without any additional setup step.

The most direct expression of this parity is the flatpak-builder-lint installation. Rather than pulling a versioned release from PyPI, the builder image installs directly from the canonical upstream source :

pip3 install --no-cache-dir git+https://github.com/flathub-infra/flatpak-builder-lint.git

This ensures the lint tool is always sourced from the same repository that Flathub itself maintains, keeping AetherPak's validation behaviour in sync with Flathub's expectations.

Note. While AetherPak aims for parity with Flathub's build environment, the images are not formally tested against Flathub's own builder configuration and may diverge over time. If you are preparing a submission to Flathub, always run a final validation in Flathub's own CI.

Building the Images Locally#

The source repository is at github.com/aetherpak/flatpak-containers. A single Containerfile defines both images using named --target stages: flatpak and flatpak-builder .

To build the images locally, clone the repository and run:

# Build the base image
podman build -t flatpak:local --target flatpak .

# Build the builder image (uses the local flatpak image as its base)
podman build \
  -t flatpak-builder:local \
  --target flatpak-builder \
  --build-arg BASE_IMAGE=flatpak:local \
  .

The --build-arg BASE_IMAGE=flatpak:local argument is important: without it, the flatpak-builder stage defaults to the flatpak stage name within the multi-stage build context. Passing an explicit tag lets you point the builder stage at any base image — including a locally modified or custom-tagged variant .

Once built, reference the local tags in a compose.yml to use them in place of the published images:

services:
  builder:
    image: flatpak-builder:local
    volumes:
      - .:/workspace
    working_dir: /workspace
    privileged: true
    command: sleep infinity

CI Build Behaviour#

In the published CI workflow, image builds are only triggered when the Containerfile or the CI workflow file itself changes, or when a build is dispatched manually . This avoids unnecessary rebuilds on documentation-only or unrelated code changes.

Usage Outside AetherPak#

The flatpak-containers images are general-purpose Fedora-based Flatpak toolchain images. They can be used independently for any workflow that needs flatpak, flatpak-builder, or the associated tooling without depending on the aetherpak binary. For example, you could use them to run flatpak-builder directly, validate manifests with flatpak-builder-lint, or as a base layer for custom container images.

That said, this use case is not explicitly supported. These images are designed and maintained to serve AetherPak's internal needs: providing a consistent, reproducible base for the CLI images and for local development against the AetherPak CI pipeline . Breaking changes to package versions, image layout, or tag conventions may be made without advance notice if they benefit the AetherPak workflow.

If you do use these images outside of AetherPak, keep the following in mind:

  • Privileged mode is required for flatpak-builder builds. flatpak-builder needs to write to the system Flatpak installation when installing runtimes and SDKs from the pre-configured Flathub remote. In a container environment, the polkit/dbus system helper is not available, so the container must run as root with --privileged .
  • No cross-compilation. Architecture support is limited to linux/amd64 and linux/arm64; there is no cross-compilation toolchain included .
  • Pin a specific digest. The latest tag moves forward with each push to main. For reproducible workflows outside AetherPak, pin to an immutable digest or a specific version tag rather than latest.
Utility Images: flatpak and flatpak-builder | Dosu