Skip to main content

Deploy your first app

What the platform enforces

PivoCloud builds the Dockerfile in your repository, reads the first EXPOSE line in it, and probes your app on that port. There is no build detection and no framework guessing: the runtime is whatever your base image pins. Three facts follow from that, and between them they account for almost every first deploy that fails. No PORT variable is set for you. PivoCloud does not inject one. Your process has to be listening on the port its own EXPOSE line declares. A Dockerfile with no EXPOSE line is not refused: PivoCloud probes port 8000 instead, and unless your app is listening there the deploy fails with the second message at the bottom of this page. Reading PORT and falling back to that number is the portable way to write it, because other hosts do set the variable:
Bind 0.0.0.0, not localhost. A server bound to 127.0.0.1 inside a container is reachable by nothing outside it. An app serves exactly one HTTP port. A backend plus a frontend is either one image serving both, or two apps built from one repository, each with its own build settings. The other three rules, the Dockerfile itself, your migrations and the ephemeral filesystem, are on what your repository needs with worked examples. Read that page once before you create anything.

The list the form shows you

The create form displays a short checklist headed Platform Requirements above the fields. Two of its three items are out of date, and where it and this page say different things, this page is correct. No environment variable carries the port for you, and the port your app must listen on is the one the first EXPOSE line in your Dockerfile declares. Your Dockerfile does not have to sit at the repository root either. The Root directory and Dockerfile path fields, both documented further down this page, build from wherever it actually lives.

Create the app, field by field

On My Apps with nothing deployed yet, the page shows an empty state and one button, Create New App. It opens the form. The fields below are in the order the form renders them. App Name. The name you and your team see in the console. The helper reads Use lowercase letters, numbers, hyphens, and underscores only and the field suggests my-awesome-app. Pick something you would recognise in a list a year from now. Subdomain. The hostname your app answers on. It has its own section below, because it is the one field with a decision in it. Plan. How much machine your app gets, and what it costs per month. Lite is the entry plan at 1,200 DA per app per month, which is exactly what the starting credit covers for a first month. The list shows each plan next to its monthly price, and once you pick a paid plan the form tells you what creating the app will charge and what your balance becomes. The repository. If GitHub is not connected yet, the form shows a Connect GitHub button and the line You'll be taken to GitHub to authorize the PivoCloud App. You'll return here afterward. Once connected, the picker is labelled Pick a repository, with a Search repositories… field inside it. Which repositories appear there is decided entirely by your App installation: see connecting GitHub. Auto-deploy on push. A toggle, offered on the GitHub App path. Its helper reads Deploys automatically when a push targets the deploy branch. Leave it on unless you want every deploy to be a deliberate act. Advanced. A collapsed section, covered below. It folds itself away as soon as the form can read your repository through the App, so on the recommended path you will not see it at all. Environment variables (optional). Its own collapsed section, offered only when you are creating an app. Anything your app needs at runtime, API keys, database URLs, feature switches, can go in here now or be set afterwards. See environment variables. Deploy branch. Which branch is built. It suggests main, and its helper reads Branch to deploy. Defaults to your repository's default branch. Root directory. The helper: The folder Docker builds from. Leave it blank to build from the repository root. Dockerfile path. The helper: The path to the Dockerfile, relative to the root directory above. Leave it blank to use the default filename. Submit with Create App.

When your Dockerfile is not at the repository root

Two fields cover this, and getting the second one wrong is the most common mistake on the whole form.
  • Root directory is the build context: the only part of your repository Docker can see. Nothing above it exists as far as the build is concerned. Leave it blank and the context is the repository root.
  • Dockerfile path is the file to build, resolved relative to the root directory above, not to the repository root. Leave it blank and the default filename is used.
So an API living in backend/ with a Dockerfile beside it wants Root directory set to backend and Dockerfile path set to Dockerfile. Not backend/Dockerfile, which would resolve to backend/backend/Dockerfile. The form prints the resolved pair back to you as you type, in this shape:
Read that line before you submit. It is the cheapest way to catch the doubled prefix. Two apps can be built from one repository this way, each with its own root directory. The monorepo example is that shape end to end.

