Skip to content
/ tino Public

tino: tiny init process (PID 1) for Docker/Kubernetes containers, written in Rust (tini alternative)

License

Notifications You must be signed in to change notification settings

lvillis/tino

Repository files navigation

🇺🇸 English · 🇨🇳 中文       |      Table of Contents ↗️

tino

tino is a tiny init process (PID 1) for Docker/Kubernetes containers, written in Rust — a modern alternative to tini.

Crates.io  Repo Size  CI  Docker Pulls  Image Size  Say Thanks


✨ Features

Feature Description
Pure Rust, static No runtime deps, musl-linked binary ≤ 60 kB
Sub-reaper mode -s flag enables PR_SET_CHILD_SUBREAPER, reaps orphaned children
Parent-death signal -p <SIG> mirrors tini -p (PR_SET_PDEATHSIG)
Signal forwarding Forwards most signals; -g mode falls back gracefully if PGID can't be assigned
Graceful shutdown SIGTERM → configurable wait → SIGKILL; timeout set via -t/--grace-ms
Exit-code remap -e <code> maps specific child exit codes to zero for health-checks
Verbosity control -v/-vv/-vvv or TINI_VERBOSITY=1..3 via tracing
Security-audited #![deny(unsafe_op_in_unsafe_fn)], minimal unsafe surface, no dynamic allocation in hot paths
Cross-platform Linux glibc / musl; works as PID 1 in Docker, LXC, Podman, Kubernetes, fire-cracker, etc.
Env overrides TINI_SUBREAPER, TINI_KILL_PROCESS_GROUP, TINI_VERBOSITY act as defaults (CLI wins)
Landlock sandbox --landlock restricts filesystem writes to allowlisted directories (Linux; may need seccomp)

📦 Installation

# Install locally with Cargo
cargo install tino

# Build a static binary (e.g. for PID 1 in Docker)
cargo build --release --target x86_64-unknown-linux-musl

# Docker image (includes /sbin/tino)
docker pull lvillis/tino

🚀 Quick Start

# Replace tini in your Dockerfile
ENTRYPOINT ["/sbin/tino", "-g", "-s", "--"]

# Run locally
tino -- echo "hello from child"

🧭 Runtime Notes

  • -g/--pgroup-kill logs a warning and falls back to single-process signalling when process-group creation fails (for example inside constrained PID namespaces).
  • tino's internal signalfd is opened with CLOEXEC, ensuring child workloads do not inherit extra file descriptors.
  • Logging setup is idempotent: repeated initialisation (tests, embedding) no longer panics.
  • TINI_* env vars only apply when the corresponding CLI flag is not set (CLI wins).
  • Landlock (optional, Linux): --landlock --landlock-writable /path (repeatable) or --landlock-profile file (one path per line) denies filesystem writes outside allowlisted directories; default is strict (use --landlock-warn-only to continue).
  • Landlock keeps /dev writable for TTY/stdout by default (disable with --landlock-no-dev).
  • Docker: if Landlock syscalls are blocked, use --security-opt seccomp=./seccomp-landlock.json (or seccomp=unconfined for testing).

🛡️ Landlock + Docker (seccomp)

Docker's default seccomp profile often blocks landlock_* syscalls. This repo includes seccomp-landlock.json, based on moby/profiles (see seccomp-landlock.upstream.sha).

docker run --rm -it \
  --security-opt seccomp=./seccomp-landlock.json \
  <image> \
  /sbin/tino --landlock --landlock-writable /data -- <cmd> ...

To make this the default for all containers, set Docker's daemon config:

{ "seccomp-profile": "/etc/docker/seccomp-landlock.json" }

Refresh the profile with python scripts/update-seccomp-landlock.py.

🧪 Testing

cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all --verbose

On Unix targets an integration suite in tests/unix_behaviour.rs covers the CLI licence output, missing-command error path, and exit-code remapping flow.

About

tino: tiny init process (PID 1) for Docker/Kubernetes containers, written in Rust (tini alternative)

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 2

  •  
  •