Skip to content

Registry Connections

Registry connections link BRIDGEPORT to your container registries, enabling update detection, tag browsing, digest-based comparison, and automated deployments.

Connect BRIDGEPORT to your container registry in under a minute:

  1. Go to Orchestration > Registries in the sidebar.
  2. Click Add Registry.
  3. Select your registry type, enter the URL and credentials.
  4. Click Test Connection to verify.
  5. Click Save.

BRIDGEPORT will start checking for image updates every 30 minutes automatically.


BRIDGEPORT supports three registry types. The “Generic” type covers any Docker Registry V2-compatible service, which includes most private registries.

TypeDescriptionAuth MethodUse For
DigitalOceanDigitalOcean Container RegistryAPI token (Bearer)DO-hosted registries
Docker HubDocker Hub public and private reposUsername/password or access tokenPublic images, Docker Hub private repos
GenericAny Docker Registry V2-compatible APIUsername/password (Basic)Harbor, GitLab Container Registry, GitHub Container Registry (GHCR), AWS ECR, self-hosted registries

The Generic client works with any registry that implements the OCI Distribution Spec. Tested registries include:

  • Harborhttps://harbor.example.com
  • GitLab Container Registryhttps://registry.gitlab.com
  • GitHub Container Registry (GHCR)https://ghcr.io
  • AWS ECRhttps://<account>.dkr.ecr.<region>.amazonaws.com (use AWS as username, ECR auth token as password)
  • Self-hosted Docker Registryhttps://registry.example.com

BRIDGEPORT’s registry system connects your container registries to the Container Images system. Registries are checked on a schedule, and when new tags are detected, the information flows through to linked images and services.

sequenceDiagram
    participant Sched as Scheduler
    participant BP as BRIDGEPORT
    participant Reg as Container Registry
    participant DB as Database

    Sched->>BP: Time to check (every N minutes)
    BP->>DB: Fetch images with registryConnectionId
    BP->>DB: Decrypt registry credentials

    loop For each image
        BP->>Reg: List tags for repository
        Reg-->>BP: Tags with digests + timestamps
        BP->>BP: detectUpdate()<br/>Compare current vs latest
        BP->>DB: Update latestTag, latestDigest, updateAvailable

        alt autoUpdate enabled AND update found
            BP->>BP: Build deployment plan
            BP->>BP: Execute plan (deploy to all services)
        end
    end

  1. Navigate to Orchestration > Registries.
  2. Click Add Registry.
  3. Fill in the form:
FieldRequiredDescription
NameYesDisplay name (e.g., “Production DO Registry”). Must be unique per environment.
TypeYesdigitalocean, dockerhub, or generic
Registry URLYesThe registry endpoint (see Authentication for examples)
Repository PrefixNoNarrows repository listing (e.g., my-registry for DO)
CredentialsDependsToken, or username/password — varies by type
DefaultNoMark as default registry for this environment
Refresh IntervalNoMinutes between update checks (default: 30, range: 5-1440)
Auto-Link PatternNoGlob pattern for auto-linking discovered images
  1. Click Test Connection to verify credentials and connectivity.
  2. Click Save.
POST /api/environments/:envId/registries
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Production DO Registry",
"type": "digitalocean",
"registryUrl": "https://api.digitalocean.com/v2/registry",
"repositoryPrefix": "my-registry",
"token": "dop_v1_abc123...",
"isDefault": true,
"refreshIntervalMinutes": 30,
"autoLinkPattern": "myapp-*"
}

Response (200):

{
"registry": {
"id": "clxyz...",
"name": "Production DO Registry",
"type": "digitalocean",
"registryUrl": "https://api.digitalocean.com/v2/registry",
"repositoryPrefix": "my-registry",
"hasToken": true,
"hasPassword": false,
"isDefault": true,
"refreshIntervalMinutes": 30,
"autoLinkPattern": "myapp-*"
}
}

Each registry type accepts different credential formats:

Registry URL: https://api.digitalocean.com/v2/registry
Token: dop_v1_abc123... (DO personal access token with registry read scope)
Prefix: my-registry (your registry name)

The DO client uses two APIs: the DigitalOcean management API for tag listing, and the Docker Registry V2 API (registry.digitalocean.com) as a fallback for manifest digests.

