Skip to content
Podman

Introduction

The Podman provider stops containers when their session expires, and starts them again when a request needs them. Sablier calls the Docker-compatible API of the Podman API service through the Podman socket. It runs the code of the Docker provider, with the differences listed on this page.

Install Sablier

Enable the Podman socket first. Sablier only sees the containers of the Podman service it connects to:

# Rootful containers: /run/podman/podman.sock
sudo systemctl enable --now podman.socket

# Your rootless containers: $XDG_RUNTIME_DIR/podman/podman.sock
systemctl --user enable --now podman.socket

Socket activation starts the API service when Sablier connects. See rootless mode for the difference between the two sockets.

Then run Sablier in a container, with the socket mounted:

Add Sablier to your Compose file:

  sablier:
    image: docker.io/sablierapp/sablier:1.19.0 # x-release-please-version
    command:
      - start
      - --provider.name=podman
    volumes:
      - ${PODMAN_SOCKET:-/run/podman/podman.sock}:/run/podman/podman.sock
    security_opt:
      - label=disable # lets the container use the socket on SELinux hosts
    ports:
      - "10000:10000"

For rootless Podman, set PODMAN_SOCKET to your user’s socket:

PODMAN_SOCKET=$XDG_RUNTIME_DIR/podman/podman.sock podman compose up -d

Reverse proxy plugins in the same Compose project reach Sablier at http://sablier:10000.

  • Mount the socket at /run/podman/podman.sock. It is the default address, whatever the path on the host.
  • Disable SELinux separation for Sablier. On SELinux hosts, a container can only use the socket with label=disable.
The Podman API allows arbitrary code execution as the user that runs it: root, for rootful Podman. Only give the socket to Sablier.

Usage example

Opt a container in with the sablier.enable label, and give it a group:

  whoami:
    image: docker.io/sablierapp/mimic:v0.3.3
    command: ["-healthy=true"]
    labels:
      sablier.enable: "true"
      sablier.group: whoami
    # Sablier reports the container ready once this check passes.
    healthcheck:
      test: ["CMD", "/mimic", "healthcheck"]
      interval: 5s
    ports:
      - "8080:80"

Then configure your reverse proxy to call Sablier for the whoami group in front of the whoami container. On the first request, Sablier starts the container and holds the request, or shows a waiting page, until its health check passes. When the session expires, Sablier stops it.

Sablier stops opted-in containers when it starts. A container you start afterwards keeps running until its first session expires, unless you stop externally-started instances.

Provider reference

Configuration

OptionDefaultDescription
--provider.podman.uriunix:///run/podman/podman.sockThe address of the Podman API service: a unix:// socket or a tcp:// address.

Every --provider.* option that is not provider-specific also applies; see the CLI reference. The --provider.docker.* options do not apply.

With tracing enabled, every call to the Podman API is a child span of the request that triggered it.

Other addresses

Sablier connects to --provider.podman.uri only: it ignores the CONTAINER_HOST and DOCKER_HOST environment variables. ssh:// addresses are not supported.

Workloads

Containers

Sablier manages the containers that carry sablier.enable=true, running or not:

  • Stop works like podman stop: the container gets its stop signal, and is killed after its stop timeout. Sablier waits until it has exited.
  • Start works like podman start. Sablier leaves a running container as is.

Create the containers with podman compose, as in the usage example, or with podman create:

podman create --name whoami \
  --label sablier.enable=true \
  --label sablier.group=whoami \
  --health-cmd '["/mimic", "healthcheck"]' \
  --health-interval 5s \
  --publish 8080:80 \
  docker.io/sablierapp/mimic:v0.3.3 -healthy=true

Sablier watches Podman events: a container you create joins its groups without restarting Sablier.

For containers that Quadlet runs as systemd services, use the systemd provider instead: it starts and stops the unit.

Instance names

A reverse proxy can target one container by name instead of a group. The instance name is the container name, as podman ps shows it.

Compose builds the name from the project and the service. Run from the examples/podman folder, the whoami container of the usage example is named:

podman_whoami_1

That is the podman-compose form; Docker Compose names it podman-whoami-1. Set container_name to choose the name yourself.

Prefer groups: a name ties your proxy configuration to the tool that created the container.

Labels

