1+ <?xml version =" 1.0" encoding =" UTF-8" ?>
2+ <cursor_rules >
3+ <title >Docker Best Practices for Java 25 Applications</title >
4+ <description >
5+ Comprehensive guidelines for containerizing Java 25 applications using Docker, focusing on performance optimization, security enhancements, and efficient resource utilization.
6+ </description >
7+
8+ <rules >
9+ <rule >
10+ <title >Use Appropriate Base Images</title >
11+ <description >
12+ Select the most suitable base image for your Java 25 application, considering size, security, and compatibility requirements.
13+ </description >
14+ <guidelines >
15+ <guideline >Use `eclipse-temurin:25-jre-alpine` for minimal production images</guideline >
16+ <guideline >Use `eclipse-temurin:25-jdk-alpine` only when JDK tools are required at runtime</guideline >
17+ <guideline >Prefer Alpine Linux variants for smaller image sizes</guideline >
18+ <guideline >Use specific version tags instead of `latest` for reproducible builds</guideline >
19+ </guidelines >
20+ <example >
21+ <![CDATA[
22+ # Production runtime image
23+ FROM eclipse-temurin:25-jre-alpine
24+
25+ # Development/build image
26+ FROM eclipse-temurin:25-jdk-alpine AS build
27+ ]]>
28+ </example >
29+ </rule >
30+
31+ <rule >
32+ <title >Implement Multi-Stage Builds</title >
33+ <description >
34+ Separate the build environment from the runtime environment to create lean, secure final images by excluding unnecessary build tools and dependencies.
35+ </description >
36+ <guidelines >
37+ <guideline >Use a build stage with JDK for compilation</guideline >
38+ <guideline >Use a runtime stage with JRE for execution</guideline >
39+ <guideline >Copy only necessary artifacts between stages</guideline >
40+ <guideline >Minimize the number of layers in the final image</guideline >
41+ </guidelines >
42+ <example >
43+ <![CDATA[
44+ # Build stage
45+ FROM eclipse-temurin:25-jdk-alpine AS build
46+ WORKDIR /app
47+ COPY pom.xml .
48+ COPY src ./src
49+ RUN ./mvnw clean package -DskipTests
50+
51+ # Runtime stage
52+ FROM eclipse-temurin:25-jre-alpine
53+ WORKDIR /app
54+ COPY --from=build /app/target/*.jar app.jar
55+ EXPOSE 8080
56+ ENTRYPOINT ["java", "-jar", "app.jar"]
57+ ]]>
58+ </example >
59+ </rule >
60+
61+ <rule >
62+ <title >Optimize JVM Configuration for Containers</title >
63+ <description >
64+ Configure the JVM to work efficiently within container resource constraints, taking advantage of Java 25's container awareness features.
65+ </description >
66+ <guidelines >
67+ <guideline >Use `-XX:+UseContainerSupport` to enable container awareness (enabled by default in Java 25)</guideline >
68+ <guideline >Set appropriate heap size using `-Xms` and `-Xmx` based on container memory limits</guideline >
69+ <guideline >Use `-XX:+UseG1GC` for better performance in containerized environments</guideline >
70+ <guideline >Enable JVM ergonomics with `-XX:+UnlockExperimentalVMOptions` for Java 25 features</guideline >
71+ <guideline >Use `-XX:+ExitOnOutOfMemoryError` to ensure container restart on OOM</guideline >
72+ </guidelines >
73+ <example >
74+ <![CDATA[
75+ ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:+UseContainerSupport -XX:+ExitOnOutOfMemoryError"
76+ ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
77+ ]]>
78+ </example >
79+ </rule >
80+
81+ <rule >
82+ <title >Implement Security Best Practices</title >
83+ <description >
84+ Enhance container security by following the principle of least privilege and implementing defense-in-depth strategies.
85+ </description >
86+ <guidelines >
87+ <guideline >Create and use a non-root user for running the application</guideline >
88+ <guideline >Use read-only root filesystem when possible</guideline >
89+ <guideline >Minimize the attack surface by removing unnecessary packages</guideline >
90+ <guideline >Scan images for vulnerabilities regularly</guideline >
91+ <guideline >Use secrets management for sensitive data</guideline >
92+ </guidelines >
93+ <example >
94+ <![CDATA[
95+ # Create non-root user
96+ RUN adduser --disabled-password --gecos "" --uid 1001 appuser
97+
98+ # Set ownership and permissions
99+ COPY --chown=appuser:appuser app.jar /app/app.jar
100+
101+ # Switch to non-root user
102+ USER appuser
103+
104+ # Use read-only filesystem
105+ # docker run --read-only --tmpfs /tmp myapp:latest
106+ ]]>
107+ </example >
108+ </rule >
109+
110+ <rule >
111+ <title >Optimize Image Layers and Caching</title >
112+ <description >
113+ Structure Dockerfile commands to maximize Docker layer caching and minimize image size.
114+ </description >
115+ <guidelines >
116+ <guideline >Order commands from least to most frequently changing</guideline >
117+ <guideline >Copy dependency files before source code to leverage cache</guideline >
118+ <guideline >Combine related RUN commands to reduce layers</guideline >
119+ <guideline >Use `.dockerignore` to exclude unnecessary files</guideline >
120+ <guideline >Clean up package caches and temporary files in the same layer</guideline >
121+ </guidelines >
122+ <example >
123+ <![CDATA[
124+ # Copy dependency files first for better caching
125+ COPY pom.xml ./
126+ COPY mvnw ./
127+ COPY .mvn ./.mvn
128+
129+ # Download dependencies (cached layer)
130+ RUN ./mvnw dependency:resolve
131+
132+ # Copy source code (changes more frequently)
133+ COPY src ./src
134+
135+ # Build application
136+ RUN ./mvnw clean package -DskipTests && \
137+ rm -rf ~/.m2/repository && \
138+ rm -rf target/classes target/generated-sources
139+ ]]>
140+ </example >
141+ </rule >
142+
143+ <rule >
144+ <title >Configure Health Checks and Monitoring</title >
145+ <description >
146+ Implement comprehensive health checking and monitoring to ensure application reliability and observability.
147+ </description >
148+ <guidelines >
149+ <guideline >Define Docker health checks for container orchestration</guideline >
150+ <guideline >Implement application health endpoints</guideline >
151+ <guideline >Configure proper logging to stdout/stderr</guideline >
152+ <guideline >Use structured logging formats (JSON) for better parsing</guideline >
153+ <guideline >Include JVM metrics and garbage collection monitoring</guideline >
154+ </guidelines >
155+ <example >
156+ <![CDATA[
157+ # Docker health check
158+ HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
159+ CMD curl -f http://localhost:8080/actuator/health || exit 1
160+
161+ # Application health endpoint (Spring Boot example)
162+ # management.endpoints.web.exposure.include=health,metrics,info
163+ # management.endpoint.health.show-details=always
164+
165+ # JVM monitoring flags
166+ ENV JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"
167+ ]]>
168+ </example >
169+ </rule >
170+
171+ <rule >
172+ <title >Manage Configuration and Secrets</title >
173+ <description >
174+ Externalize configuration and handle secrets securely to support different deployment environments.
175+ </description >
176+ <guidelines >
177+ <guideline >Use environment variables for configuration</guideline >
178+ <guideline >Support configuration files mounted as volumes</guideline >
179+ <guideline >Never embed secrets in Docker images</guideline >
180+ <guideline >Use Docker secrets or external secret management</guideline >
181+ <guideline >Implement configuration validation at startup</guideline >
182+ </guidelines >
183+ <example >
184+ <![CDATA[
185+ # Environment-based configuration
186+ ENV SPRING_PROFILES_ACTIVE=production
187+ ENV SERVER_PORT=8080
188+ ENV MANAGEMENT_PORT=9090
189+
190+ # Support for external configuration
191+ VOLUME ["/app/config"]
192+
193+ # Configuration precedence: env vars > mounted files > defaults
194+ ENTRYPOINT ["java", "-Dspring.config.location=classpath:/,file:/app/config/", "-jar", "app.jar"]
195+ ]]>
196+ </example >
197+ </rule >
198+
199+ <rule >
200+ <title >Optimize for Different Deployment Scenarios</title >
201+ <description >
202+ Create flexible Docker configurations that work well across development, testing, and production environments.
203+ </description >
204+ <guidelines >
205+ <guideline >Use build arguments for environment-specific customization</guideline >
206+ <guideline >Support both standalone and orchestrated deployments</guideline >
207+ <guideline >Implement graceful shutdown handling</guideline >
208+ <guideline >Configure appropriate resource limits and requests</guideline >
209+ <guideline >Use init systems for proper signal handling in containers</guideline >
210+ </guidelines >
211+ <example >
212+ <![CDATA[
213+ # Build arguments for flexibility
214+ ARG JAVA_OPTS_BUILD=""
215+ ARG APP_VERSION="latest"
216+
217+ # Graceful shutdown support
218+ ENV JAVA_OPTS="$JAVA_OPTS -Dserver.shutdown=graceful"
219+
220+ # Signal handling for proper shutdown
221+ RUN apk add --no-cache tini
222+ ENTRYPOINT ["tini", "--"]
223+ CMD ["java", "-jar", "app.jar"]
224+
225+ # Resource limits in deployment
226+ # resources:
227+ # limits:
228+ # memory: "1Gi"
229+ # cpu: "1000m"
230+ # requests:
231+ # memory: "512Mi"
232+ # cpu: "500m"
233+ ]]>
234+ </example >
235+ </rule >
236+
237+ <rule >
238+ <title >Leverage Java 25 Specific Features</title >
239+ <description >
240+ Take advantage of Java 25's latest features and improvements for better container performance and developer experience.
241+ </description >
242+ <guidelines >
243+ <guideline >Use Virtual Threads for improved scalability in I/O-intensive applications</guideline >
244+ <guideline >Leverage Pattern Matching and Switch Expressions for cleaner code</guideline >
245+ <guideline >Use Record Classes for data transfer objects</guideline >
246+ <guideline >Take advantage of improved garbage collection algorithms</guideline >
247+ <guideline >Use Text Blocks for embedded configuration or SQL</guideline >
248+ </guidelines >
249+ <example >
250+ <![CDATA[
251+ # Enable Virtual Threads (if using frameworks that support them)
252+ ENV JAVA_OPTS="$JAVA_OPTS -Djdk.virtualThreadScheduler.parallelism=1"
253+
254+ # Example of Java 25 features in application code:
255+ # public record UserRequest(String name, int age) {}
256+ #
257+ # public String processUser(Object obj) {
258+ # return switch (obj) {
259+ # case UserRequest(var name, var age) when age >= 18 ->
260+ # "Adult user: " + name;
261+ # case UserRequest(var name, var age) ->
262+ # "Minor user: " + name;
263+ # default -> "Unknown type";
264+ # };
265+ # }
266+ ]]>
267+ </example >
268+ </rule >
269+
270+ <rule >
271+ <title >Implement Efficient Development Workflow</title >
272+ <description >
273+ Create Docker configurations that support efficient development cycles and debugging capabilities.
274+ </description >
275+ <guidelines >
276+ <guideline >Use Docker Compose for local development environments</guideline >
277+ <guideline >Implement hot-reload capabilities for development</guideline >
278+ <guideline >Support remote debugging configurations</guideline >
279+ <guideline >Create separate profiles for development and production</guideline >
280+ <guideline >Use volume mounts for rapid iteration during development</guideline >
281+ </guidelines >
282+ <example >
283+ <![CDATA[
284+ # Development Dockerfile
285+ FROM eclipse-temurin:25-jdk-alpine AS development
286+ WORKDIR /app
287+ COPY pom.xml .
288+ RUN ./mvnw dependency:resolve
289+ VOLUME ["/app/src", "/app/target"]
290+ EXPOSE 8080 5005
291+ ENV JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
292+ CMD ["./mvnw", "spring-boot:run"]
293+
294+ # docker-compose.yml for development
295+ # version: '3.8'
296+ # services:
297+ # app:
298+ # build:
299+ # context: .
300+ # target: development
301+ # ports:
302+ # - "8080:8080"
303+ # - "5005:5005"
304+ # volumes:
305+ # - ./src:/app/src
306+ # - ./target:/app/target
307+ ]]>
308+ </example >
309+ </rule >
310+ </rules >
311+
312+ <anti_patterns >
313+ <anti_pattern >
314+ <title >Using Root User in Production</title >
315+ <description >Running applications as root user increases security risks</description >
316+ <example >USER root # AVOID THIS</example >
317+ </anti_pattern >
318+
319+ <anti_pattern >
320+ <title >Installing Unnecessary Packages</title >
321+ <description >Including development tools and unnecessary packages in production images</description >
322+ <example >RUN apk add --no-cache curl wget vim git # AVOID UNNECESSARY TOOLS</example >
323+ </anti_pattern >
324+
325+ <anti_pattern >
326+ <title >Hardcoding Configuration</title >
327+ <description >Embedding environment-specific configuration in Docker images</description >
328+ <example >ENV DATABASE_URL=prod.db.example.com # AVOID HARDCODING</example >
329+ </anti_pattern >
330+
331+ <anti_pattern >
332+ <title >Ignoring JVM Container Settings</title >
333+ <description >Not configuring JVM for container resource limits</description >
334+ <example >java -Xmx4g -jar app.jar # AVOID FIXED HEAP SIZES</example >
335+ </anti_pattern >
336+
337+ <anti_pattern >
338+ <title >Using Latest Tags in Production</title >
339+ <description >Using unstable or latest tags for base images in production</description >
340+ <example >FROM eclipse-temurin:latest # AVOID LATEST TAG</example >
341+ </anti_pattern >
342+ </anti_patterns >
343+
344+ <best_practices_summary >
345+ <practice >Use multi-stage builds with appropriate base images</practice >
346+ <practice >Configure JVM for container environments</practice >
347+ <practice >Implement security best practices with non-root users</practice >
348+ <practice >Optimize Docker layers and caching strategies</practice >
349+ <practice >Configure comprehensive health checks and monitoring</practice >
350+ <practice >Externalize configuration and manage secrets properly</practice >
351+ <practice >Leverage Java 25 specific features and improvements</practice >
352+ <practice >Support efficient development workflows</practice >
353+ </best_practices_summary >
354+ </cursor_rules >
0 commit comments