docker-build-nix
Build and push Docker/OCI images generated by Nix flakes, with Attic cache integration.
Features
- Reproducible builds: Uses Nix flakes for bit-for-bit identical images
- Attic caching: Pushes build artifacts to your Attic cache for faster subsequent builds
- Nix store optimization: Leverages Nix's existing binary caches (nixos.org + your Attic)
- Smaller images: Nix
dockerTools.buildLayeredImage creates optimized layers
Usage
Basic example
name: Build Docker Image
on:
push:
branches: [main]
jobs:
build:
runs-on: nix # Requires runner with Nix
steps:
- uses: actions/checkout@v4
- uses: https://git.toph.so/toph/ci-actions/docker-build-nix@main
with:
flake-output: .#dojo-image
image-name: toph/dojo
registry-password: ${{ secrets.GITEA_TOKEN }}
env:
ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN }}
Multiple images
jobs:
build-web:
runs-on: nix
steps:
- uses: actions/checkout@v4
- uses: https://git.toph.so/toph/ci-actions/docker-build-nix@main
with:
flake-output: .#dojo-image
image-name: toph/dojo
image-tag: main
registry-password: ${{ secrets.GITEA_TOKEN }}
env:
ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN }}
build-agent:
runs-on: nix
steps:
- uses: actions/checkout@v4
- uses: https://git.toph.so/toph/ci-actions/docker-build-nix@main
with:
flake-output: .#agent-image
image-name: toph/dojo/agent
image-tag: main
registry-password: ${{ secrets.GITEA_TOKEN }}
env:
ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN }}
Inputs
| Input |
Required |
Default |
Description |
flake-output |
✅ |
- |
Nix flake output (e.g., .#dojo-image) |
image-name |
✅ |
- |
Target image name (e.g., user/repo) |
registry-password |
✅ |
- |
Registry password/token |
image-tag |
❌ |
main |
Image tag |
registry |
❌ |
git.toph.so |
Docker registry |
registry-username |
❌ |
${{ gitea.actor }} |
Registry username |
cache-name |
❌ |
ci |
Attic cache name |
attic-endpoint |
❌ |
https://cache.toph.so |
Attic endpoint |
Environment Variables
| Variable |
Required |
Description |
ATTIC_TOKEN |
Optional |
Attic token for pushing to cache. If not set, skips cache push. |
How It Works
- Build with Nix: Runs
nix build <flake-output> which uses Nix caching
- Push to Attic: Uploads the entire build closure to your Attic cache
- Load to Docker: Loads the OCI tarball into local Docker daemon
- Tag & Push: Tags and pushes to your Docker registry
Example Flake
Your flake.nix should export image outputs:
{
outputs = { self, nixpkgs }:
let
pkgs = import nixpkgs { system = "x86_64-linux"; };
in
{
packages.x86_64-linux = {
# Your app
default = pkgs.callPackage ./package.nix { };
# OCI image
dojo-image = pkgs.dockerTools.buildLayeredImage {
name = "dojo";
tag = "latest";
contents = [ self.packages.x86_64-linux.default ];
config = {
Cmd = [ "${self.packages.x86_64-linux.default}/bin/dojo" ];
};
};
};
};
}
Prerequisites
- Nix runner: Runner with
nix label using docker://registry.toph.so/nix-runner:latest
- Attic cache: Optional but recommended for caching (
cache.toph.so)
- ATTIC_TOKEN: Set in Forgejo secrets if you want cache push
- GITEA_TOKEN: Auto-available in Forgejo Actions
Comparison with docker-build
| Feature |
docker-build |
docker-build-nix |
| Build method |
Docker |
Nix |
| Reproducibility |
Layer-dependent |
Byte-for-byte |
| Caching |
S3 layers |
Attic derivations |
| Image size |
Larger |
Optimized |
| Runner |
Any |
Requires Nix |
See Also