---
title: Overview
description: What the container collection is, its features, and how it works.
url: https://containers.supanadit.com/index.md
---

# Containers

**Transparent, reproducible alternatives to Bitnami containers**

A collection of production-ready Docker containers for databases, message brokers, observability, and big data — every image built with forge from a declarative forge.toml manifest and supervised by ezx. No setup.sh, no shell entrypoints, no mystery layers: fully reproducible, reviewable builds that run as non-root and are simple enough to operate without being a Docker expert.

- **Registry:** ghcr.io/supanadit/containers
- **License:** MIT License
- **Repository:** <https://github.com/supanadit/containers>
- **Docs:** <https://docs.containers.supanadit.com>

## What it does

Production-ready images for PostgreSQL, MariaDB, Kafka, Grafana, Prometheus, and more — each built from a declarative forge.toml manifest and supervised by a single Go binary. No setup.sh, no shell entrypoints, no root processes. An open alternative to Bitnami.

## The problem

Most community container images ask you to trust them blindly. Entrypoints buried in setup.sh with implicit ordering and no review trail. Applications running as root because nobody got around to chowning. Config generated by sed one-liners that break on the first edge case. Build layers that recompile the world whenever one ARG changes. Health checks that return 200 while the app is still bootstrapping. These containers are built differently — declaratively, from source, with supervision built in.

## Features

- **Declarative builds with forge** — Every image is assembled by forge from a forge.toml manifest: apt packages, pinned source downloads with checksums, compiled binaries, users, and cleanup as an ordered, dependency-resolved op list.
- **Supervised by ezx** — A single Go binary stays PID 1: it forwards signals, reaps zombies, rotates logs, probes readiness, and drops privileges per process. The application never runs unsupervised.
- **JavaScript entrypoints, zero shell** — Each container ships a small module set (env, validation, directories, config, runtime, health API) that validates, writes config, and starts the app. No bash to break at 3 a.m.
- **Non-root by default** — Every application runs as its own dedicated user via process.user/process.group. /opt/containers/{data,config,logs,run,backup} is pre-created and pre-owned so volumes just work.
- **Composite health endpoints** — Each image exposes a shared health server with app-specific probes plus a composite endpoint, so orchestrators see real readiness instead of a TCP handshake.
- **Env-var driven configuration** — One env.js per container is the single source of truth for every variable. Config files are generated at boot from typed values — env.bool, env.int — never sed-edited.
- **Checksum-verified downloads** — forge, ezx, JDK tarballs, and every pinned binary are downloaded and checksum-verified during the build. The supply chain is explicit and auditable.
- **Tested in CI, per container** — Every container has compose-based test suites that assert the app answers on its own protocol, the composite health endpoint is healthy, the app runs as a non-root user, and ezx is PID 1.
- **TLS and clustering ready** — Where the upstream app supports it, the container does too — PostgreSQL with TLS, etcd clusters, Kafka in KRaft mode, MinIO distributed — configured with plain environment variables.
- **Working examples included** — The documentation site carries per-container guides — TLS, clustering, KRaft, pgBackRest — plus ready-made compose scenarios you can copy verbatim.

## The containers

### Databases

- **postgresql** — PostgreSQL with optional TLS, composite health probing, and scheduled pgBackRest backups built in.
- **mariadb** — MariaDB with scheduled backups, strict validation at boot, and a dedicated non-root daemon user.
- **pgpool-ii** — Pgpool-II connection pooling and load balancing for PostgreSQL, using upstream launchers under ezx supervision.
- **maxscale** — MariaDB MaxScale proxy for routing, filtering, and high availability in front of MariaDB clusters.

### Messaging & Coordination

- **apache-kafka** — Apache Kafka in KRaft mode — no ZooKeeper required — with scheduled maintenance jobs and KRaft bootstrapping.
- **apache-zookeeper** — Apache ZooKeeper ensemble node with generated dynamic configuration and fail-fast environment validation.
- **etcd** — etcd built from source with a Go toolchain, cluster flags driven entirely by environment variables.

### Storage

- **minio** — MinIO object storage compiled from upstream source, single-node or distributed layouts.

### Observability

- **prometheus** — Prometheus with config generated at boot from environment variables and composite health probing.
- **grafana** — Grafana dashboards with provisioning and datasource configuration handled by the entrypoint.
- **grafana-loki** — Grafana Loki log aggregation, single-node or scalable, with S3-compatible storage support.
- **grafana-mimir** — Grafana Mimir for long-term Prometheus metrics, in single-binary or clustered layouts.
- **grafana-tempo** — Grafana Tempo distributed tracing backend with single-node and microservice compositions.
- **grafana-alloy** — Grafana Alloy telemetry collector for pipelines that feed Loki, Mimir, and Tempo.
- **grafana-pyroscope** — Grafana Pyroscope continuous profiling storage with single and multi-instance compositions.
- **thanos** — Thanos for global Prometheus views — sidecar and store patterns covered by compose examples.

### Big Data & Workflow

- **apache-airflow** — Apache Airflow with scheduler, webserver, and workers orchestrated as separate supervised nodes.
- **apache-cassandra** — Apache Cassandra with rack/DC-aware seed configuration generated from environment variables.
- **apache-flink** — Apache Flink with JobManager and TaskManager as supervised processes behind one entrypoint.
- **apache-spark** — Apache Spark with master and worker nodes configured declaratively and health-checked.

### Web

- **wordpress** — WordPress on Apache with generated wp-config.php, tuned php.ini, and MariaDB pairing in the examples.

## How it works

Every container follows the same contract: a declarative forge.toml build, a JavaScript entrypoint with no shell, and an ezx supervisor that stays PID 1 for the lifetime of the container.

Packages, checksum-verified sources, and pinned variables flow into forge, which resolves the manifest into a DAG and builds the image in parallel, ordered operations. At run time the ezx entrypoint validates the environment and writes config, then the supervisor stays PID 1: it drops privileges, forwards signals, and probes the composite health endpoint for the whole lifetime of the container.

