hammerkit
Service

Service

A service is a long-running process, such as a database, that a task needs in order to do its work.

Services help tasks do their work — for example, a database for your application or an API for your integration tests.

Services can run in a container or be forwarded from a Kubernetes cluster. Each service a task needs is reachable on the container network by the service's name.

Local tasks can also use needs, but hammerkit does not provide DNS resolution for them. Instead, the connection details of each needed service are passed to the task as environment variables (see environment hints).

Container

Like container tasks, container services need an image to run. Tasks declare which services they need, and hammerkit ensures those services are running before the task executes.

Use healthchecks to ensure that a service is running and ready to be used.

services:
  postgres:
    image: postgres
    envs:
      POSTGRES_USER: api
      POSTGRES_DB: api
      POSTGRES_PASSWORD: 123456
    healthcheck:
      cmd: "pg_isready -U api"
    ports:
      - 5432

tasks:
  api:
    image: node:alpine
    needs: [postgres]
    cmds:
      - node index.js

Kubernetes

Kubernetes services let tasks use resources from local and remote Kubernetes clusters. This makes it easy to integrate with resources from development or staging environments, and to debug or troubleshoot your application with data from other environments.

services:
  postgres-staging:
    context: staging
    ports:
      - 5432:5432
    selector:
      type: deployment
      name: postgres

tasks:
  api-staging:
    image: node:alpine
    needs: [postgres-staging]
    cmds:
      - node index.js

Connecting from a container task

A container task shares a network with its needed services and reaches each one by its service name as the hostname, on the service's container port. You don't publish a port for this — ports are only needed to reach a service from your host.

For the postgres service above (exposing 5432), a container task connects with a URL like postgres://api@postgres:5432/api — postgres is the service name and 5432 the container port. Keep that string in a shared top-level envs block so the service and the task agree on it:

.hammerkit.yaml
envs:
  DATABASE_URL: postgres://api@postgres:5432/api

services:
  postgres:
    image: postgres:16-alpine
    envs:
      POSTGRES_USER: api
      POSTGRES_DB: api
      POSTGRES_HOST_AUTH_METHOD: trust
    healthcheck:
      cmd: "pg_isready -U api"
    ports:
      - 5432

tasks:
  migrate:
    image: node:24-alpine
    needs: [postgres]
    envs:
      DATABASE_URL: $DATABASE_URL
    cmds:
      - node migrate.js

Environment hints for local tasks

A local task (a task without an image) is not part of that container network, so hammerkit instead injects the connection details as environment variables.

For every needed service the following variables are available, where NAME is the uppercased service name:

  • HAMMERKIT_<NAME>_HOST - host the service is reachable on.
  • HAMMERKIT_<NAME>_PORT - the primary published port.
  • HAMMERKIT_<NAME>_PORT_<containerPort> - the published port for a specific container port. The suffix is always the numeric container port (ports cannot be named), so this is mainly useful for services that expose more than one port.

For a service named postgres exposing port 5432 a local task receives HAMMERKIT_POSTGRES_HOST, HAMMERKIT_POSTGRES_PORT and HAMMERKIT_POSTGRES_PORT_5432.

Service dependencies

Like tasks, services can declare deps and needs. Use deps when a service requires a task to run first (for example building an image input), and needs when a service depends on another service.

services:
  api:
    image: node:alpine
    deps: [install]
    needs: [postgres]
    cmd: node index.js

  postgres:
    image: postgres:16-alpine
    ports: [5432]

tasks:
  install:
    image: node:alpine
    cmds:
      - npm ci

Starting and stopping services

Services start and stop automatically based on the needs of the tasks you run. They can also be controlled directly with the CLI:

  • hammerkit up starts the services.
  • hammerkit down stops the services.

This is useful to keep shared services such as a database running across multiple task runs.

A service's container is recreated when it starts, so data written inside it is lost on the next start unless you attach a volume. Declare a volume to persist a database's data — or to seed/back it up with store / restore.

On this page