Build containers. Skip the daemon.
Quick Start | Features | CLI Reference | Go Library
Gib is a lightweight, daemonless container image builder and a drop-in replacement for Jib CLI. One static binary, no JVM. Your existing jib.yaml files just work.
- Drop-in Jib replacement — 100% compatible with
jib.yamlbuild files - No runtime dependencies — builds container images directly, no daemon or JVM needed
- Go library — use programmatically in your Go applications
- Powered by go-containerregistry — battle-tested container image library
- Modern CLI — powered by Fang
With mise-gib (recommended):
mise plugin install gib https://github.com/jbadeau/mise-gib.git
mise install gib@latest
mise use gib@latestWith go install:
go install github.com/jbadeau/gib/cmd/gib@latestgib build --target=my-registry.example.com/my-app:latestgib build --target=tar://my-image.tar --name=my-app:latestAs Jib writes it, a Docker-format image's tarball is a docker save
archive naming the image by every tag, and an OCI-format image's is an
OCI image layout, the manifest among its blobs with its exact bytes.
docker load reads either, and gib push pushes the very manifest the
build wrote.
gib build --target=docker://my-app:latestThe image is loaded into the Docker daemon DOCKER_HOST names, as docker load would load it.
gib push my-image.tar my-registry.example.com/my-app:1.4.0Build once, push later: push builds nothing. It pushes every blob and
every manifest with the bytes the tarball holds, so the digest the
registry reports, printed on stdout, is the digest the tarball was
written with; only the tag is new.
- OCI image layout (
index.json, asgib build,crane pull --format=ocior apko write): anindex.jsonnaming one image pushes that image; one naming an index pushes the index, children and all. Blobs are found by their content wherever the tarball keeps them, so apko's tarball, whoseindex.jsonis itself the index of every architecture it built, is pushed as that multi-arch index. - docker-save archive (
manifest.jsononly): the config and layers are pushed as they are, under the Docker schema 2 manifest describing them, the manifestcrane pushor a registry pull ofdocker load's image would carry. An archive of compressed layers pushes those bytes; one of uncompressed layers has them compressed first, so its digest is that of the compressed image.
gib build --target=tar://amd64.tar --parameter=arch=amd64 --platform=linux/amd64 --name=my-app
gib build --target=tar://arm64.tar --parameter=arch=arm64 --platform=linux/arm64 --name=my-app
gib push amd64.tar arm64.tar my-registry.example.com/my-app:1.4.0Jib lays the same layers on every platform it builds for, so an image
whose layers differ by platform, a Go program linked for each, is built
once per platform. push given several tarballs, each one image, pushes
every image with its exact bytes and an image index naming each by the
platform its config states, in the order given: a Docker manifest list
of Docker-format images, an OCI index of OCI images. Two images for one
platform, or images of both formats, are refused. The same images in
the same order make the same index, so its digest is reproducible.
The reference names a tag; one naming a digest is refused, the digest
being the tarball's. A tarball holding several tagged images is pushed
only when exactly one of them is tagged in the reference's repository.
Credentials resolve as for gib build.
apiVersion: jib/v1alpha1
kind: BuildFile
from:
image: ubuntu
entrypoint: ["/app/run.sh"]
layers:
entries:
- name: app
files:
- src: .
dest: /appgib build --target <image> [options] [@<argfile>...]
gib build takes the options of jib build, and refuses what it
refuses: a command line Jib rejects exits 2, a build that fails exits
- The container settings of
jib jarandjib war(--entrypointand the like) belong in the build file. Two options are gib's own:--frombuilds on another base image than the build file names, such as a tarball a sandboxed build is handed in place of a registry pull, and--platformbuilds for one platform in place of the build file's, for an image built once per platform.
| Option | Description |
|---|---|
-t, --target |
(required) Target image: a reference, registry://<ref>, docker://<ref> or tar://<path> |
--name |
The image's name in a tarball (required with tar://) |
--from |
The base image, in place of the build file's from.image (gib only) |
--platform |
The one platform, os/arch, to build for, in place of the build file's from.platforms (gib only) |
-b, --build-file |
Build file path (default: <context>/jib.yaml) |
-c, --context |
Build context directory (default: .) |
-p, --parameter |
Template parameter name=value (repeatable) |
--additional-tags |
Extra tags, comma separated (repeatable) |
--credential-helper |
A credential helper: its path, or the suffix of docker-credential-<suffix> |
--username / --password |
Credentials for both registries; --password alone prompts for it |
--to-*, --from-* |
The same, for the target or the base image registry alone |
--allow-insecure-registries |
Reach a registry without TLS verification, then over HTTP |
--send-credentials-over-http |
Send credentials over plain HTTP |
--image-metadata-out |
Write the image's digest, ID and tags to a JSON file |
--verbosity |
quiet, error, warn, lifecycle (default), info or debug |
--console |
auto (default), rich or plain |
Without credentials given, they are found where Jib finds them: Podman's
auth.json, Docker's config.json (its credential helpers too),
docker-credential-gcr for gcr.io and docker-credential-ecr-login
for amazonaws.com, and Google's Application Default Credentials.
Registry mirrors are read from Jib's global config.json.
Run gib build --help for the full list of options.
gib push <tarball>... <reference> [options]
| Option | Description |
|---|---|
--to-username / --to-password |
Target registry credentials |
--to-credential-helper |
Target registry credential helper |
--username / --password, --credential-helper |
Fallbacks for the above |
--allow-insecure-registries |
Reach a registry without TLS verification, then over HTTP |
Use Gib programmatically to build container images in your Go applications:
builder := gib.From("ubuntu:22.04").
SetEntrypoint("sh", "run.sh").
SetUser("appuser").
SetWorkingDirectory("/app")
result, err := builder.Containerize(
context.Background(),
gib.ToRegistry("my-registry.example.com/app:v1"),
)Or build from an existing jib.yaml:
spec, _ := buildfile.Parse("jib.yaml", nil)
builder, _ := buildfile.Convert(spec, ".", nil)
result, _ := builder.Containerize(ctx, gib.ToTar("image.tar", gib.WithTarImageName("app")))