# Openship Image-Registry Container Image Management: Registry Resolution and Drift Detection

> Discover Openship image-registry container image management. Track image names, references, and digests for automated drift detection and registry-agnostic credential lookup.

- Repository: [oblien/openship](https://github.com/oblien/openship)
- Tags: deep-dive
- Published: 2026-08-19

---

**Openship treats every container image as a first-class resource by tracking the user-defined image name, resolved registry reference, and immutable SHA256 digest in the service database schema, enabling automated drift detection and registry-agnostic credential lookup.**

Openship is an open-source deployment platform that manages containerized applications across multiple environments. The `oblien/openship` repository implements a robust **image-registry container image management** system that tracks image provenance from registry resolution through runtime deployment. Understanding how Openship handles container images is essential for operating services securely and detecting configuration drift.

## Core Database Schema for Container Images

In [`packages/db/src/schema/service.ts`](https://github.com/oblien/openship/blob/main/packages/db/src/schema/service.ts), the service table defines three critical columns that form the foundation of image tracking:

- **`image`**: The user-provided image name (e.g., `postgres:16` or `ghcr.io/oblien/openship-api:v3`)
- **`imageRef`**: The concrete tag that was actually pulled during deployment
- **`imageDigest`**: The immutable SHA256 content-addressable digest of the running image

According to the source code in [`packages/db/src/schema/service.ts`](https://github.com/oblien/openship/blob/main/packages/db/src/schema/service.ts) (lines 89-95), these fields enable Openship to distinguish between the intended image specification and the actual runtime state. When the deployment scanner processes a service, it populates `imageRef` and `imageDigest` by inspecting the pulled container image (lines 262-268), then persists this runtime information to enable rollback capabilities and drift detection (lines 251-262).

## Registry Resolution and Normalization

Openship resolves ambiguous image references to specific registry hosts using the `registryForImage` helper function defined in [`packages/core/src/image-ref.ts`](https://github.com/oblien/openship/blob/main/packages/core/src/image-ref.ts) (lines 7-20). This function parses image references to extract the registry hostname, handling edge cases such as:

- Images without explicit registries (defaulting to Docker Hub)
- Scheme-prefixed hosts (`https://ghcr.io`)
- Trailing slashes and normalization

For credential lookup, Openship uses `registryConfigKeys` (lines 95-103) to generate all possible key variations for a given host. This ensures that credentials match regardless of how the registry was specified, expanding `registry.example.com` into variants like `https://registry.example.com` and `registry.example.com/`.

## Deployment Scanning and Digest Tracking

During the deployment lifecycle, Openship's scanner records the exact image state:

1. The user defines a service with an `image` specification
2. The deployment process pulls the image and resolves the full reference (`imageRef`)
3. The system computes the SHA256 digest (`imageDigest`) of the pulled image
4. Both values are stored in the database alongside the service record

This digest serves as the authoritative proof that the running container matches the scanned version, preventing "dependency confusion" attacks and enabling immutable deployments.

## Drift Detection in the Dashboard

The [`apps/dashboard/src/utils/deploymentPhaseDetector.ts`](https://github.com/oblien/openship/blob/main/apps/dashboard/src/utils/deploymentPhaseDetector.ts) implements logic that compares the stored `imageDigest` against the latest digest available in the registry. When differences are detected, Openship flags the service as "behind" and surfaces a "swap image" action in the UI. This drift detection mechanism ensures operators can identify services running outdated or modified images compared to their registry counterparts.

## CI/CD Image Publishing Pipeline

Openship supports a Docker-only release path defined in [`scripts/release.ts`](https://github.com/oblien/openship/blob/main/scripts/release.ts) (lines 156-166) that publishes pre-built images to GitHub Container Registry (GHCR) without modifying Git tags or "latest" tags. This path is executed by the [`docker-images.yml`](https://github.com/oblien/openship/blob/main/docker-images.yml) workflow to push the API, dashboard, and edge images, demonstrating how the platform manages its own container artifacts using the same registry abstractions provided to user services.

## Practical Code Examples

### Resolving a Registry from an Image Reference

```typescript
import { registryForImage } from "@openship/core/image-ref";

const ref = "ghcr.io/oblien/openship-api:0.6.5";
const registry = registryForImage(ref);   // → "ghcr.io"

```

### Generating Credential Lookup Keys

```typescript
import { registryConfigKeys } from "@openship/core/image-ref";

const keys = registryConfigKeys("registry.example.com");
/* keys includes:
   - "registry.example.com"
   - "https://registry.example.com"
   - "registry.example.com/"
*/

```

### Querying Service Image Metadata

```typescript
import { db } from "@openship/db";
import { eq } from "drizzle-orm";

const service = await db.select()
  .from("service")
  .where(eq("serviceId", "svc-123"))
  .one();

console.log({
  image: service.image,           // user‑provided name
  imageRef: service.imageRef,    // concrete tag pulled
  digest: service.imageDigest,   // SHA256 of the pulled image
});

```

## Summary

- **Triple-field tracking**: Openship stores `image`, `imageRef`, and `imageDigest` in [`packages/db/src/schema/service.ts`](https://github.com/oblien/openship/blob/main/packages/db/src/schema/service.ts) to maintain complete provenance of container deployments.
- **Registry normalization**: The `registryForImage` and `registryConfigKeys` utilities in [`packages/core/src/image-ref.ts`](https://github.com/oblien/openship/blob/main/packages/core/src/image-ref.ts) handle registry host extraction and credential key generation across various reference formats.
- **Immutable verification**: The `imageDigest` field provides content-addressable verification of running containers, enabling secure rollback and drift detection.
- **CI integration**: The [`scripts/release.ts`](https://github.com/oblien/openship/blob/main/scripts/release.ts) pipeline demonstrates Docker-only releases to GHCR, separating image publication from version control tagging.

## Frequently Asked Questions

### How does Openship handle different container registry formats?

Openship normalizes registry hosts by stripping URL schemes, trailing slashes, and lower-casing hostnames using the `registryForImage` function in [`packages/core/src/image-ref.ts`](https://github.com/oblien/openship/blob/main/packages/core/src/image-ref.ts). The `registryConfigKeys` utility then generates all possible credential lookup variations, ensuring authentication succeeds regardless of whether users specify `https://ghcr.io`, `ghcr.io/`, or `ghcr.io`.

### What is the difference between imageRef and imageDigest in Openship?

The `imageRef` field stores the concrete tag that was pulled (e.g., `ghcr.io/oblien/openship-api:v3`), while `imageDigest` contains the immutable SHA256 hash of that specific image. The digest serves as the authoritative fingerprint for drift detection, allowing Openship to identify when a running container no longer matches the registry's current version of that tag.

### How does Openship detect when a service is running an outdated image?

The dashboard's [`deploymentPhaseDetector.ts`](https://github.com/oblien/openship/blob/main/deploymentPhaseDetector.ts) compares the `imageDigest` stored in the database against the latest digest available from the registry. If the digests differ, Openship flags the service as having drift and presents a "swap image" action, enabling operators to update to the latest version or rollback to a previous digest.

### Where does Openship store credentials for private container registries?

Registry credentials are managed through the `registryConfigKeys` abstraction in [`packages/core/src/image-ref.ts`](https://github.com/oblien/openship/blob/main/packages/core/src/image-ref.ts), which expands normalized hostnames into all possible key formats for lookup in Openship's credential store. This allows the system to match credentials against various registry URL formats while keeping the underlying credential storage implementation agnostic to reference formatting.