Need help with your JSON?

Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool

Building Docker Containers for JSON Processing Tools

What Searchers Usually Need

If you are looking for a JSON formatter that runs in Docker, the real requirement is usually much simpler than it sounds: you want one repeatable command that formats, validates, or transforms JSON the same way on every machine and in every CI job.

For most teams, a tiny jq container is enough. Build your own image only when you need a pinned team command, a wrapper script, extra certificates, bundled schemas, or additional tools around the formatter itself.

Before You Build Anything: Use the Official jq Image

The jq project now publishes container images from GitHub Container Registry at ghcr.io/jqlang/jq. If your goal is simply to pretty-print, validate, or run filters against JSON, start there instead of maintaining a custom Dockerfile.

echo '{"name":"Alice","age":30}' | docker run --rm -i ghcr.io/jqlang/jq:latest .

The . filter is the simplest possible JSON formatter: it reads JSON, validates it, and prints formatted output. That makes it a solid default for Docker-based formatting jobs.

docker run --rm \
  -v "$PWD":/work \
  -w /work \
  ghcr.io/jqlang/jq:latest . package.json > package.pretty.json

Use the official image when you do not need customization. Build your own only when the container has to behave like a team-standard command or ship extra logic alongside jq.

Minimal jq Dockerfile for a Team-Friendly Formatter

For a custom image, keep the runtime tiny and make the container behave like a CLI executable. Docker's current guidance is to use ENTRYPOINT for the executable and CMD for default arguments.

FROM alpine:3.21

RUN apk add --no-cache jq

WORKDIR /work
ENTRYPOINT ["jq"]
CMD ["."]

Why this layout works well:

  • apk add --no-cache keeps Alpine package indexes out of the final image.
  • CMD ["."] makes the image pretty-print JSON by default.
  • Extra arguments after docker run ... my-json-formatter replace the default filter without replacing the jq executable.
docker build --pull -t my-json-formatter .

Use --pull when rebuilding so Docker checks for a fresher base image.

docker run --rm -i my-json-formatter < payload.json

docker run --rm -i my-json-formatter '.items[] | {id, status}' < payload.json

When You Should Build More Than a jq Wrapper

A custom image is worth the maintenance cost when your formatter is only one step in a broader workflow.

  • You need a wrapper script that normalizes exit codes, error messages, or key ordering.
  • You want bundled schemas, CA certificates, or auth helpers available inside CI and batch jobs.
  • You need several tools, such as jq, yq, or a Python validator, in one stable environment.
  • You want a short internal command name that teammates can run without caring how it is packaged.

Custom Script Example: Format JSON and Sort Keys

If plain jq . is not enough, wrap a small script in a slim runtime image. This example sorts object keys so the output is stable in diffs and code review.

Python Script (format_json.py):

import json
import sys

try:
    data = json.load(sys.stdin)
except json.JSONDecodeError as exc:
    print(f"Invalid JSON: {exc}", file=sys.stderr)
    raise SystemExit(1)

json.dump(data, sys.stdout, indent=2, sort_keys=True)
sys.stdout.write("\n")

Dockerfile:

FROM python:3.12-slim

WORKDIR /app
COPY format_json.py .

ENTRYPOINT ["python", "/app/format_json.py"]
docker build --pull -t sorted-json .
echo '{"b":1,"a":2}' | docker run --rm -i sorted-json

If you later add third-party Python packages, copy requirements.txt before the rest of the source and install dependencies in that earlier layer so Docker can reuse build cache when your script changes but your dependencies do not.

Current Docker Build Practices That Matter Here

  • Use multi-stage builds when build-only tooling is involved. If your JSON tool needs compilation or heavy build dependencies, keep those in a builder stage and copy only the runtime artifacts into the final image.
  • Pin base image tags you have tested. A tag like alpine:3.21 is more predictable than floating latest.
  • Add a small .dockerignore. Exclude local output, logs, and bulky sample data so builds stay fast.
  • Keep the container ephemeral. For formatter jobs, use docker run --rm and write the result to stdout unless you truly need persistent in-container state.
  • Keep one concern per image. A formatter image should format JSON, not quietly grow into a general-purpose shell toolbox unless that is a deliberate team choice.
.git
node_modules
dist
coverage
*.log
sample-data/

A small .dockerignore like this is often enough for a JSON-tool image.

Troubleshooting the Usual Failures

  • No output when piping JSON in: use -i so Docker keeps standard input open.
  • Temporary formatter containers pile up: add --rm to remove them automatically after each run.
  • Mounted files end up owned by root: prefer redirecting stdout on the host, or run with --user "$(id -u):$(id -g)" if the container must write into a bind mount.
  • Your default filter seems to disappear: arguments after the image name override CMD, while ENTRYPOINT keeps the executable fixed.
  • The image is larger than expected: remove unnecessary packages and switch to a slimmer base or a multi-stage build.

Conclusion

For most Docker-based JSON formatting jobs, the fastest answer is the official jq image plus docker run --rm -i ... .. Build your own image when you need a pinned team workflow, extra scripts, or stricter reproducibility. Keep the image small, pin what you test, and make stdout the default interface.

Need help with your JSON?

Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool