feat(dockerfile): migrate to scratch-based image#143
Conversation
LaurenceJJones
commented
Dec 18, 2025
- Replace alpine base with scratch for minimal 16MB image
- Remove docker_start.sh (no shell in scratch)
- Use ENTRYPOINT + CMD for direct binary execution
- Add CA certificates for HTTPS connections to LAPI
- Add docker/README.md with comprehensive usage documentation
- Replace alpine base with scratch for minimal 16MB image - Remove docker_start.sh (no shell in scratch) - Use ENTRYPOINT + CMD for direct binary execution - Add CA certificates for HTTPS connections to LAPI - Add docker/README.md with comprehensive usage documentation
- Add /run/crowdsec-spoa/ for Unix socket - Add /var/log/crowdsec-spoa/ for log files - Use .keep files to ensure empty directories are copied to scratch
- Add config/crowdsec-spoa-bouncer.docker.yaml with stdout logging - Support env vars: CROWDSEC_KEY, CROWDSEC_URL, LOG_LEVEL, etc. - Enable Prometheus by default on port 6060 - Update Dockerfile to use Docker config and expose both ports - Update README with comprehensive environment variables table
There was a problem hiding this comment.
Pull request overview
This PR migrates the Docker image from an Alpine-based image to a minimal scratch-based image, reducing the image size to approximately 16MB. The migration eliminates the shell wrapper script in favor of direct binary execution and adds comprehensive Docker usage documentation.
Key Changes:
- Replaced Alpine base with scratch for a minimal, security-focused image containing only the static binary and essential files
- Removed
docker_start.shshell script and implemented direct ENTRYPOINT/CMD configuration for binary execution - Added CA certificates to the image to support HTTPS connections to CrowdSec LAPI
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| Dockerfile | Migrated from Alpine to scratch base image, added CA certificates, restructured file copying for minimal image, removed user/group setup and VOLUME declarations |
| docker/docker_start.sh | Removed shell startup script (incompatible with scratch image which has no shell) |
| docker/README.md | Added comprehensive documentation covering image contents, configuration options, Docker Compose examples, health checks, and troubleshooting guidance |
Comments suppressed due to low confidence (1)
Dockerfile:17
- The migration to scratch removes user configuration entirely, meaning the container now runs as root by default. The previous Alpine image configured specific users (crowdsec-spoa:haproxy with specific UIDs/GIDs 99) and set directory permissions accordingly. This is a breaking change that affects:
- Security posture - running as root is generally discouraged
- File permissions - users who mount volumes may encounter permission issues since the container now runs as root instead of UID 99
- Docker Compose compatibility - existing deployments may fail if they rely on the specific user/group setup
Consider either: (a) documenting this breaking change prominently in the PR description and migration guide, or (b) adding a USER instruction to maintain backwards compatibility with a non-root user, though this requires using a base image that includes user setup (like distroless) instead of scratch.
FROM scratch
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- StrictExpand doesn't support ${VAR:-default} syntax
- Set default values via ENV in Dockerfile
- Simplify docker.yaml to use plain ${VAR} substitution
- Update README to clarify only CROWDSEC_KEY is required
Address Copilot review: use pinned versions instead of :latest - haproxy:3.1 - curlimages/curl:8.11.1
Address Copilot review: keep volumes for user customization even though documentation examples were simplified
Custom configuration file is the primary method, environment variables are a convenience layer for simple deployments.
* feat: migrate to scratch-based Docker image
- Replace alpine base with scratch for minimal 16MB image
- Remove docker_start.sh (no shell in scratch)
- Use ENTRYPOINT + CMD for direct binary execution
- Add CA certificates for HTTPS connections to LAPI
- Add docker/README.md with comprehensive usage documentation
* fix: create runtime directories for scratch image
- Add /run/crowdsec-spoa/ for Unix socket
- Add /var/log/crowdsec-spoa/ for log files
- Use .keep files to ensure empty directories are copied to scratch
* fix: correct Docker image name to crowdsecurity/spoa-bouncer
* feat: add Docker-optimized config with environment variables
- Add config/crowdsec-spoa-bouncer.docker.yaml with stdout logging
- Support env vars: CROWDSEC_KEY, CROWDSEC_URL, LOG_LEVEL, etc.
- Enable Prometheus by default on port 6060
- Update Dockerfile to use Docker config and expose both ports
- Update README with comprehensive environment variables table
* fix: use ENV defaults instead of shell syntax for env vars
- StrictExpand doesn't support ${VAR:-default} syntax
- Set default values via ENV in Dockerfile
- Simplify docker.yaml to use plain ${VAR} substitution
- Update README to clarify only CROWDSEC_KEY is required
* docs: pin image versions in Docker examples
Address Copilot review: use pinned versions instead of :latest
- haproxy:3.1
- curlimages/curl:8.11.1
* fix: restore VOLUME declarations for Lua and HTML customization
Address Copilot review: keep volumes for user customization even though
documentation examples were simplified
* docs: remove GOMEMLIMIT from README examples
* docs: reorder config sections - custom config before env vars
Custom configuration file is the primary method, environment variables
are a convenience layer for simple deployments.