Files
panda-rpki-oss/docs/docker.md
yuyr e3a1d0a6ff
Some checks failed
ci / rust (push) Has been cancelled
ci / docker (push) Has been cancelled
ci / audit (push) Has been cancelled
补充 OSS 验证策略配置示例
2026-09-23 10:36:21 +08:00

10 KiB

Docker and Compose

For every field, default, constraint and complete example, see the TOML configuration reference。

The image contains the validator, rsync, CA certificates and /usr/bin/time. The root filesystem is read-only; input and configuration are read-only; output and state mounts are writable. The application receives a subcommand and one configuration option: validate|daemon --config FILE.

Build the image:

docker build -f docker/Dockerfile -t panda-rpki:v0.1.0 .

Single validate run

Create a TOML whose paths are valid inside the container:

config-version = 1
mode = "validate"
out = "/output"
rrdp-state-dir = "/state/repository"
ccr-out = "/output/result.ccr"

[[anchors]]
id = "anchor"
tal = "/input/anchor.tal"
# ta = "/input/anchor.cer" # uncomment for fixed TA mode

Run the provided Compose template:

mkdir -p state output
export CONFIG_FILE="$PWD/validate.toml"
export INPUT_DIR="$PWD/input" STATE_DIR="$PWD/state" OUTPUT_DIR="$PWD/output"
export PUID="$(id -u)" PGID="$(id -g)"
docker compose -f docker/compose.yaml run --build --rm validator

The template mounts the TOML read-only at /config/validate.toml and invokes panda-rpki validate --config /config/validate.toml. Host variables only select mounts, image and container UID/GID; they are not read as validator settings.

Local HTTPS test repository

Use validate-localhost.toml and compose.localhost.yaml to run the generated HTTPS repository used by the regression tests. The TOML explicitly sets http-root-cert = ["/fixture/certs/rrdp-ca.pem"]; this is the generated test server CA, separate from the RPKI trust anchor. The validator uses host networking because the generated RRDP URI is https://localhost:8443:

work="$(mktemp -d)"
python3 tests/support/generate_repository.py \
  --rrdp-host localhost --rrdp-port 8443 --output "$work/fixture"
ln -s cases/baseline-v1/http "$work/fixture/active"
mkdir -p "$work/output" "$work/state"
python3 tests/support/serve_repository.py \
  "$work/fixture/active" 8443 \
  "$work/fixture/certs/rrdp-server.pem" \
  "$work/fixture/certs/rrdp-server.key" >"$work/server.log" 2>&1 &
server_pid="$!"
trap 'kill "$server_pid" 2>/dev/null || true; rm -rf "$work"' EXIT
for _ in $(seq 1 50); do grep -qx ready "$work/server.log" && break; sleep 0.1; done
grep -qx ready "$work/server.log"
export CONFIG_FILE="$PWD/docker/examples/validate-localhost.toml"
export FIXTURE_DIR="$work/fixture" OUTPUT_DIR="$work/output" STATE_DIR="$work/state"
export PUID="$(id -u)" PGID="$(id -g)"
docker compose -f docker/compose.localhost.yaml run --build --rm validator

All five RIRs

Copy the vendored OpenBSD TALs and constraints into an operator-managed input directory. Review the retained upstream notices, including the ARIN disclaimer. TA certificates are optional; the examples refresh them. Both all5 templates enable constraints by default:

