Deploy from Git

Last updated

Push your source and the platform builds and runs it. The first push creates the application; later pushes update it.

Requirements

  • A Dockerfile at the root of what you push. Not Dockerfile.prod, not docker/Dockerfile — that exact name, at the top level. If it's missing, the push is rejected with a message saying so, before any build starts.
  • Your repository's history. Shallow clones are rejected — see CI notes below.

Two branches, and the second one is the useful one

The push URL is shown in the panel (Add app → Advanced → Git Push) with credentials embedded in it. The branch you push to determines what happens:

Push to What happens
deploy Build the image and apply it — your container is replaced
build Build the image only — your running app is untouched
anything else Nothing, with a message explaining why
git push <push-url> HEAD:build     # does it build?
git push <push-url> HEAD:deploy    # ship it

HEAD:deploy pushes your current local branch to the remote deploy branch, whatever your branch is called locally.

Use build while you're iterating. Deploying replaces the container, which means a brief interruption, dropped connections and cleared in-memory state — none of which you want while you're finding out whether a Dockerfile line is correct.

Build output comes back over git

The build streams its output to your terminal as the push completes, so a failure is visible where you already are. If a build fails, that output is the first place to look; the app's logs cover the running container.

What the build does and doesn't get

  • No environment variables and no build arguments. An ARG without a default resolves to empty, and anything a framework inlines at build time won't have your values. See Configuration.
  • Limited memory and CPU — less than your app gets at runtime. A heavy asset build or compile can exceed it, usually failing part-way through with no clear error. Build in CI and push an image if that happens.
  • The image is built for linux/amd64.

One push at a time

Pushes are processed one at a time per application, so two landing together will race and one will fail. In CI, use a concurrency group.

From CI

Store the push URL as a secret — it contains credentials that allow pushing code to your app, so treat it like a password.

The one thing that catches everyone: checkout actions usually default to a shallow clone, and a shallow push is rejected with shallow update not allowed. Set the full history (fetch-depth: 0 in GitHub Actions).

Push-only

The repository is a deploy target, not a code host. You cannot clone or fetch from it — keep your code in GitHub, GitLab, or your own Gitea, and push here to ship.

Troubleshooting

Symptom Cause
"You have just pushed to not tracked branch" Push to deploy or build
"No Dockerfile found in the root of the pushed branch" It's in a subfolder, or named something else
shallow update not allowed Shallow clone in CI — fetch full history
Build stops part-way with no error Out of memory — build in CI instead
Deploy succeeds, URL doesn't respond App is listening on 127.0.0.1 — bind 0.0.0.0