The platform embeds an OCI container registry (Docker Registry HTTP API V2) inside the app. It is open at /v2 on the same address as the app, so docker · containerd · podman push and pull without a separate registry server. Training runtime images, serving images and imported partner images all live here.

Issue a token

  1. Go to the avatar at the top right → Account settings (계정 설정)Container tokens (컨테이너 토큰). Every member can issue one.
  2. Set a name and the expiry in days, then press Issue (발급). ① The token is shown only this once, ② together with a docker login command filled in with this server's host and user name.
    Right after issuing a container token — ① the secret is shown only now ② a ready docker login command
Rule
pull (GET · HEAD)The issuer has VIEW or higher in that tenant
push (every other request)The issuer has DEVELOPER or higher in that tenant
TenantThe tenant at issue time is fixed in the token. The X-Tenant header is not used

Permissions are checked again on every request. A VIEWER can also get a token, but that token can only pull. If the issuer's role changes later, the change applies immediately to tokens already issued.

You can also issue one through the API.

curl -sS -X POST "$API/api/v1/registry/tokens" \
  -H "Authorization: Bearer $JWT" -H "X-Tenant: DEMO" \
  -H 'Content-Type: application/json' -d '{"name": "ci-push", "expires_in_days": 7}'
# -> {"id": "…", "token": "<secret>", "tenant": "DEMO", "username": "demo", "registry_host": "mlops.example.com"}

Login · push · pull

echo "<issued token>" | docker login mlops.example.com -u demo --password-stdin

docker tag example/mnist-trainer:v1 mlops.example.com/demo/example/mnist-trainer:v1
docker push mlops.example.com/demo/example/mnist-trainer:v1
docker pull mlops.example.com/demo/example/mnist-trainer:v1
  • Any user name works. The token is the password. For readability, the tenant code (lower case) is recommended.
  • Do not put a scheme such as http:// in an image address. It is always host[:port]/path:tag.
  • Storage is completely separated per tenant. The first path segment is just a name; whatever name you push under, the image goes into the token's tenant space. By convention, putting the tenant code in the first segment (demo/…) gives the same shape as images imported on screen.
  • Another tenant's images look as if they do not exist (not found). The registry deliberately answers 404 so that "exists but no permission" cannot be told apart from "does not exist".

You can see listings with the standard API.

curl -u "demo:<token>" https://mlops.example.com/v2/_catalog
curl -u "demo:<token>" https://mlops.example.com/v2/demo/example/mnist-trainer/tags/list
# {"name":"demo/example/mnist-trainer","tags":["v1"]}

A registry open over HTTP (insecure registry)

If the registry is behind HTTPS, there is nothing to configure. If the platform is open only over HTTP, you must configure the client side to allow HTTP. Docker allows localhost as an exception, so it works without configuration.

Add the host to /etc/docker/daemon.json and restart Docker.

{ "insecure-registries": ["mlops.example.com:10000"] }
sudo systemctl restart docker

Node-side settings are usually made by the operator at installation — see Installation.

The shared namespace mlops

Repositories whose path starts with mlops/ are in a reserved shared namespace. A system administrator uses it to build training runtime · dataset stager · serving builder images once and hand them out to several tenants.

Tenant tokenPlatform token (system administrator)
mlops/… pullOnly tags shared with the tenant. Tags and repositories not shared return not foundAll
mlops/… pushRejected (shared namespace is read-only for tenant tokens)Allowed
Own tenant spaceAllowedNone

So sharing is per tag. Even within the same mlops/training-runtime repository, tenant A may get only the yolo-cuda tag and tenant B only the rfdetr-cpu tag. The system administrator decides who gets which shared images — see the Administration guide.

You cannot put images into mlops/ by import (tar upload). An import always goes into your own tenant space.

Troubleshooting

SymptomCause and fix
http: server gave HTTP response to HTTPS clientAn HTTP registry, but the client tried HTTPS. Apply the insecure setting above
unauthorized / 401The token is wrong, expired or revoked. Issue a new one
push fails with 403 insufficient permissionThe token's issuer has less than DEVELOPER in that tenant
pull returns not foundAnother tenant's image, an mlops/ tag not shared with you, or it really does not exist
A layer push is cut off midwayThe body size or time limit of a front proxy. Tell the operator, or hand it over as a file and import it on screen

Written for the platform as of 2026-09-21.

© Geo-MLOps