Container images

Two images. One filter. Wherever you ship.

Every release publishes two distroless Linux images to GitHub Container Registry — one packaged as a GitHub Action, one as a standalone HTTP API. Both are built from the same Native AOT engine and tagged in lockstep.

Native AOT Distroless base linux/amd64 · linux/arm64 v13.3.0
🐙

Action container

ghcr.io/ievangelist/profanity-filter — the runner image used by the GitHub Action step. You usually don’t pull this directly; GitHub does it for you when a workflow says uses: IEvangelist/profanity-filter@main.

🛰️

API container

ghcr.io/ievangelist/profanity-filter-api — the standalone HTTP API. Powers the Aspire integration, the ProfanityFilter.Client NuGet, and any standalone deployment.

Action container

View on GHCR

The Action container packages the runner the workflow step uses. Powered by .NET 10 Native AOT, it cold-starts in milliseconds, has no .NET runtime to install, and is what makes a single uses: line work end-to-end.

Pull

terminal bash
docker pull ghcr.io/ievangelist/profanity-filter:13.3.0

API container

View on GHCR

A standalone ASP.NET Core minimal-API surface over the same filter engine, plus a SignalR hub for live streaming. Same image the Aspire integration pulls.

Pull

terminal bash
docker pull ghcr.io/ievangelist/profanity-filter-api:13.3.0

Run it standalone

The API listens on :8080 inside the container. Map the port and you’re live.

terminal bash
# Run the API on http://localhost:8080
docker run --rm \
  --name profanity-filter-api \
  -p 8080:8080 \
  ghcr.io/ievangelist/profanity-filter-api:13.3.0

# Optional — mount your own *.txt word lists, merged with the
# built-in 4,900+ word dictionary at startup:
docker run --rm \
  --name profanity-filter-api \
  -p 8080:8080 \
  -v "$(pwd)/CustomData":/app/CustomData:ro \
  ghcr.io/ievangelist/profanity-filter-api:13.3.0

Or with Compose

compose.yaml yaml
# compose.yaml
services:
  profanity-filter:
    image: ghcr.io/ievangelist/profanity-filter-api:13.3.0
    container_name: profanity-filter-api
    ports:
      - "8080:8080"
    volumes:
      - ./CustomData:/app/CustomData:ro
    restart: unless-stopped

HTTP surface

All routes return JSON. The container also serves an interactive Scalar reference at /scalar and an OpenAPI document at /openapi/v1.json.

Method Path Description
POST /profanity/filter Apply the filter to a body of text. Returns the filtered output, the matched words, and the per-step trace.
GET /profanity/strategies List the 14 replacement strategies (Emoji, RedactedRectangle, AngerEmoji, …).
GET /profanity/targets List the supported filter targets.
GET /profanity/data List the available word-list data set names (one per language plus any custom mounts).
GET /profanity/data/{name} Return the words in a single data set.
WS /profanity/hub SignalR hub — bi-directional streaming for live UIs (WebSockets / SSE / long-polling).

Try it

terminal bash
curl -X POST http://localhost:8080/profanity/filter \
  -H "content-type: application/json" \
  -d '{
    "text": "What the heck, dude?",
    "strategy": "Emoji"
  }'