Skip to content

Create your own template ​

DockIY templates are ordinary Git repositories with a dockiy.yml, a Docker build, a Compose file, and deployment hooks. Start from one of the existing templates, or create a repository with this minimum structure:

text
.
├── Dockerfile
├── docker-compose.yml
├── dockiy.yml
└── scripts/
    ├── build.sh
    └── start.sh

Define dockiy.yml ​

Put dockiy.yml at the repository root. A single-environment application can use default:

yaml
name: my-app

images:
  - app

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

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

For separate staging and production deployments, define exactly these two environments instead:

yaml
environments:
  staging:
    host: staging.example.com
    compose_file: docker-compose.yml
    secrets_file: .enc.staging.env
  production:
    host: app.example.com
    compose_file: docker-compose.yml
    secrets_file: .enc.production.env

Important rules:

  • name and image names must start with a lowercase letter and contain only lowercase letters, numbers, _, or -.
  • Omit images only when the build produces one image named app.
  • build and start hooks are required. pre_start, rollback_pre_start, and healthcheck are optional.
  • Use either default alone, or staging and production together. Other environment names are not supported.
  • All referenced paths must be clean paths inside the repository. They cannot be absolute paths or use ...
  • secrets_file must point to a tracked SOPS-encrypted file.

See the configuration reference for all manifest fields and .dockiy.template.yml options.

Build the image locally ​

The build hook runs from the repository root on the developer's computer. It must build and tag every image listed in dockiy.yml; DockIY pushes those tags to the server registry after the hook succeeds.

For one image, scripts/build.sh can be:

bash
#!/usr/bin/env bash
set -euo pipefail

docker build \
  --platform "$DOCKIY_PLATFORM" \
  --tag "$DOCKIY_APP_IMAGE" \
  .

For multiple images, build each configured image with its matching variable:

bash
docker build --platform "$DOCKIY_PLATFORM" --tag "$DOCKIY_APP_IMAGE" .
docker build --platform "$DOCKIY_PLATFORM" --target migrate \
  --tag "$DOCKIY_MIGRATE_IMAGE" .

The hook must exit non-zero when a build fails. Do not push images from the hook; the CLI manages the registry tunnel and pushes all configured images.

Create a compatible Compose file ​

DockIY uploads the selected Compose file to the release directory as docker-compose.yml, together with deploy.env. Use the generated image and runtime variables instead of hardcoded release or registry values:

yaml
name: ${DOCKIY_COMPOSE_PROJECT_NAME:?DOCKIY_COMPOSE_PROJECT_NAME is required}

services:
  app:
    image: ${DOCKIY_APP_IMAGE:?DOCKIY_APP_IMAGE is required}
    environment:
      APP_ENV: ${DOCKIY_ENVIRONMENT:?DOCKIY_ENVIRONMENT is required}
    networks:
      - reverse_proxy
    healthcheck:
      test: ["CMD", "wget", "--spider", "--quiet", "http://127.0.0.1:8080/"]
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=reverse_proxy"
      - "traefik.http.routers.${DOCKIY_COMPOSE_PROJECT_NAME}.rule=Host(`${DOCKIY_APP_HOST}`)"
      - "traefik.http.routers.${DOCKIY_COMPOSE_PROJECT_NAME}.entrypoints=websecure"
      - "traefik.http.routers.${DOCKIY_COMPOSE_PROJECT_NAME}.tls=true"
      - "traefik.http.routers.${DOCKIY_COMPOSE_PROJECT_NAME}.service=${DOCKIY_COMPOSE_PROJECT_NAME}"
      - "traefik.http.services.${DOCKIY_COMPOSE_PROJECT_NAME}.loadbalancer.server.port=8080"

networks:
  reverse_proxy:
    name: reverse_proxy
    external: true

The service must listen on the port named in the Traefik service label and join the external reverse_proxy network. Do not publish a host port for the public application; Traefik provides the HTTPS entrypoint. Add a container healthcheck when the start hook uses docker compose --wait.

Values from a SOPS file are available to Compose through deploy.env, but Compose variables are not automatically passed into a container. Map every runtime value explicitly under environment or secrets.

Write the deployment hooks ​

Hooks are executable files with a shebang. Use set -euo pipefail where the script supports it, and make remote hooks safe to run again after a lost SSH connection.

Start hook ​

start is required and runs remotely after the release files are installed. It should start the application and wait for the services to become ready:

bash
#!/usr/bin/env bash
set -euo pipefail

docker compose --env-file deploy.env up \
  --detach \
  --remove-orphans \
  --pull always \
  --wait \
  app

The hook runs in a release directory containing docker-compose.yml, deploy.env, and the uploaded hook files.

Optional hooks ​

  • pre_start runs before start during a normal deployment. Use it for transactional database migrations or other prerequisites.
  • rollback_pre_start runs before start during a rollback. The normal pre_start hook does not run during rollback.
  • healthcheck runs after start and must exit non-zero when the deployment is not usable.

For example, a migration pre-start hook can wait for the database and run a one-shot migration service:

bash
#!/usr/bin/env bash
set -euo pipefail

docker compose --env-file deploy.env up --detach --wait db
docker compose --env-file deploy.env run --rm migrate

Use a versioned and retry-safe migration tool. DockIY does not provide exactly-once execution for hooks and does not roll back database changes.

Use DockIY variables ​

The build hook receives these values locally:

VariableMeaning
DOCKIY_PLATFORMTarget Docker platform from the selected server configuration
DOCKIY_<NAME>_IMAGELocal registry reference for each image in images

Image names are uppercased and hyphens become underscores, so an image named worker-api uses DOCKIY_WORKER_API_IMAGE.

The generated deploy.env contains these values for the selected environment:

VariableMeaning
DOCKIY_APP_HOSTHostname from the selected environment
DOCKIY_COMPOSE_PROJECT_NAMECompose project name: name for default, or name-environment
DOCKIY_ENVIRONMENTdefault, staging, or production
DOCKIY_GIT_COMMITGit commit being deployed
DOCKIY_RELEASERelease Git tag
DOCKIY_<NAME>_IMAGEServer registry reference for each configured image

Remote hooks receive DOCKIY_COMPOSE_PROJECT_NAME directly. The other deployment values are in deploy.env; use docker compose --env-file deploy.env when a hook needs them. Secrets from secrets_file are included in the same file. Never add DOCKIY_* values or plaintext secrets to the tracked encrypted files; DockIY supplies its own variables after decrypting them.

Optional encrypted configuration ​

If the template needs secrets, commit encrypted environment files and point to them from each environment's secrets_file:

yaml
environments:
  production:
    host: app.example.com
    compose_file: docker-compose.yml
    secrets_file: .enc.production.env

The CLI decrypts the file on the developer's computer and uploads it as deploy.env. Private identity keys remain on the developer's computer.

For reusable templates, add .dockiy.template.yml to remove maintainer-owned ciphertext and create a fresh SOPS configuration during dockiy app init:

yaml
remove:
  - .enc.production.env
sops:
  config_file: .sops.yaml
  path_regex: '^\.enc\..*\.env$'

Test and deploy ​

Before publishing a template:

  1. Build the image through the real build hook and verify that every configured image is created.
  2. Run the Compose stack locally with a local .env file.
  3. Check that the public service has a healthcheck, joins reverse_proxy, and uses the correct internal port in its Traefik label.
  4. Run dockiy config validate, commit the repository, and deploy a test environment.
bash
dockiy app deploy --version v0.1.0
# or, for a staging/production manifest:
dockiy app deploy staging
dockiy app deploy production --version v0.1.0

Use Deploying applications for status, retries, versioning, and rollback behavior.

Released under the MIT License.