---
url: /guide/deploying-apps.md
description: Deploy and update an application with DockIY.
---

# Deploying applications

Run these commands from an application Git repository. DockIY reads
`dockiy.yml` from the repository root.

## 1. Configure the application

`dockiy app init` creates a project with a deployment manifest. For an
application with staging and production environments, the important parts look
like this:

```yaml
name: my-app

environments:
  staging:
    host: staging.example.com
    compose_file: docker-compose.yml
  production:
    host: example.com
    compose_file: docker-compose.yml

hooks:
  build: scripts/build.sh
  start: scripts/start.sh
  healthcheck: scripts/healthcheck.sh
```

For a single environment, use `default` instead:

```yaml
environments:
  default:
    host: example.com
    compose_file: docker-compose.yml
```

The `build` and `start` hooks are required. `healthcheck` is optional. Add a
`pre_start` hook for database migrations and `rollback_pre_start` when a
rollback needs its own migration step.

Add `secrets_file` under an environment when it uses a SOPS-encrypted file.

If the application builds more than one image, list them in `dockiy.yml`:

```yaml
images:
  - app
  - migrate
```

Use the resulting `DOCKIY_<NAME>_IMAGE` variables in your Compose file or
hooks. The [templates](/templates/react) show complete working examples.

Each application service must join the external `reverse_proxy` network and
have its Traefik labels. It does not need to publish a host port.

## 2. Deploy

Commit and push the application before deploying it.

For one `default` environment:

```bash
dockiy app deploy --version v0.1.0
```

For staging and production:

```bash
dockiy app deploy staging
dockiy app deploy production --version v0.1.0
```

The first versioned deployment asks you to confirm `v0.1.0`. Later production
or default releases can use an exact version or `patch`, `minor`, or `major` (`dockiy app deploy production --version patch`).
Staging creates its version from the deployment time and Git commit, so it does
not use `--version`.

DockIY builds the application on your computer, sends the image to the private
server registry, uploads the Compose files and hooks, and starts the new
release. SOPS decrypts secrets on your computer; private identity keys are never
sent to the server.

::: tip Git checks

Deploy committed changes from the tip of a branch. Use `--allow-dirty` only for
a staging deployment with uncommitted changes, or `--allow-non-tip` when you
intentionally deploy an older commit that is already on `origin`.

:::

### Optional deployment confirmation

To require Yes/No approval before deploying production, add this to your global
config or the application's local `dockiy.config.yml`:

```yaml
confirm_deployments: [production]
```

Use any combination of `default`, `staging`, and `production`.

### What does the CLI actually do?

1. Fetch `origin`, validate the worktree and release, and ask permission if the branch needs pushing.
2. Push an unpublished commit on the primary branch, if needed.
3. Build a new Docker image from the corresponding script and upload it to the VPS registry.
4. Upload `docker-compose.yml`, decrypted secrets, and other runtime files to the VPS.
5. Run the start script on the VPS (essentially `docker compose up -d`, pulling the image from the local registry on the same VPS).
6. Create and push the release Git tag after the application starts.

## 3. Check the deployment

```bash
dockiy app list
dockiy app status my-app production
```

Use `default` or `staging` instead of `production` when needed. The status
command shows the deployed release, images, and running containers.

If a deployment is interrupted, check its status first. Repeat the same deploy
command when the application is already running but Git tagging or server
recording did not finish. Use `--retry-incomplete` only when you want to run
interrupted hooks again.

## 4. Roll back

Roll back to an exact release tag:

```bash
dockiy app rollback production --to prod/v1.0.0
dockiy app rollback --to v1.0.0
```

Use the first command for production and the second for a `default`
environment. Staging releases use tags in the form
`staging/<timestamp>-<commit>`.

Rollback restores the previous application files and images, then runs the
rollback and healthcheck hooks. It does not restore database data or undo a
database migration; the application must handle that separately.

## 5. Clean old releases

Preview cleanup for one application environment, then run it:

```bash
dockiy releases clean production --keep 2 --dry-run
dockiy releases clean production --keep 2
```

The current release is always kept. Cleanup removes older release directories,
unused Docker images on the VPS, and their registry tags. It keeps images still
referenced by a retained release or a container. When it deletes a registry
manifest, DockIY briefly stops the registry, runs garbage collection to reclaim
unreferenced storage, and restarts it. Run `dockiy server update` before using
image cleanup so the registry allows deletion.

Each app environment has one `releases.json` on the VPS that records releases,
deployment state, and cleanup results, including deleted directories and images.
You can rerun cleanup after an interrupted attempt. See the
[`releases clean` reference](/cli/#dockiy-releases-clean) for `--since` and
`--app` options.

Continue with the [React template](/templates/react), [VitePress
template](/templates/vitepress), [Nuxt template](/templates/nuxt), or [Nuxt
Better Auth template](/templates/nuxt-betterauth).
