# Deploy a Docker image or Dockerfile

> Run a prebuilt Docker image or build your repository's Dockerfile with Falak, with blue/green container swaps, health checks and automatic HTTPS in front.

Source: https://falak.sh/docs/deploy/docker-image/

The **Docker** runtime runs one container per server behind Caddy. The image comes either from a registry (Docker Hub, GHCR, …) or from your repository's `Dockerfile`, built by Falak. Deployments swap containers blue/green, so the old container keeps serving until the new one passes its health check.

For multi-container apps, use [Docker Compose](/docs/deploy/docker-compose/) instead.

## Prerequisites

- A server of type **app**, **web** or **worker** with **Docker** installed. Tick **Install Docker Engine (with Compose and Buildx)** when you create the server.
- Your container listens on the port in the **`PORT`** environment variable.
- To build a `Dockerfile`: a **builder server** (type `builder`, with Docker). The builder on the control plane host only does native builds by default. See [Builders](/docs/operations/builders/).

## Deploy

  
    

    1. On the canvas: **+ Create → Docker image**.
    2. Enter the image reference, for example `ghcr.io/acme/api:1.4.2`.
    3. Pick servers and a domain, then **Deploy**.

    

    There is no build step. Each deployment pulls the image (if it is missing on the server) and swaps containers. To ship a new version, change the image tag under **Settings → Build → Image** and redeploy.
  
  
    

    1. **+ Create → Git repository** and pick the repository.
    2. Choose the **Docker** preset. The runtime is **Docker** and the build mode **Docker image**.
    3. Optional: set **Settings → Build → Dockerfile** if it is not `./Dockerfile`.
    4. Pick servers and a domain, then **Deploy**.

    

    The builder builds the image with BuildKit and pushes it to Falak's registry as `<registry>/<namespace>/<site-slug>:<build-id>`. Without a Dockerfile, the builder uses a Railpack plan (when available) or generates a Dockerfile for the detected stack and prints it in the build log.
  

## How it runs

| Aspect | Value |
|---|---|
| Container port | The site's **app port** (allocated from 3000–3999 per server). Falak sets `PORT` to it and maps it. |
| Environment | Site variables (references resolved) + `PORT` + `FALAK_SITE_ID`, `FALAK_SERVER_ID`, `FALAK_DEPLOYMENT_ID`, `FALAK_RELEASE_ID` |
| Labels | `falak.site.id`, `falak.deployment.id`, `falak.release.id` |
| Pull policy | Pull when missing |
| Strategy | **Blue / green** (default), rolling or canary |
| Health check | `GET /` expecting `200`, checked on the new container before it takes traffic |

### Blue/green swap

```text title="What deploy.container.swap does"
old container on port 3004 (blue) keeps serving
new container starts on port 4004 (green = app port + 1000)
health check against the new container
Caddy upstream switches to the new container
old container stops
```

The app port must leave room for the green port (app port + 1000 ≤ 65535).

## Registries

- Images built by Falak are pulled from Falak's registry with credentials Falak provides.
- Public images need nothing.
- **Private third-party registries:** Falak only passes credentials for its own registry. Log in on each server as the user running Docker (for example `docker login ghcr.io` as root) before deploying. *This path is not covered by Falak's automated tests.*

## Limits

- Docker runtimes and Docker builds on a real BuildKit are covered by unit and feature tests, not yet by the end-to-end suite.
- Falak deletes its own registry's old images and garbage-collects it weekly; see [The built-in image registry](/docs/operations/install/#the-built-in-image-registry).
- The Laravel Dockerfile Falak generates builds front-end assets before `composer install`; projects that import CSS from `vendor/` need their own Dockerfile.
- Workers, daemons and cron from the **Processes** tab are not run for container sites; run them in the container or use Compose.

## Next steps