Sablier settings are container labels that start with sablier.:

    labels:
      sablier.enable: "true"
      sablier.group: team-a,team-b
  • Set labels when you create the container. Podman can’t change the labels of an existing container, so recreate it, for example with podman compose up -d.
  • sablier.enable must be exactly true. Sablier lists containers with that label and value.
  • Quote true and numbers in a Compose map. Compose labels are strings.

With podman create or podman run, pass each label with --label, as in whoami.sh. The label reference lists every key.

Workload settings

Each excerpt below is the labels of a complete Compose file in examples/podman. Run one next to Sablier with podman compose -f compose.yml -f <file> up -d.

Enable
Since v1.10.0

sablier.enable=true opts the container in. It is required, and any other value is ignored. See the usage example.

Group
Since v1.10.0

sablier.group puts the container in one or more groups, separated by commas. A session for any of them starts it. Without it, the container is in the default group.

    labels:
      sablier.enable: "true"
      sablier.group: team-a,team-b

A list of groups needs v1.13.0 or later. Learn more about groups.

Ready after
Since v1.13.0

sablier.ready-after keeps reporting the container as not ready for a settling delay after it turns healthy. Use it when a container passes its health check before it can serve traffic.

    labels:
      sablier.enable: "true"
      sablier.group: slow-starter
      sablier.ready-after: 15s

Learn more about delaying readiness.

Ready on start
Since v1.15.0

sablier.ready-on-start=true reports the container ready as soon as Sablier starts it, without waiting for its health check.

    labels:
      sablier.enable: "true"
      sablier.group: whoami
      sablier.ready-on-start: "true"

Learn more about marking ready on start.

Running hours
Since v1.13.0

  • sablier.running-hours keeps the container running during a daily window.
  • sablier.running-days limits that window to some weekdays, since v1.15.0.
    labels:
      sablier.enable: "true"
      sablier.group: office-app
      sablier.running-hours: "09:00-18:00"
      sablier.running-days: Mon,Tue,Wed,Thu,Fri

The window uses Sablier’s local time, which is UTC in the Sablier image. Set the TZ environment variable of the Sablier container to change it:

  sablier:
    environment:
      - TZ=Europe/Paris # running hours use Sablier's local time

Learn more about running hours.

Anti-affinity
Since v1.15.0

sablier.anti-affinity lists groups the container backs off from: Sablier keeps it idle while any of them has an active session.

    labels:
      sablier.enable: "true"
      sablier.group: background
      sablier.anti-affinity: streaming

Learn more about anti-affinity.

Scale instead of stop
Since v1.13.0

Keep the container running when idle, optionally with lower CPU and memory limits, instead of stopping it:

  • sablier.idle.replicas=1 keeps the container running when idle.
  • sablier.idle.cpu and sablier.idle.memory set its CPU and memory limits while idle. They need sablier.idle.replicas=1.
  • sablier.active.cpu and sablier.active.memory set the limits again on the next session.

CPU values are cores, such as 0.5. Sablier sends them as a CPU quota over a 100 ms period, the form Podman’s Docker-compatible API reads.

Memory values use the suffixes b, k, m and g, such as 64m or 1g. Sablier sets the swap limit to the same value, which disables swap for the container.

    labels:
      sablier.enable: "true"
      sablier.group: cache
      sablier.idle.replicas: "1"
      sablier.idle.memory: 64m
      sablier.active.memory: 512m
  • Memory limits need Podman 5.1 or later. Older versions lack the Docker-compatible update endpoint that Sablier calls.
  • Rootless Podman may refuse to change limits. It depends on the host’s cgroup setup; see podman update.

Learn more about scaling instead of stopping.

Readiness

Sablier reports a container:

  • ready when it is running and its health check passes. A running container without a health check is ready at once, and Sablier logs a warning.
  • starting when it is created, restarting or being removed, or running with a health check that has not passed yet. An unhealthy container counts as starting: Sablier keeps waiting until the request times out.
  • stopped when it exited with code 0, or is paused.
  • error when it exited with another code, or is dead.

Give your containers a health check, so Sablier sends traffic only once they can serve it.

Podman schedules health checks with systemd timers. On a host without systemd, they never run, and a container with a health check stays starting. Run them yourself with podman healthcheck run, or remove the health check.

Limitations

Examples