Deploy by pushing a Docker image
Last updated
Build the image yourself and push it to the account's registry. Useful when you already build in CI, or when your build is too heavy for the platform's builder.
Push it
The panel shows a registry URL and generated per-repository credentials:
docker login -u USERNAME -p PASSWORD REGISTRY_URL
docker build -t REGISTRY_URL/REPO:TAG .
docker push REGISTRY_URL/REPO:TAG
Then create the app from the pushed image.
Treat the registry credentials as secrets — in CI, store them as repository secrets rather than putting them in a workflow file.
Images must be linux/amd64
This is the one that catches people, and it fails quietly.
Docker builds for the architecture of the machine doing the building. On an Apple Silicon Mac that's arm64, and the platform runs amd64. An arm64-only image uploads successfully — the blobs transfer fine — but it isn't usable, so the tag may not appear where you expect and auto-deploy skips it without an error.
The symptom set is: a push that "worked", a tag you can't find, and an app that never updates.
Build for the right platform explicitly:
docker buildx build --platform linux/amd64 -t REGISTRY_URL/REPO:TAG --push .
Push directly from the build (--push) rather than building then pushing separately — a cross-platform build doesn't land in your local image store the way you'd expect.
Emulated builds are slow for anything that compiles. Two ways to avoid thinking about it at all:
- Build in CI — runners are amd64, so it's correct by default and native rather than emulated.
- Build multi-platform:
--platform linux/amd64,linux/arm64gives you an image that runs natively on your Mac and deploys here.
Pulling official public images is unaffected — those publish manifest lists and the right variant is selected. The problem is specific to images you build on arm64 hardware.
Auto-deploy on push
Opt-in, from an existing app's Deployment tab rather than the create flow. Enabling it appends a suffix to the tag you push; pushing a tag with that suffix applies the image to bound apps and restarts them.
Until you enable it, pushing an image doesn't change a running app — you apply it explicitly.
Tags
Use immutable tags — a version, a commit SHA, a date — rather than overwriting latest. It makes "which version is running" answerable, and makes rolling back a matter of pointing at a previous tag.
Related
- Deploy from Git — if you'd rather the platform built it
- Private registry — where credentials belong