This document describes how to build and use the Facet Docker container for generating PDFs and HTML from React templates.
- Multi-architecture support: Builds for both
linux/amd64andlinux/arm64platforms - Chromium browser: Pre-installed and configured for PDF generation via Puppeteer
- All dependencies cached: Fonts, libraries, and browser binaries are included in the image
- Facet CLI: Ready to use for generating PDFs and HTML from React templates
- Example included: Sample template and data files for testing
# Build for your current architecture
docker build -t facet:latest .
# Build for a specific architecture
docker build --platform linux/amd64 -t facet:amd64 .
docker build --platform linux/arm64 -t facet:arm64 .
# Build for multiple architectures (requires buildx)
docker buildx build --platform linux/amd64,linux/arm64 -t facet:latest .The repository includes a GitHub Actions workflow (.github/workflows/docker-build.yml) that automatically builds and pushes multi-arch Docker images to GitHub Container Registry (ghcr.io).
- Push to main: Builds and pushes with
latesttag - Push to feature branches: Builds and pushes with branch name tag
- Tags (v)*: Builds and pushes with version tags
- Pull requests: Builds without pushing (validation only)
- Manual: Can be triggered via workflow_dispatch
Images are published to: ghcr.io/flanksource/facet
Tags:
latest- Latest build from main branchv1.2.3- Specific version tagsmain-<sha>- Build from specific commit<branch>- Build from feature branch
Generate a PDF from your templates:
docker run --rm \
-v $(pwd):/work \
ghcr.io/flanksource/facet \
pdf /work/MyTemplate.tsx --data /work/data.json -o /work/output.pdfGenerate HTML:
docker run --rm \
-v $(pwd):/work \
ghcr.io/flanksource/facet \
html /work/MyTemplate.tsx --data /work/data.json -o /work/output.htmlTest the container with the included sample:
docker run --rm \
-v $(pwd):/work \
ghcr.io/flanksource/facet \
pdf /app/examples/SimpleReport.tsx \
--data /app/examples/simple-data.json \
-o /work/sample.pdfThis will create sample.pdf in your current directory.
Start an interactive shell in the container:
docker run --rm -it \
-v $(pwd):/work \
ghcr.io/flanksource/facet \
/bin/bashThen run facet commands:
facet pdf /work/template.tsx --data /work/data.jsonThe container sets the following environment variables:
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true- Uses system ChromiumPUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium- Path to Chromium binary
The Dockerfile uses a multi-stage build:
- Builder stage: Installs build dependencies, copies source, and builds the CLI library
- Runtime stage: Minimal image with only runtime dependencies, Chromium, and compiled artifacts
- Node.js 20: JavaScript runtime
- Chromium: Headless browser for PDF generation
- Fonts: Liberation, Noto Color Emoji, and various international fonts
- Facet CLI: Built library and source files
- Dependencies: All npm packages required for PDF generation
/app: Application files and built CLI/app/examples: Sample templates/workspace: Default working directory (mount your files here)
If you encounter permission issues with generated files:
docker run --rm \
-v $(pwd):/work \
--user $(id -u):$(id -g) \
ghcr.io/flanksource/facet \
pdf /work/template.tsx --data /work/data.jsonIf the container fails to generate PDFs, verify Chromium is working:
docker run --rm ghcr.io/flanksource/facet chromium --versionRun the container with verbose output:
docker run --rm \
-v $(pwd):/work \
ghcr.io/flanksource/facet \
pdf /work/template.tsx --data /work/data.json --verboseBuild and test locally before pushing:
# Build
docker build -t facet:dev .
# Test
docker run --rm facet:dev pdf /app/examples/SimpleReport.tsx \
--data /app/examples/simple-data.json -o /tmp/test.pdf
# Verify output
docker run --rm facet:dev ls -lh /tmp/test.pdfThe .dockerignore file excludes unnecessary files from the build context:
- Git files and history
- Node modules (installed during build)
- Test files
- Documentation
- Build artifacts
See the main README.md for license information.