Deploy a Container Image
Run any Docker image as an app — from your Cosmoner registry, Docker Hub or the GitHub container registry — and redeploy it from CI when you push a new tag.
Overview
If you already build images, you can run one directly instead of having Cosmoner build from your repository. Any language, any base image, any build system: if it runs in a container and answers HTTP, it runs as an app.
An image app can pull from:
- Your project registries — a Cosmoner container registry in the same project. No credentials needed, and pushes can redeploy the app automatically.
- Docker Hub.
- GitHub container registry (
ghcr.io).
Images from other registries cannot be deployed yet.
1. Push your image
For a Cosmoner registry, the repository page in the control panel shows the
exact docker login, docker tag and docker push commands for it. For Docker
Hub and the GitHub container registry, push as you normally would.
Build the image for linux/amd64. On an Apple Silicon Mac, that means
docker build --platform linux/amd64 … — an arm64 image will not start.
2. Create the app
In your project, go to Apps → New app, choose a domain, then select the Container Image tab.
- From a project registry, pick it under Your registries, then the image and the Tag.
- From Docker Hub or the GitHub container registry, choose it under Container registry and pick the image, or select Enter an image manually and type its name. For a public image, leave the credentials empty. For a private one, either connect the account, or enter a Username and a read-only Personal access token — not your account password.
Ports
Set Internal container port to the port your container listens on. That is
where traffic is sent, and the container is also given it in the PORT
environment variable. Both port fields default to 80, which suits images
built on a web server such as nginx; an app server listening on 3000 or
8000 needs it changed.
Environment variables
Add, link and import variables the same way as for a git app — see Environment variables. They are set on the running container; nothing is rebuilt.
Then Continue, choose a plan and the number of instances, and Launch.
Deploying new versions
On push, from a project registry
An app running an image from your own registry can redeploy itself when you push. Under Deploy on push:
| Setting | What a push does |
|---|---|
| Same tag | Redeploys when the tag the app runs is pushed again — e.g. you always push :latest or :production. |
| Newest image | Deploys every push to the repository and switches the app to its tag — e.g. you tag each build with its commit SHA. |
| Off | Nothing. You deploy from the API, the CLI or CI. |
Change it later on the app's General tab, under Deploys.
From CI, with the CLI
The cosmoner CLI deploys a tag and waits until it is live,
which makes it a natural last step of a pipeline:
npx @cosmoner/cli deploy web --tag "$GIT_SHA"It exits non-zero if the rollout fails, so the pipeline fails with it. Give it
an API key with apps:read and apps:write in
COSMONER_API_KEY. --digest deploys one exact image instead of a tag, and
with neither, the app's current tag is pulled again.
The CLI deploys images from Cosmoner registries. For Docker Hub and the GitHub container registry, redeploy through the Apps API.
Going back to an earlier version
Select Roll back on an earlier deployment in the Deployments section of the app's Overview tab. The app goes back to the exact image that deployment ran, pinned to its digest, so pushes to its tag no longer move it until you deploy a tag again. Rolling back needs the image to still be in the repository — deleting it from the registry removes that option.
From CI, deploying an earlier tag or digest does the same. Tagging images with
something that identifies the build, such as the commit SHA, rather than only
latest, keeps every version addressable.
Troubleshooting
The deploy never becomes healthy. Check Runtime logs. The usual cause is
a port mismatch: Internal container port must be the port the process
listens on. Also check the process listens on 0.0.0.0, not 127.0.0.1 —
a server bound to localhost cannot be reached from outside its container.
exec format error in the logs. The image was built for another CPU
architecture. Rebuild it with --platform linux/amd64.
The image cannot be read. For a private image, check the token has read access to that repository, and that the name and tag are spelled exactly as in the registry.
Deploy a Next.js App
Run a Next.js app on Cosmoner from your repository — server rendering, API routes and NEXT_PUBLIC_ variables included — or ship it as a static export.
Passkeys
Sign in with Touch ID, Face ID, Windows Hello, or a security key — no password and no code, and nothing a phishing site can capture.