Skip to content

OCI Stack Bundles

ReadyStackGo can pull stack definitions directly from OCI container registries like Docker Hub, GitHub Container Registry (GHCR), or Azure Container Registry. This enables versioned stack distribution via CI/CD pipelines and deterministic deployments with lock files.

FeatureDescription
OCI Registry SourceAdd a container registry as a stack source
Tag-based VersioningEach registry tag represents a stack version
Glob Tag FilteringFilter tags with patterns like v*, ams-*
Lock File SupportPin images to digests for deterministic deployments
Test ConnectionVerify registry access before adding a source
AuthenticationSupport for private registries with username/password

Step by Step: Adding an OCI Registry Source

Section titled “Step by Step: Adding an OCI Registry Source”

Go to SettingsStack SourcesAdd Source.

Choose OCI Registry from the source type selection.

Fill in the registry details:

  • Source ID – Unique identifier (e.g., my-oci-stacks)
  • Display Name – Human-readable name
  • Registry Host – Registry hostname without protocol (e.g., docker.io, ghcr.io, myregistry.azurecr.io)
  • Repository – Full repository path (e.g., myorg/rsgo-stacks)
  • Tag Pattern – Glob pattern to filter tags (default: * = all tags)

Step 4: Configure Authentication (Optional)

Section titled “Step 4: Configure Authentication (Optional)”

For private registries, provide credentials:

  • Username – Registry username
  • Password / Token – Access token or password
RegistryUsernamePassword
Docker HubDocker Hub usernameAccess Token
GHCRGitHub usernamePAT with read:packages
Azure CRService Principal IDService Principal Secret

Click Test Connection to verify access. The test lists available tags and shows a preview of the first 10 tags.

Click Create Source to add the registry. RSGO will immediately sync and load stacks from matching tags.


An OCI Stack Bundle is a container image with stack definition files as layers.

LayerMedia TypeContentRequired
1application/vnd.rsgo.stack.manifest.v1+yamlstack.yaml – RSGO ManifestYes
2application/vnd.rsgo.stack.lock.v1+jsonlock.json – Image DigestsNo
3application/vnd.rsgo.stack.meta.v1+jsonmeta.json – Marketplace MetadataNo

You can also use a standard Docker image with stack files at known paths:

/rsgo/stack.yaml # or stack.yml
/rsgo/lock.json # optional
/rsgo/meta.json # optional

RSGO automatically extracts these files from tar.gz layers during sync.


A lock file pins each service image to a specific digest (sha256:...) instead of a mutable tag. This ensures deployments use the exact same image regardless of tag changes.

{
"apiVersion": "1",
"stackName": "my-app",
"stackVersion": "1.0.0",
"images": [
{
"name": "web",
"image": "nginx",
"tag": "1.25-alpine",
"digest": "sha256:a8281ce42034b078dc7d88a5bfe6cb40...",
"role": "main"
},
{
"name": "cache",
"image": "redis",
"tag": "7-alpine",
"digest": "sha256:e422889e156a60c4e7f0ba0c3e5b..."
}
]
}
  1. If a lock file exists and contains an entry for a service → image@sha256:digest
  2. If no lock entry exists for a service → falls back to image:tag
  3. Lock files are optional — deployments work without them

FROM scratch
COPY stack.yaml /rsgo/stack.yaml
COPY lock.json /rsgo/lock.json
Terminal window
docker build -t ghcr.io/myorg/rsgo-stacks:v1.0.0 .
docker push ghcr.io/myorg/rsgo-stacks:v1.0.0
Terminal window
oras push ghcr.io/myorg/rsgo-stacks:v1.0.0 \
stack.yaml:application/vnd.rsgo.stack.manifest.v1+yaml \
lock.json:application/vnd.rsgo.stack.lock.v1+json
name: Publish Stack Bundle
on:
push:
tags: ['v*']
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Log in to GHCR
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build and push bundle
run: |
docker build -t ghcr.io/${{ github.repository }}/stacks:${{ github.ref_name }} .
docker push ghcr.io/${{ github.repository }}/stacks:${{ github.ref_name }}

  • Downloaded manifests are cached in ~/.rsgo/oci-cache/{sourceId}/{tag}/
  • On sync, RSGO checks the manifest digest — if unchanged, the cached version is used
  • Only new or changed tags trigger a re-download
  • Pagination is supported for repositories with more than 100 tags

POST /api/stack-sources/test-oci-connection
FieldTypeRequiredDescription
registryUrlstringYesRegistry hostname
repositorystringYesRepository path
usernamestringNoRegistry username
passwordstringNoRegistry password

Response:

{
"success": true,
"message": "Connection successful. Found 15 tag(s).",
"tagCount": 15,
"sampleTags": ["v1.0.0", "v1.1.0", "v2.0.0"]
}
POST /api/stack-sources
{
"id": "my-oci-stacks",
"name": "My OCI Stacks",
"type": "OciRegistry",
"registryUrl": "ghcr.io",
"repository": "myorg/rsgo-stacks",
"tagPattern": "v*",
"registryUsername": "user",
"registryPassword": "token"
}