Registry URL: https://hub.docker.com
Username: myuser
Password: dckr_pat_abc123... (Docker Hub access token recommended over password)

For public repositories, credentials are optional but recommended to avoid rate limits. For private repositories, credentials are required.

Registry URL: https://registry.example.com (the registry's base URL)
Username: myuser
Password: mypassword

The Generic client authenticates via HTTP Basic auth and communicates using the standard Docker Registry V2 API (/v2/ endpoints).

GHCR example:

Registry URL: https://ghcr.io
Username: USERNAME
Password: ghp_abc123... (GitHub personal access token with read:packages scope)

GitLab example:

Registry URL: https://registry.gitlab.com
Username: gitlab-ci-token (or your username for personal tokens)
Password: glpat-abc123... (GitLab personal access token with read_registry scope)

Stored credentials are also used at deploy time to authenticate the target server against the registry, so docker pull and docker compose pull succeed for private images without any manual docker login on the box.

How it works:

  • SSH-mode servers. Before the first pull from a given registry, BRIDGEPORT runs docker login over SSH. The password is written to a 0600 temp file and piped into --password-stdin — it is never passed as a CLI argument and never appears in ps or shell history. The temp file is removed in a finally, even if login fails. The resulting auth lives in the SSH user’s ~/.docker/config.json on the server and is reused for subsequent pulls.
  • Socket-mode servers. When BRIDGEPORT talks directly to a local Docker daemon, no persistent state is written. Credentials are passed in-process to dockerode’s pull() via the authconfig option for each pull.

Login state is tracked per (server, registry) in the ServerRegistryLogin table. BRIDGEPORT skips the login step when an existing row is at least as fresh as the registry’s updatedAt. Editing any auth-relevant field on a registry connection (token, username, password, registryUrl, type) deletes all of that registry’s login rows, forcing a re-login on the next deploy with the new credentials. Metadata-only edits (name, auto-link pattern, refresh interval, default flag) leave the cache intact.

DigitalOcean uses the API token as both the username and the password for docker login registry.digitalocean.com. Docker Hub omits the host argument so docker login uses its index.docker.io default. Generic registries use the registry hostname (scheme and any trailing /v2 are stripped).

If login fails — for example, a revoked token — the deploy fails fast with docker login failed: <reason> instead of falling through to a confusing “image not found” later.


Each registry connection has a configurable refresh interval that controls how often BRIDGEPORT checks for new tags.

SettingRangeDefault
refreshIntervalMinutes5 — 1440 (24 hours)30 minutes

The global scheduler runs at the interval configured by SCHEDULER_UPDATE_CHECK_INTERVAL (default: 1800 seconds / 30 minutes). During each run, it checks all container images whose linked registry is due for a refresh.

You can trigger an immediate update check for all images linked to a registry:

POST /api/registries/:id/check-updates
Authorization: Bearer <token>

Returns results for each checked service:

{
"results": [
{ "serviceId": "svc1", "name": "app-api", "hasUpdate": true, "latestTag": "v2.4.0" },
{ "serviceId": "svc2", "name": "app-worker", "hasUpdate": false }
],
"summary": {
"checked": 2,
"withUpdates": 1,
"errors": 0
}
}

An auto-link pattern is a string that BRIDGEPORT matches against image names during container discovery. When a new container is discovered and its image name matches the pattern, BRIDGEPORT creates a ContainerImage linked to this registry automatically.

Examples:

PatternMatches
myapp-*myapp-backend, myapp-frontend, myapp-worker
registry.example.com/*Any image from registry.example.com
(empty)No auto-linking (manual linking only)

Set the pattern when creating or editing a registry:

PATCH /api/registries/:id
Authorization: Bearer <token>
Content-Type: application/json
{
"autoLinkPattern": "myapp-*"
}

Once a container image is linked to a registry, you can browse its available tags:

GET /api/container-images/:id/tags
Authorization: Bearer <token>

List all repositories in the registry:

GET /api/registries/:id/repositories
Authorization: Bearer <token>

List tags for a specific repository:

GET /api/registries/:id/repositories/:repo/tags
Authorization: Bearer <token>

Each tag includes:

FieldDescription
tagTag name (e.g., v2.4.0, latest)
digestManifest digest (e.g., sha256:abc123...)
sizeCompressed image size in bytes
updatedAtWhen the tag was last updated

BRIDGEPORT uses a digest-based comparison system to detect updates accurately, even for rolling tags like latest.

Tags are grouped into “families” based on their suffix:

  • v2.3.1 and v2.4.0 are in the same bare-version family
  • 2.9.0-alpine and 2.10.0-alpine are in the -alpine family
  • latest and stable are each in their own family

Only tags in the same family as the current tag are compared. If a newer tag exists with a different digest, an update is reported.

For rolling tags where the tag name never changes, BRIDGEPORT compares the manifest digest from the registry against the deployedDigest recorded after the last deployment. If the digests differ, the image was updated.

flowchart TD
    A[Fetch tags from registry] --> B{Tag name changed?}
    B -->|Yes: v2.3.1 vs v2.4.0| C[Compare digests if available]
    B -->|No: latest vs latest| D{Registry returned digest?}

    C --> E{Digests differ?}
    E -->|Yes| F[Update available]
    E -->|No| G[No update]

    D -->|Yes| H{Compare with deployedDigest}
    D -->|No| I[Cannot determine -- no false positive]

    H -->|Differ| F
    H -->|Same| G

    F --> J{Companion tag?}
    J -->|Digest matches another tag| K["Display: 20260225-a1b2c3d<br/>(instead of 'latest')"]
    J -->|No match| L["Display: latest"]
ScenarioDetection Method
New version tag (e.g., v2.3.1 to v2.4.0)Tag name + digest comparison
Rolling tag with digest (e.g., latest)Digest comparison against deployedDigest
Rolling tag without digestNo detection (avoids false positives)
Same tag, same digestNo update
FeatureDigitalOceanDocker HubGeneric V2
Tag listingDO management APIHub API/v2/{repo}/tags/list + manifest HEADs
Digest sourceAPI field (+ V2 fallback)API fieldDocker-Content-Digest header
Real timestampsYesYesNo (set to current time)
Image sizesYesYesNo (always 0)
Auth methodBearer tokenToken exchange / BasicBasic auth

FieldTypeDefaultDescription
namestringDisplay name (unique per environment)
typeenumdigitalocean, dockerhub, or generic
registryUrlstringRegistry API endpoint
repositoryPrefixstringnullPrefix for narrowing repository listing
tokenstringnullAPI token (encrypted at rest)
usernamestringnullUsername for basic auth
passwordstringnullPassword for basic auth (encrypted at rest)
isDefaultbooleanfalseDefault registry for the environment
refreshIntervalMinutesinteger30How often to check for updates (5-1440)
autoLinkPatternstringnullPattern for auto-linking discovered images
SettingLocationDefaultDescription
SCHEDULER_UPDATE_CHECK_INTERVALEnv var1800sGlobal scheduler interval for registry checks
registryMaxTagsAdmin > System50Max tags to fetch per repo (Generic registries)

“Connection test failed” Verify the registry URL, credentials, and that the BRIDGEPORT server can reach the registry. For Generic registries, ensure the URL includes the scheme (e.g., https://registry.example.com). The test calls the /v2/ endpoint.

“Registry API error: 401” Credentials are invalid or expired. For Docker Hub, ensure your access token has not expired. For GHCR, ensure the personal access token has the read:packages scope.

“Registry API error: 403” The credentials are valid but lack permissions. For DO registries, the API token needs registry read access. For GHCR, the token needs the read:packages scope for the target repository.

“Cannot delete registry connection with N container image(s) attached” Container images must be unlinked or deleted before the registry can be removed. Edit each container image and either set registryConnectionId to null or delete the image.

Tags show “0 bytes” and no real timestamps This is normal for Generic V2 registries. The Docker Registry V2 API does not provide size or timestamp information in tag listings. BRIDGEPORT fetches digests via manifest HEAD requests but cannot retrieve sizes or timestamps.

Update check finds updates but they are false positives This can happen if the deployed digest was not recorded (e.g., the service was deployed before the digest tracking feature was added). Deploy the current tag once to store the digest, which will clear the false positive.

“No registry connection configured for this image” The container image has no registryConnectionId. Edit the container image and select a registry connection.