Deploy your first app
What the platform enforces
PivoCloud builds the Dockerfile in your repository, reads the firstEXPOSE
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:
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 headedPlatform 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
OnMy 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 directoryis 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 pathis 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.
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:
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 withapp-,
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
TheAdvanced 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.
Deploymentscarries the build log. Watch it here on the first deploy: this is where a failing build tells you why.Domainscarries the address your app answers on, with its certificate state, and is where you change the subdomain before the first deploy.Environmentis 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.Overviewcarries the app’s status and which repository it came from.Billingcarries what this app costs and what it has cost.
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 checkRoot 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.