Choosing the subdomain

The field starts filled in for you, derived from the app name as you type it. The moment you edit it yourself, that link is cut permanently: the field stops following the name, even if you clear what you typed. The rules are: between 3 and 63 characters, lowercase letters, numbers and hyphens. It cannot start or end with a hyphen, and it cannot start with app-, which is reserved for the addresses PivoCloud generates. A further set of names is reserved as well, and when one of them applies the verdict beside the field names the rule you broke. The console appends your account’s app domain after it, and shows you the full address you are about to get. The two rules a first name most often trips print their own message: Can't start or end with a hyphen. and Subdomains can't start with "app-". That prefix is used for automatic URLs. Leaving it blank is a perfectly good choice. Do that and PivoCloud builds a hostname from the app’s own id, and shows it to you before you submit in the shape app-4f3c1a2b…. You can pick a real name later. As you type, a small verdict appears beside the field. It reads Checking… while the console asks, then one of Available, Taken, Reserved, Invalid or Check unavailable. Treat that verdict as a hint rather than a reservation. It tells you what was true a second ago, not what will be true when you submit: a name can show Available and still be refused if someone else creates it first. Nothing holds a subdomain for you until the app exists. Until the first deploy you can still change it. The console says so where the address is shown: This URL starts working the first time you deploy. You can change it until then without using up a certificate.

Deploying without the GitHub App

The Advanced section is the path for a repository the App connection cannot reach: a repository you do not want to grant the App, or a one-off you would rather not install anything for. It holds three controls: a repository URL, a toggle marked Private repository, and, once that toggle is on, a field for a GitHub token with read access to the repository contents. The section hides itself as soon as the form successfully reads your repository through the App, which is why most people never open it. Prefer the App connection where you can: it is what makes deploying on every push possible, and it means no token of yours has to live here. When the repository was picked through the App, the form does not ask for a token at all. Under Private repository it shows this line instead: Access to this repository goes through your GitHub connection. No token is needed. An app that still holds a token saved from before it moved onto the App connection shows one more line next to a Remove token button: A token saved earlier is still stored but is not used for this app.

Migrations

Nothing runs your migrations. There is no release phase and no automatic migration step, so a schema change is yours to trigger explicitly. The entrypoint pattern that makes it opt-in, so a container restart cannot surprise you, is on what your repository needs.

Watch the build, then reach your app

Creating the app takes you to its page, which is organised as five tabs: Overview, Deployments, Environment, Domains and Billing.
  • Deployments carries the build log. Watch it here on the first deploy: this is where a failing build tells you why.
  • Domains carries the address your app answers on, with its certificate state, and is where you change the subdomain before the first deploy.
  • Environment is where you add or change environment variables. Before the first deploy, saving only stores them: there is no container yet to replace. Saving a change afterwards replaces the running container rather than rebuilding the image, so it is fast. See environment variables.
  • Overview carries the app’s status and which repository it came from.
  • Billing carries what this app costs and what it has cost.
The first deploy starts when you press Deploy on the app page. It does not begin on its own, so add your environment variables first if your app needs them at startup. After that, the button on the app page reads Redeploy and rebuilds from your deploy branch on demand.

If the first deploy fails

Two messages account for most first failures, and both are worth reading literally. The first says the build found nothing to build at the path your two settings resolved to, and then lists the Dockerfiles it did find in your repository. One of the two settings is off. Compare the path in the message against the list underneath it, and check Root directory first. The second message reports that your container started but nothing answered on the port PivoCloud probed. Check your EXPOSE line against the port in your own startup log, then read the container logs. If your Dockerfile has no EXPOSE line at all, PivoCloud probed port 8000, so there is nothing for you to compare and the fix is to declare the line. Both messages, and every other one PivoCloud prints when a deploy does not work, are on why did my deploy fail with what each one really means. The contract your repository has to satisfy, including the whole EXPOSE rule, is on what your repository needs.