mkdir -p input state/all5 output/all5
cp tals/*.tal tals/*.constraints input/
cp docker/examples/validate-all5.toml all5.toml
export CONFIG_FILE="$PWD/all5.toml"
export INPUT_DIR="$PWD/input" STATE_DIR="$PWD/state/all5" OUTPUT_DIR="$PWD/output/all5"
docker compose -f docker/compose.all5.yaml run --build --rm validator

The application still receives only validate --config; workers, timeouts, logging and sync policy belong in all5.toml.

Daemon

Daemon TOML paths are also container paths. state-root owns run directories, protocol state and the latest pointer:

config-version = 1
mode = "daemon"
state-root = "/data"
interval-secs = 600
retain-runs = 10
run-timeout-secs = 1800
shutdown-grace-secs = 30

[[anchors]]
id = "anchor"
tal = "/input/anchor.tal"
# ta = "/input/anchor.cer" # uncomment for fixed TA mode

Run the daemon template:

mkdir -p daemon-state
export CONFIG_FILE="$PWD/daemon.toml"
export INPUT_DIR="$PWD/input" DAEMON_DIR="$PWD/daemon-state"
export PUID="$(id -u)" PGID="$(id -g)"
docker compose -f docker/compose.daemon.yaml up --build

For an all-RIR daemon use docker/compose.all5-daemon.yaml with an all-RIR TOML. Stop the whole Compose service for an upgrade so the state-root lock and validator child are released; do not delete daemon-state.

Configuration and persistence

Run docker compose ... run --rm validator validate --config ... --check-config only when the image command is overridden deliberately; the normal templates already pass the config. Check/print never download TA files or open RocksDB. Successful validate publication, when publish-dir is configured, is an immutable publish/runs/<id> plus publish/latest; daemon publication uses its existing state-root/runs/run_<seq> directory. Cache files are written beside the protocol state as <state>.ta-cache/.

If a host path is not writable by the selected UID/GID, pre-create it and fix ownership. Preserve existing state and run history when changing images. Verify summary.json, result-complete.json, vrps.csv, vaps.csv, timing files and the latest link after a deployment.

Complete configuration examples

Copy a template before editing it; set CONFIG_FILE to the copy's absolute path. These templates use automatic TA certificate refresh, text/info logs and require-complete = true. They never download or update TAL files.

Compose file Complete TOML
compose.yaml validate.toml
compose.localhost.yaml validate-localhost.toml
compose.all5.yaml validate-all5.toml
compose.daemon.yaml daemon.toml
compose.all5-daemon.yaml daemon-all5.toml

validate-policy.toml is an additional configuration-only showcase for the validation-policy, validation-time and RRDP/rsync settings. Run it with compose.yaml after copying it outside the examples directory and setting CONFIG_FILE to the copied file.

For example, from the repository root:

mkdir -p input
cp tals/*.tal tals/*.constraints input/
cp docker/examples/daemon-all5.toml daemon.toml
export CONFIG_FILE="$PWD/daemon.toml"
export INPUT_DIR="$PWD/input" DAEMON_DIR="$PWD/daemon-state"
mkdir -p "$DAEMON_DIR"
export PUID="$(id -u)" PGID="$(id -g)"
docker compose -p panda-all5 -f docker/compose.all5-daemon.yaml up -d --build

For single validation, /state is the writable mount parent. Set rrdp-state-dir = "/state/repository" so both /state/repository and its sibling /state/repository.ta-cache are persistent and writable. Existing fixed-mode deployments with rrdp-state-dir = "/state" must plan a stopped state-layout migration or mount /state.ta-cache separately before enabling automatic mode. Do not silently point an existing database at an empty path. Daemon needs no such migration: /data/state and /data/state.ta-cache already share the writable /data mount.

Graceful stop, edit and reload

Use the same project name, Compose file and environment file on every command. The following assumes the panda-all5 project created above:

dc() { docker compose -p panda-all5 -f docker/compose.all5-daemon.yaml "$@"; }
dc stop --timeout 40 validator
dc ps -a
cp -a "$CONFIG_FILE" "$CONFIG_FILE.bak.$(date -u +%Y%m%dT%H%M%SZ)"

Edit the existing top-level field to log-format = "text". To enable automatic TA refresh, remove each desired anchor's ta field; keep its id and tal. ta-refresh-policy = "allow-valid-cache" allows a revalidated cache fallback and marks that run partial; "require-fresh" rejects the fallback. Missing or invalid cache cannot satisfy the first automatic run if all downloads fail.

Check the changed file and recreate the service:

dc run --rm --no-deps validator daemon --config /config/daemon.toml --check-config
dc run --rm --no-deps validator daemon --config /config/daemon.toml --print-config
# Continue only after Configuration valid. and the expected effective settings.
dc up -d --no-build --force-recreate validator
dc logs --since 2m validator

Recreation is intentional: editors and sed -i can replace the host file's inode, while an existing single-file bind mount may retain the old file. start or restart alone is not the documented configuration reload procedure. Recreation retains bind-mounted state and run history.

SIGTERM prevents further cycles and allows the active child up to shutdown-grace-secs (30 here) to finish. If it does not finish, the controller sends TERM, then KILL after another 2 seconds. Docker's 40-second timeout leaves room for controller cleanup. It is not an unlimited wait for the current cycle. To avoid interrupting a long cycle, stop during the daemon's sleeping interval. exited confirms the container stopped; exit 3 means the controller recorded partial runs under require-complete, and does not mean stop failed. Inspect lifecycle logs to establish whether the last child finished or was interrupted.

The controller logs are in docker compose logs; child diagnostics are in data/runs/run_XXXXXX/validator.log on the host. Existing logs keep their original format. JSON summary/metadata files remain JSON even with text diagnostics. latest exists only after a complete success; partial runs do not create or replace it, including the first run after upgrading an old state root.

Change or disable constraints

Edit the copied input/<rir>.constraints files, or set an anchor's constraints to a different file under /input. Set top-level ta-constraints-enabled = false to disable all policies, including same-stem auto-discovery. The all5 examples use true and explicit paths so missing files fail configuration checks.

Use the stop/check/print/force-recreate steps above after editing. Validate-only runs read the configuration and policies afresh on each invocation. Do not copy vendored files over customized input files during an image upgrade; merge upstream updates deliberately and retain backups. No online TAL or policy update is performed by the validator.