pier_

Deploy an app

Build a container from a Dockerfile, run it in its own microVM, and reach it over HTTPS

Goal. A repository with a Dockerfile becomes a running app with a public HTTPS hostname. The example is acme's api: a Go HTTP server in api/, listening on 8080. For an image that already exists (no build), see Variations.

Declare the app

pier.yaml
version: 1
name: acme
project: acme-ad19
environments:
  prod:
    apps:
      - name: api
        build_context: ./api      # ./api/Dockerfile
        targets:
          - name: primary
            plan: app-s

build_context is the directory docker build runs in, relative to pier.yaml; the Dockerfile is read from there (dockerfile: on the target overrides the path). plan is the target's size (Plans). project: is the slug the platform generated when the project was created; pier config init --name acme writes it.

Deploy

pier deploy
output
→  Comparing prod environment against platform state...

  Changes:
    + create environment "prod" (new environment)
    + create app "api" in prod (plan: app-s, replicas: 1)
    + create postgres "main" in prod (plan: pg-s, version: 17, replicas: 1)
    + create bucket "uploads" in prod (access: private)
    + create site "www" in prod

  Deploy:
    app "api"    build (first deploy)
    site "www"    build required (new resource — initial build required)
    postgres "main"    deploy (deployed inline)
    bucket "uploads"    deploy (deployed inline)

OK  Applied 5 config change(s) to prod
→  Building api from ./api
→  Building pier-build/api:latest...

→  Pushing registry.pier.run/01a05313-e4fa-7707-a014-05f1ae901cec/api:9eed0df...
9eed0df: digest: sha256:13e134f00256cce6b3bc076b2671fb63dca2eee0bfb14509576612703a39c662 size: 855
OK  Pushed registry.pier.run/01a05313-e4fa-7707-a014-05f1ae901cec/api:9eed0df
→  Deploying api...
→  Found 1 site files to deploy
→  Uploading 1 files...
OK  All files uploaded
→  Waiting for infrastructure provisioning...
OK  Infrastructure ready

OK  Summary: 1 built, 4 deployed

deploy first converges the whole environment's declaration; the create … lines are the pier apply step that deploy implies, so acme's Postgres, bucket and site are provisioned in the same run. It then builds the image with the local docker, pushes it to the project's registry with the credentials pier login installed, and rolls the target. A new app reaches running when its first instance passes its readiness check.

Reach it

pier info api
output
Name         api
ID           app_01m19h7sdyef8v937vjvbjw7hj
Environment  prod
Target       primary
Deployment   depl_01m19h7sefeemtmtcc334e1wax
Status       running
Replicas     1
Image        registry.pier.run/01a05313-e4fa-7707-a014-05f1ae901cec/api:9eed0df
Port         8080
URL          https://9z2vay2eae6.app.pier.run
CPU          500m
Memory       512Mi
Created      2026-08-30 22:30:08
Updated      2026-08-30 22:30:08

                                         
 INSTANCE PHASE   READY RESTARTS STARTED 
                                         
 j675p    Running yes   0        42s ago 
                                         
curl -sS https://s9vmcq9byrx.app.pier.run/
curl -sS https://s9vmcq9byrx.app.pier.run/json
output
hello from app-01a05313-e5c2-70df-acd5-6de1595d13b8-666765455b-j675p
{"host":"app-01a05313-e5c2-70df-acd5-6de1595d13b8-666765455b-j675p","status":"ok","version":"1.0.0"}

The hostname is keyed by a random id, not by the app's name, so renaming api later does not change it. A custom domain attaches your own name.

Watch it

pier logs api --tail 5
output
  api · the last hour
2026-08-30 22:31:46.362  INFO     [t5dk7]  2026/08/30 14:31:46 [tick 8] hello-web running on app-01a05313-e5c2-70df-acd5-6de1595d13b8-58946dd54b-t5dk7
2026-08-30 22:31:51.366  INFO     [t5dk7]  2026/08/30 14:31:51 [tick 9] hello-web running on app-01a05313-e5c2-70df-acd5-6de1595d13b8-58946dd54b-t5dk7
2026-08-30 22:31:56.366  INFO     [t5dk7]  2026/08/30 14:31:56 [tick 10] hello-web running on app-01a05313-e5c2-70df-acd5-6de1595d13b8-58946dd54b-t5dk7
2026-08-30 22:32:01.370  INFO     [t5dk7]  2026/08/30 14:32:01 [tick 11] hello-web running on app-01a05313-e5c2-70df-acd5-6de1595d13b8-58946dd54b-t5dk7
2026-08-30 22:32:06.374  INFO     [t5dk7]  2026/08/30 14:32:06 [tick 12] hello-web running on app-01a05313-e5c2-70df-acd5-6de1595d13b8-58946dd54b-t5dk7

pier logs api --follow streams; pier monitor api shows CPU, memory and requests; pier events lists what the platform did.

What changed

The declaration above is the whole change. pier deploy recorded a deploy for api (pier deploys ls api) with the digest of the image it built; a rollback returns to that record.

Variations

  • A pre-built image, no build: set image: and port: on the target instead of a build_context. pier deploy pulls the image and does not run docker.

    pier.yaml
        apps:
          - name: whoami
            targets:
              - name: primary
                image: traefik/whoami:v1.10.1
                port: 80
                plan: app-s
  • No Dockerfile: Pier detects Node, Python, Go, Rust, Ruby, PHP, Java, .NET, Elixir and Deno projects and builds them without one. Add a Dockerfile to control the build.

  • From the CLI instead of the file: pier add app --name api --plan app-s declares the same thing and writes it to pier.yaml; --stage writes without applying.

  • Build on the platform on each push: Deploy from GitHub.

See also

Apps · pier deploy · pier info · Concepts: target

On this page