Simple-Observability/grue

grue is a CLI that turns any S3-compatible bucket into a container registry

Go

3

0 commits

updated Sep 16, 2026

See the code

README

grue

grue - because S3 is all you need

Why run a container registry when you already have a S3?

grue is a CLI that turns any S3-compatible bucket into a container registry. It pushes and pulls Docker images directly to and from object storage. You can use Cloudflare R2, AWS S3, MinIO, Backblaze B2, or another S3-compatible store. Authentication uses your S3 API keys.

The whole program is one file, grue.go, and under 1000 lines of code.

Commands

  • grue connect - configure an S3-compatible storage backend
  • grue push <name[:tag]> - push a local image to the bucket
  • grue pull <name[:tag]> - pull an image from the bucket into Docker
  • grue ls - list repositories and tags
  • grue rm <name[:tag]> - delete a tag, or all tags of a repository

Usage

# Connect to S3
grue connect

# Push a local container image to your bucket
grue push my-image:1.2.3

# On another machine, pull it back
grue pull my-image:1.2.3

# The image appears in Docker
docker run my-image:1.2.3

Use env secrets:

GRUE_ACCESS_KEY=... grue push my-image:1.2.3

List what is in the bucket:

grue ls

Delete a tag:

grue rm my-image:old

Delete all tags of a repository:

grue rm my-image

Configuration

Environment variables take priority over the config file.

VariablePurpose
GRUE_ENDPOINTS3 endpoint URL
GRUE_REGIONRegion
GRUE_ACCESS_KEYAccess key
GRUE_SECRET_KEYSecret key
GRUE_BUCKETBucket name
GRUE_PREFIXKey prefix (default grue/)
GRUE_CONFIGPath to the config file

The config file is at ~/.config/grue/config.json by default. Override the path with GRUE_CONFIG.

GitHub Action

The grue action builds a Docker image and pushes it to your S3 bucket. You do not need a container registry.

Replace docker/build-push-action with the grue action. Then add your S3 credentials.

Before — push to a registry:

- uses: docker/build-push-action@v7
  with:
    context: .
    tags: myimage:latest
    push: true

After — push to S3:

- uses: Simple-Observability/grue@v1.0.0
  with:
    context: .
    tags: myimage:latest
    endpoint: ${{ secrets.GRUE_ENDPOINT }}
    bucket: ${{ secrets.GRUE_BUCKET }}
    access-key: ${{ secrets.GRUE_ACCESS_KEY }}
    secret-key: ${{ secrets.GRUE_SECRET_KEY }}

The grue action uses docker/build-push-action to build the image. All build inputs (build-args, target, cache-from, cache-to, platform, and more) are sent to it directly. See their inputs list for the full set.

Grue inputs

These inputs control the S3 connection and the grue binary. Build inputs are the same as docker/build-push-action.

InputDescriptionDefault
tagsImage refs to push, one per linerequired
endpointS3 endpoint URL
regionS3 region
bucketS3 bucket name
prefixKey prefix in the bucket (default grue/)
access-keyS3 access key
secret-keyS3 secret key
grue-versiongrue binary version, from GitHub releaseslatest

Limitations

  • No blob garbage collection. rm deletes tags only; the blobs they referenced are retained. A future gc/prune command is planned.
  • One platform per tag. The action builds one platform at a time. grue stores one image per tag. There is no multi-arch index.
container-image
container-registry
docker

Simple-Observability/grue

grue is a CLI that turns any S3-compatible bucket into a container registry

Go

3

0 commits

updated Sep 16, 2026

See the code

README

grue

grue - because S3 is all you need

Why run a container registry when you already have a S3?

grue is a CLI that turns any S3-compatible bucket into a container registry. It pushes and pulls Docker images directly to and from object storage. You can use Cloudflare R2, AWS S3, MinIO, Backblaze B2, or another S3-compatible store. Authentication uses your S3 API keys.

The whole program is one file, grue.go, and under 1000 lines of code.

Commands

  • grue connect - configure an S3-compatible storage backend
  • grue push <name[:tag]> - push a local image to the bucket
  • grue pull <name[:tag]> - pull an image from the bucket into Docker
  • grue ls - list repositories and tags
  • grue rm <name[:tag]> - delete a tag, or all tags of a repository

Usage

# Connect to S3
grue connect

# Push a local container image to your bucket
grue push my-image:1.2.3

# On another machine, pull it back
grue pull my-image:1.2.3

# The image appears in Docker
docker run my-image:1.2.3

Use env secrets:

GRUE_ACCESS_KEY=... grue push my-image:1.2.3

List what is in the bucket:

grue ls

Delete a tag:

grue rm my-image:old

Delete all tags of a repository:

grue rm my-image

Configuration

Environment variables take priority over the config file.

VariablePurpose
GRUE_ENDPOINTS3 endpoint URL
GRUE_REGIONRegion
GRUE_ACCESS_KEYAccess key
GRUE_SECRET_KEYSecret key
GRUE_BUCKETBucket name
GRUE_PREFIXKey prefix (default grue/)
GRUE_CONFIGPath to the config file

The config file is at ~/.config/grue/config.json by default. Override the path with GRUE_CONFIG.

GitHub Action

The grue action builds a Docker image and pushes it to your S3 bucket. You do not need a container registry.

Replace docker/build-push-action with the grue action. Then add your S3 credentials.

Before — push to a registry:

- uses: docker/build-push-action@v7
  with:
    context: .
    tags: myimage:latest
    push: true

After — push to S3:

- uses: Simple-Observability/grue@v1.0.0
  with:
    context: .
    tags: myimage:latest
    endpoint: ${{ secrets.GRUE_ENDPOINT }}
    bucket: ${{ secrets.GRUE_BUCKET }}
    access-key: ${{ secrets.GRUE_ACCESS_KEY }}
    secret-key: ${{ secrets.GRUE_SECRET_KEY }}

The grue action uses docker/build-push-action to build the image. All build inputs (build-args, target, cache-from, cache-to, platform, and more) are sent to it directly. See their inputs list for the full set.

Grue inputs

These inputs control the S3 connection and the grue binary. Build inputs are the same as docker/build-push-action.

InputDescriptionDefault
tagsImage refs to push, one per linerequired
endpointS3 endpoint URL
regionS3 region
bucketS3 bucket name
prefixKey prefix in the bucket (default grue/)
access-keyS3 access key
secret-keyS3 secret key
grue-versiongrue binary version, from GitHub releaseslatest

Limitations

  • No blob garbage collection. rm deletes tags only; the blobs they referenced are retained. A future gc/prune command is planned.
  • One platform per tag. The action builds one platform at a time. grue stores one image per tag. There is no multi-arch index.
container-image
container-registry
docker

Languages

Go

100.0%