Created by Chris Bunting cbuntingde@gmail.com
An interactive script that generates secure, hardened Dockerfiles for Java applications based on your specific requirements.
According to a recent survey of Java developers:
- 48% prefer pre-hardened container images over managing security themselves
- 62% of container security mistakes come from human error
- 23% experienced container-related security incidents in the past year
- Most use bloated general-purpose distributions with unnecessary packages
This script automates the creation of minimal, secure Java containers following industry best practices.
✅ Interactive Configuration - Answer simple questions, get a production-ready Dockerfile
✅ Multiple Security Levels - From maximum security (Distroless) to maximum compatibility (Ubuntu)
✅ Best Practice Enforcement - Non-root users, minimal packages, proper labels
✅ Multiple JDK Options - Eclipse Temurin, Amazon Corretto, Microsoft, Azul Zulu
✅ Complete Setup - Generates Dockerfile, docker-compose.yml, .dockerignore, and documentation
✅ Security Scanning - Includes scan script for Trivy, Grype, and Docker Scout
# Run the interactive script
./java-docker-hardener.sh
# Follow the prompts to configure your containerThe script creates:
- Dockerfile.hardened - Your custom hardened Dockerfile
- docker-compose.hardened.yml - Docker Compose configuration with security options
- .dockerignore.hardened - Optimized ignore file
- DOCKER_README.md - Complete documentation for your specific setup
- scan-image.sh - Security scanning script
- Java 8 (LTS)
- Java 11 (LTS)
- Java 17 (LTS)
- Java 21 (LTS)
- Java 23 (Latest)
- JRE only - Smaller, production-optimized (recommended)
- Full JDK - For development or debugging
-
Maximum Security (Distroless)
- No shell, no package manager
- Minimal attack surface
- Best for production
-
High Security (Alpine)
- Minimal Linux distribution
- Small size (~50MB)
- Good compatibility
-
Balanced (Debian Slim)
- Broad compatibility
- Moderate size
- Well-tested
-
Standard (Ubuntu)
- Maximum compatibility
- Larger size
- Good for complex dependencies
- Eclipse Temurin (recommended)
- Amazon Corretto
- Microsoft OpenJDK
- Azul Zulu
- Executable JAR - Spring Boot, Micronaut, Quarkus, or any standalone JAR
- WAR file - Traditional servlet container applications (Tomcat, Jetty)
- Standard Java - Applications with external dependencies/libraries
- ✅ Run as non-root user
- ✅ Security scanning metadata/labels
- ✅ Minimize installed packages
- ✅ Health checks
- ✅ JVM container-aware settings
For a Java 17 Spring Boot app with maximum security:
FROM gcr.io/distroless/java17-debian12:nonroot
LABEL org.opencontainers.image.title="Hardened Java Application"
LABEL security.hardening="enabled"
WORKDIR /app
COPY app.jar /app/app.jar
EXPOSE 8080
ENV JAVA_OPTS="-Xmx512m -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
ENTRYPOINT ["java"]
CMD ["-jar", "/app/app.jar"]# 1. Run the script
./java-docker-hardener.sh
# Example selections:
# - Java 17 (LTS)
# - JRE only
# - Maximum Security (Distroless)
# - Eclipse Temurin
# - Executable JAR
# - Yes to all security options
# 2. Place your JAR file
cp target/myapp.jar app.jar
# 3. Build the image
docker build -f Dockerfile.hardened -t myapp:secure .
# 4. Scan for vulnerabilities
./scan-image.sh myapp:secure
# 5. Run the container
docker run -p 8080:8080 myapp:secure- Only includes necessary runtime components
- Reduces attack surface by 80%+ compared to full OS images
- Containers run as unprivileged user
- Limits damage from container breakout
- Removes package managers, build tools, docs
- Fewer components = fewer vulnerabilities
- Uses
-XX:+UseContainerSupport - Respects cgroup memory limits
- Better resource utilization
- Docker Compose includes
read_only: true - Only /tmp is writable
- Removes all Linux capabilities
- Only adds what's strictly necessary
- Built-in container health monitoring
- Automatic restart on failure
| Base Image | Approximate Size | Use Case |
|---|---|---|
| Distroless | 120-150 MB | Maximum security, production |
| Alpine | 150-180 MB | High security, small size |
| Debian Slim | 200-250 MB | Balanced approach |
| Ubuntu | 300-400 MB | Maximum compatibility |
The generated scan-image.sh script supports:
trivy image myapp:securegrype myapp:securedocker scout cves myapp:secureEdit the generated Dockerfile to add specific JVM flags:
ENV JAVA_OPTS="-Xmx1g -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError"Combine with the script output for even smaller images:
# Build stage
FROM eclipse-temurin:17-jdk-alpine AS build
WORKDIR /build
COPY . .
RUN ./gradlew build
# Runtime (generated by script)
FROM gcr.io/distroless/java17-debian12:nonroot
COPY --from=build /build/target/app.jar /app/app.jar
# ... rest from generated DockerfileNever hardcode secrets! Use environment variables:
docker run -e DB_PASSWORD_FILE=/run/secrets/db_pass \
-v ./secrets:/run/secrets:ro \
myapp:secureDistroless has no shell. To debug:
# Use debug variant with busybox
FROM gcr.io/distroless/java17-debian12:debug-nonrootCheck ownership if using non-root:
RUN chown -R appuser:appuser /appIncrease container memory or tune JVM:
docker run -m 1g -e JAVA_OPTS="-Xmx800m" myapp:secureapiVersion: apps/v1
kind: Deployment
metadata:
name: java-app
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1001
fsGroup: 1001
containers:
- name: app
image: myapp:secure
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]docker service create \
--name myapp \
--publish 8080:8080 \
--replicas 3 \
--update-parallelism 1 \
--update-delay 10s \
myapp:secure- Regular Scans - Run security scans in CI/CD
- Update Base Images - Rebuild monthly for patches
- Monitor CVEs - Subscribe to security advisories
- SBOM Generation - Track dependencies
# Generate SBOM
docker sbom myapp:secureFeel free to enhance the script with:
- Additional JDK distributions
- More security hardening options
- Platform-specific optimizations
- Better vulnerability scanning integration
This script is provided as-is for educational and production use.