Use the container registry directly
docker login · push · pull against the platform's built-in OCI registry, HTTP registry settings, tenant isolation and the shared namespace
Required permission: View
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
- Go to the avatar at the top right → Account settings (계정 설정) → Container tokens (컨테이너 토큰). Every member can issue one.
- Set a name and the expiry in days, then press Issue (발급). ① The token is shown only this once, ② together with a
docker logincommand 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 |
| Tenant | The 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 alwayshost[: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 dockerpodman login --tls-verify=false mlops.example.com:10000 -u demo
podman push --tls-verify=false mlops.example.com:10000/demo/example/mnist-trainer:v1Configure this on the nodes where training and serving pods pull images. /etc/rancher/k3s/registries.yaml:
mirrors:
"mlops.example.com:10000":
endpoint: ["http://mlops.example.com:10000"]
configs:
"mlops.example.com:10000":
tls:
insecure_skip_verify: trueAfter saving, restart k3s (sudo systemctl restart k3s; on agent nodes, k3s-agent).
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 token | Platform token (system administrator) | |
|---|---|---|
mlops/… pull | Only tags shared with the tenant. Tags and repositories not shared return not found | All |
mlops/… push | Rejected (shared namespace is read-only for tenant tokens) | Allowed |
| Own tenant space | Allowed | None |
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
| Symptom | Cause and fix |
|---|---|
http: server gave HTTP response to HTTPS client | An HTTP registry, but the client tried HTTPS. Apply the insecure setting above |
unauthorized / 401 | The token is wrong, expired or revoked. Issue a new one |
push fails with 403 insufficient permission | The token's issuer has less than DEVELOPER in that tenant |
pull returns not found | Another tenant's image, an mlops/ tag not shared with you, or it really does not exist |
| A layer push is cut off midway | The body size or time limit of a front proxy. Tell the operator, or hand it over as a file and import it on screen |