Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Windows Tipps & SecurityDave Plummer Has Made the Task Manager of Your Dreams(21.09.2026 um 21:20 Uhr)
Sichere ProgrammierungSubqueries and CTEs: Asking a Question Inside a Question(21.09.2026 um 21:00 Uhr)
Sichere ProgrammierungTVL Trend Analysis & Liquidity Risk Assessment: Lido(21.09.2026 um 21:00 Uhr)
Sichere ProgrammierungReact is Officially Dead in 2026 (Thanks to AI)(21.09.2026 um 21:01 Uhr)
Sichere ProgrammierungUsing SHA256 to Build Trustworthy Data Portals in Brazil(21.09.2026 um 21:01 Uhr)
Sichere Programmierung🚀 I reached 1,001 views on DEV!(21.09.2026 um 21:03 Uhr)
Sichere ProgrammierungReact Mental Models 2(21.09.2026 um 21:05 Uhr)
Sichere ProgrammierungAustralian RAM and SSD prices climb as stock tightens(21.09.2026 um 21:09 Uhr)
Windows Tipps & SecurityDave Plummer Has Made the Task Manager of Your Dreams(21.09.2026 um 21:20 Uhr)
Sichere ProgrammierungSubqueries and CTEs: Asking a Question Inside a Question(21.09.2026 um 21:00 Uhr)
Sichere ProgrammierungTVL Trend Analysis & Liquidity Risk Assessment: Lido(21.09.2026 um 21:00 Uhr)
Sichere ProgrammierungReact is Officially Dead in 2026 (Thanks to AI)(21.09.2026 um 21:01 Uhr)
Sichere ProgrammierungUsing SHA256 to Build Trustworthy Data Portals in Brazil(21.09.2026 um 21:01 Uhr)
Sichere Programmierung🚀 I reached 1,001 views on DEV!(21.09.2026 um 21:03 Uhr)
Sichere ProgrammierungReact Mental Models 2(21.09.2026 um 21:05 Uhr)
Sichere ProgrammierungAustralian RAM and SSD prices climb as stock tightens(21.09.2026 um 21:09 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Build Better Containers🐳

🎯 Objectives Demonstrate how to containerize a backend application using Docker Highlight common pitfalls and best practices in Dockerfile creation Showcase multi-stage builds for leaner, production-ready images Implement secure co…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




🎯 Objectives




  • Demonstrate how to containerize a backend application using Docker

  • Highlight common pitfalls and best practices in Dockerfile creation

  • Showcase multi-stage builds for leaner, production-ready images

  • Implement secure containerization techniques (non-root users, minimal base images)

  • Optimize build performance with caching and artifact strategies

  • Ensure reproducibility and clarity for CI/CD integration






Why Containerization Isn’t Enough



Containerizing an application is often seen as a checkbox task—docker build, docker run, and you're done. But in production environments, bloated images, insecure defaults, and slow builds can lead to:




  • Longer CI/CD cycles

  • Vulnerability exposure

  • Poor reproducibility across environments

  • Optimizing your Dockerfile is not just a performance tweak—it's a security and reliability upgrade.






Containerize the Application



A container is a standardized unit of software development that holds everything that your software application requires to run. This includes relevant code, runtime, system tools, and system libraries.



Containers are created from a read-only template called a container image . Images are typically built from a Dockerfile. A Dockerfile is a plaintext file that specifies all the components that are included in the container.



Let’s start with a basic Java Spring Boot app. A naive Dockerfile might look like this:




FROM openjdk:17
COPY target/app.jar /app.jar
CMD ["java", "-jar", "/app.jar"]






This works, but it’s:




  • Heavy: The base image is large

  • Insecure: Runs as root by default

  • Opaque: No build separation or caching






Starting Point: First Version (Basic)



Here's a basic first version of a Dockerfile with slim Alpine variants eclipse-temurin base image for a Maven-based Java application — it's functional, but not optimized. This is often what developers start with before applying best practices:




FROM eclipse-temurin:17-jdk-alpine

WORKDIR /app

COPY . .

RUN mvn clean package

CMD ["java", "-jar", "target/app.jar"]














Optimizing the Dockerfile






✅ Add a .dockerignore File



A .dockerignore file works like .gitignore, preventing specified files from being sent to the Docker daemon during build. This speeds up builds and prevents sensitive files from being included in your image.




target/
.git
.idea/
*.iml
*.log
*.md
*.bak










✅ Step 1: Use Multi-Stage Build



Multi-stage builds let you use one image for building (with all build tools) and another for running your application. This results in significantly smaller production images and improved security by not including build tools in the final image.




# -------- Stage 1: Build with Maven--------

# Use Eclipse Temurin JDK 17 with Alpine Linux
FROM eclipse-temurin:17-jdk-alpine AS builder

# Set working directory
WORKDIR /app

# Copy pom.xml and maven wrapper download dependencies
COPY ./pom.xml ./pom.xml
COPY ./mvnw ./mvnw
COPY ./.mvn ./.mvn

# Make Maven wrapper executable and download dependencies
RUN chmod +x ./mvnw && ./mvnw dependency:go-offline

# Copy source files and build
COPY src ./src/

# Build the application
RUN ./mvnw clean package -DskipTests && mv target/docker-demo-0.0.1-exec.jar docker-demo.jar
RUN rm -rf target







🔨 Stage Declaration




  • Uses Eclipse Temurin JDK 17 with Alpine Linux for minimal footprint

  • Names this stage builder for reference in later stages

  • Alpine is lightweight but requires manual setup for tools like Maven



📦 Maven Execution




  • - chmod +x ./mvnw


    • Purpose: Grants execute permission to the Maven Wrapper script (mvnw).

    • When copying files into a Docker container, file permissions may not be preserved.

    • mvnw ensures a consistent Maven version without requiring the user or CI to have Maven pre-installed






  • ./mvnw dependency:go-offline


    • Purpose: Pre-downloads all project dependencies, plugins, and transitive dependencies to the local .m2 repository.








📁 Working Directory Setup




  • Sets /app as the working directory

  • All subsequent paths are relative to this location



⚡ Dependency Optimization




  • Copies only the pom.xml first—before source code

  • Downloads all dependencies using mvn dependency:go-offline

  • Benefit: Docker layer caching ensures dependencies aren’t re-downloaded unless pom.xml changes



🧪 Source Code & Build




  • Copies the source code

  • Builds the application, skipping tests for faster CI builds

  • Renames the JAR for simplicity

  • Removes the target directory to reduce image size






✅ Step 2: Use Lightweight Runtime Image



Reduce image size and attack surface. The final image is much smaller and doesn't include Maven or source code.




# -------- Stage 2: Runtime --------

FROM eclipse-temurin:17-jre-alpine AS runtime










✅ Step 3: COPY Artifacts in Multi-Stage Builds



This line is a key part of a multi-stage Dockerfile, used to transfer the compiled Spring Boot application from the build stage to the runtime stage.





# Copy built JAR from builder stage
COPY --from=builder /app/docker-demo.jar docker-demo.jar







This command is executed in Stage 2 of a multi-stage build:




  • Stage 1 (builder): Uses Maven to compile the Java application and produce a JAR

  • Stage 2 (runtime): Uses a lightweight JRE base image to run the application



The JAR is copied from the builder stage into the runtime stage for execution




  • COPY: Docker instruction to copy files or directories

  • --from=builder: Specifies the source stage (builder) defined earlier

  • /app/docker-demo.jar: Source path in the builder stage

  • docker-demo.jar: Destination path in the current stage (relative to WORKDIR /app)






✅ Step 4: Run as Non-Root User



Running containers as root is a security risk. Create a non-privileged user and switch to it before running your application. This limits the potential damage if your container is compromised.




# Define build arguments for user and group
ARG USER_ID=1001
ARG GROUP_ID=1001
ARG USERNAME=springuser
ARG GROUPNAME=springuser

# Create group and user using ARGs
RUN addgroup -g ${GROUP_ID} ${GROUPNAME} \
&& adduser -u ${USER_ID} -G ${GROUPNAME} -s /bin/sh -D ${USERNAME}

# Change ownership
RUN chown -R ${USERNAME}:${GROUPNAME} /app


# Switch to non-root user
USER ${USERNAME}







⚙️ Build Arguments Definition




  • These ARG instructions define build-time variables with default values:

  • USER_ID=1001: Numeric user ID

  • GROUP_ID=1001: Numeric group ID

  • USERNAME=springuser: User account name

  • GROUPNAME=springuser: Group name

  • 🔧 These can be overridden at build time using --build-arg flags for flexibility across environments.



👤 User and Group Creation



This command creates a secure user and group in Alpine Linux:

addgroup: Creates a group with the specified GID

adduser:




  • -u: Sets the user ID

  • -G: Adds user to the group

  • -s /bin/sh: Sets shell

  • -D: Creates a system user without a password



🏷️ Ownership Change

Uses chown to change ownership of /app and all its contents

-R: Applies changes recursively to subdirectories and files

${USERNAME}:${GROUPNAME}: Sets ownership using build-time arguments (defaults to springuser:springuser)



Ensures the non-root user has read/write access to the application directory—including the JAR copied from the builder stage.



👤 Switch to Non-Root User




  • Changes the execution context from root to the specified user

  • All subsequent instructions (including CMD or ENTRYPOINT) will run as springuser



By running your Spring Boot application as springuser instead of root, you significantly reduce the attack surface and improve container isolation.





✅ Step 5: Set ENTRYPOINT and Optional HEALTHCHECK



ENTRYPOINT defines the executable that runs when the container starts, while CMD provides default arguments to that executable. Using them together makes your containers more flexible and user-friendly.




# Expose application port
EXPOSE 8080

# Alternative using wget (no additional package needed)
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1

ENTRYPOINT ["java","-jar","-Dserver.port=8080","/app/docker-demo.jar"]







🌐 Port Exposure




  • the container listens on port 8080

  • Important: This does not publish the port—use -p 8080:8080 when running the container to map it to the host

  • Useful for tooling and orchestration platforms to understand expected traffic ports



❤️ Health Check Configuration

This directive sets up a health probe using Spring Boot’s Actuator endpoint:




  • --interval=30s: Runs every 30 seconds

  • --timeout=10s: Each check times out after 10 seconds

  • --start-period=60s: Waits 60 seconds before starting checks (allows app startup)

  • --retries=3: Marks container unhealthy after 3 consecutive failures



The command:




  • Uses wget with --spider to check endpoint accessibility without downloading content

  • Fails with exit 1 if the health endpoint is unreachable



Ensures the container is only marked healthy when the application is responsive.



🚀 Entrypoint Configuration



Defines the command that runs when the container starts:




  • java -jar: Executes the Spring Boot application

  • -Dserver.port=8080: Explicitly sets the server port

  • /app/docker-demo.jar: Path to the packaged JAR file







✅ Final Optimized Dockerfile





# -------- Stage 1: Build with Maven--------

# Use Eclipse Temurin JDK 17 with Alpine Linux
FROM eclipse-temurin:17-jdk-alpine AS builder

# Set working directory
WORKDIR /app

# Copy pom.xml and maven wrapper download dependencies
COPY ./pom.xml ./pom.xml
COPY ./mvnw ./mvnw
COPY ./.mvn ./.mvn

# Make Maven wrapper executable and download dependencies
RUN chmod +x ./mvnw && ./mvnw dependency:go-offline

# Copy source files and build
COPY src ./src/

# Build the application
RUN ./mvnw clean package -DskipTests && mv target/docker-demo-0.0.1-exec.jar docker-demo.jar
RUN rm -rf target

# -------- Stage 2: Runtime --------

FROM eclipse-temurin:17-jre-alpine AS runtime

# Set the working directory and make it writable by the non-root user
WORKDIR /app

# Copy built JAR from builder stage
COPY --from=builder /app/docker-demo.jar docker-demo.jar

# Define build arguments for user and group
ARG USER_ID=1001
ARG GROUP_ID=1001
ARG USERNAME=springuser
ARG GROUPNAME=springuser

# Create group and user using ARGs
RUN addgroup -g ${GROUP_ID} ${GROUPNAME} \
&& adduser -u ${USER_ID} -G ${GROUPNAME} -s /bin/sh -D ${USERNAME}

# Change ownership
RUN chown -R ${USERNAME}:${GROUPNAME} /app

# Switch to non-root user
USER ${USERNAME}

# Expose application port
EXPOSE 8080

# Alternative using wget (no additional package needed)
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1

ENTRYPOINT ["java","-jar","-Dserver.port=8080","/app/docker-demo.jar"]








Check size of the image, it is about 300 MB:









Layered JARs & Build pack support



layered JARs, which split your fat JAR into logical layers:





Why It Helps with Docker

Docker caches layers. So when you rebuild your app:



Without layers: Any change (even a single line of code) forces a full image rebuild.



With layers: Only the application layer changes. The rest are cached.



Benefits:




  • Faster rebuilds in CI/CD pipelines

  • Smaller incremental pushes to registries

  • Improved startup time (especially with lazy class loading)



How to Use It




<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>







Then use layertools to inspect or extract layers:




java -Djarmode=layertools -jar target/{your-jar-name}.jar extract







You get:



/app

├── dependencies/

├── snapshot-dependencies/

├── spring-boot-loader/ ✅ contains JarLauncher.class

├── application/



Dockerfile(without good practice ):




# Use multi-stage build
FROM eclipse-temurin:17-jdk-alpine AS builder
# Set working directory
WORKDIR /app
# Copy pom.xml and maven wrapper to download dependencies
COPY ./pom.xml ./pom.xml
COPY ./mvnw ./mvnw
COPY ./.mvn ./.mvn
RUN chmod +x ./mvnw && ./mvnw dependency:go-offline
# Copy source files and build
COPY src ./src/
RUN ./mvnw clean package -DskipTests
# Extract layered JAR using layertools (fixed JAR filename)
RUN java -Djarmode=layertools -jar target/docker-demo-0.0.1.jar extract
# Clean up Maven repository to reduce image size
RUN rm -rf ~/.m2/repository

# Runtime stage
FROM eclipse-temurin:17-jre-alpine AS runtime
WORKDIR /app
# Copy layers from the builder stage
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]







Check size of the image, it is about 240 MB:

Layered JARs do not directly reduce the total image size, but they optimize your Docker images in smarter ways.







Buildpack support provides the Java runtime for the application, so it’s now possible to skip the Dockerfile and build the Docker image automatically



✅ 1. Build the Image




./mvnw spring-boot:build-image -DskipTests






Spring Boot uses Paketo Buildpacks by default and creates a Docker image locally.



✅ 2. Run the Image




docker run -p 8080:8080 my-app:0.0.1-SNAPSHOT






✅ 3. Customize the Build Image (Optional)

Use environment variables or configuration:




./mvnw spring-boot:build-image \
-Dspring-boot.build-image.imageName=my-org/my-app \
-Dspring-boot.build-image.builder=paketobuildpacks/builder:tiny \
-Dspring-boot.build-image.env.BP_JVM_VERSION=17






Security & Production Readiness




  • Paketo buildpacks ensure:

  • No root user by default

  • Minimal base OS (Tiny <50MB)

  • Regular vulnerability scans (via CVEs)

  • JVM flags optimized for container environments






Head-to-Head Comparison











How to further reduce image size, even if you're already following best practices like multi-stage builds and slim base images?



Here’s how to further reduce image size, even if you're already following best practices like multi-stage builds and slim base images:






1. Custom Runtime Footprint- jlink Custom Java Runtime



Instead of using a full JRE (even slim ones), you can generate a minimal JRE with only the required Java modules using jlink.




  • Uses Eclipse Temurin JDK 17 as the base image (needed for the jdeps and jlink tools)

  • Names this stage jre-builder for reference in later stages

  • Sets the working directory to /app

  • Copies the compiled JAR file from Stage 1 (builder stage)

  • Creates a target directory and extracts the JAR contents using jar -xf

  • This extraction is necessary because Spring Boot creates "fat JARs" with dependencies in BOOT-INF/lib/



jdeps is a Java dependency analysis tool that identifies which JDK modules are actually used




  • --ignore-missing-deps: Ignores missing dependencies (common with Spring Boot fat JARs)

  • --multi-release 17: Analyzes for Java 17 multi-release JAR support

  • --print-module-deps: Outputs only the required module names

  • --class-path: Points to the extracted dependencies in BOOT-INF/lib/

  • The output (list of required modules) is saved to jre-deps.text



jlink creates a custom JRE containing only the modules identified by jdeps




  • --add-modules $(cat jre-deps.text): Includes only the necessary modules from the analysis

  • --compress=2: Applies maximum compression to reduce size

  • --strip-debug: Removes debug information

  • --no-header-files and --no-man-pages: Excludes unnecessary files

  • --output /opt/jre: Creates the custom JRE in /opt/jre



This stage significantly reduces the final Docker image size by creating a minimal JRE that contains only the Java modules actually needed by the Spring Boot application, rather than including the entire JDK or standard JRE.




# ---------- Stage 2: Analyze dependencies with jdeps ----------

FROM eclipse-temurin:17-jdk-alpine AS jre-builder

WORKDIR /app

# Copy fat jar from builder stage
COPY --from=builder /app/docker-demo.jar docker-demo.jar

# Unpack the jar to inspect contents
RUN mkdir target && cd target && cp ../docker-demo.jar docker-demo.jar && jar -xf ../docker-demo.jar

# jdeps is a Java dependency analysis tool. We are printing the module
# dependencies of our application and its libraries.
# The --ignore-missing-deps flag is useful for Spring Boot fat JARs as it may
# report some non-module-system dependencies as missing.
# The output is piped to a file that will be used by jlink.
RUN jdeps --ignore-missing-deps \
--multi-release 17 --print-module-deps \
--class-path="target/BOOT-INF/lib/*" \
target/docker-demo.jar > jre-deps.text

# 3. Create a custom JRE
RUN jlink \
--add-modules $(cat jre-deps.text) \
--compress=2 \
--strip-debug \
--no-header-files \
--no-man-pages \
--output /opt/jre







Stage 3: Runtime



Creates a new build stage named "runtime" using Alpine Linux 3.20 as the base image




  • Alpine is chosen because it's extremely lightweight (~5MB), making it ideal for production runtime containers

  • This is the final stage that will become the actual container image


  • Copies the custom Java Runtime Environment (JRE) from the previous stage (jre-builder)


  • The --from=jre-builder flag specifies the source stage in this multi-stage build


  • This custom JRE was created using jlink in stage 2 and contains only the Java modules needed by the application


  • By using a custom JRE instead of a full JDK, the final image size is significantly reduced





FROM alpine:3.20 AS runtime

# Set the working directory and make it writable by the non-root user
WORKDIR /app

# Copy custom JRE from previous stage
COPY --from=jre-builder /opt/jre /opt/jre

# Copy built JAR from builder stage
COPY --from=builder /app/docker-demo.jar docker-demo.jar

ENTRYPOINT ["/opt/jre/bin/java","-jar","-Dserver.port=8080","/app/docker-demo.jar"]









Check size of the image, it is about 184 MB:







2. Dockerfile for GraalVM Native Image



GraalVM is a high-performance JIT (Just-In-Time) and AOT (Ahead-of-Time) compiler that enables Java applications to be compiled into native code.

They are well suited to applications that are deployed using container images and are especially interesting when combined with "Function as a service" (FaaS) platforms.




A GraalVM Native Image is a complete, platform-specific executable. You do not need to ship a Java Virtual Machine in order to run a native image.




Key Advantages of GraalVM:




  • ✅ Instant startup time — Runs natively without requiring a JVM!

  • ✅ Lower memory consumption — Uses significantly less RAM compared to the traditional JVM.

  • ✅ Smaller Docker containers — Ideal for cloud-native architectures.

  • ✅ Enhanced security — Eliminates unnecessary runtime components, reducing the attack surface.



Key Differences with JVM Deployments

The fact that GraalVM Native Images are produced ahead-of-time means that there are some key differences between native and JVM based applications. The main differences are:




  • Static analysis of your application is performed at build-time from the main entry point.

  • Code that cannot be reached when the native image is created will be removed and won’t be part of the executable.

  • GraalVM is not directly aware of dynamic elements of your code and must be told about reflection, resources, serialization, and dynamic proxies.

  • The application classpath is fixed at build time and cannot change.

  • There is no lazy class loading, everything shipped in the executables will be loaded in memory on startup.

  • There are some limitations around some aspects of Java applications that are not fully supported.



Why Is GraalVM Native Build Slow?




  • Heavy Static Analysis GraalVM performs deep static analysis to eliminate unused code and handle reflection, proxies, and dynamic features. This takes time.

  • No Runtime Profiling by Default Unlike JIT, GraalVM AOT lacks runtime profiling unless you use Profile-Guided Optimization (PGO).

  • Large Classpath Spring Boot apps often pull in dozens of libraries (JPA, Web, Security), which bloats the analysis phase.

  • Reflection & Dynamic Proxies These require manual configuration or tracing via native-image-agent, which adds build overhead.

  • Native image compilation is very memory-intensive (can use several GBs of RAM).



The -Pnative profile is used to generate a native executable for your platform. This will generate a native executable called docker-demo in the target/ directory.





Add native-maven-plugin in pom.xml file




<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.10.6</version>
<extensions>true</extensions>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>









Dockerfile:




# STAGE 1: Builder - Note- latest is error prone
FROM ghcr.io/graalvm/graalvm-ce:latest AS builder

# Install native-image component
RUN gu install native-image

# Set working directory
WORKDIR /app

# Copy pom.xml and maven wrapper download dependencies
COPY ./pom.xml ./pom.xml
COPY ./mvnw ./mvnw
COPY ./.mvn ./.mvn

# Make maven wrapper executable
RUN chmod +x ./mvnw

RUN ./mvnw dependency:go-offline -B

# Copy source files and build
COPY src ./src/

# Build the application
RUN ./mvnw package -Pnative -Dquarkus.container-image.build=false -DskipTests

FROM alpine:3.20 AS runtime

WORKDIR /app

# Create non-root user
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup \

COPY --from=builder /app/target/docker-demo ./app

RUN chmod +x ./app

USER appuser
# Expose application port
EXPOSE 8080
CMD ["./app"]






Tip :




If you want to go native please look at Quarkus. It was built with native in mind. Porting an existing Springboot app to Spring native is a lot of trial and error. Spring relies heavily on reflection and AOP, while GraalVM is all about having everything ready at compile time.










Common Pitfalls in Dockerfile Creation



Here’s a curated list of common pitfalls in Dockerfile creation, especially relevant for backend engineers and DevOps professionals working with CI/CD pipelines and production-grade containers.




  • Using a large base image


    • Problem: Increases image size and build time.

    • ❌ FROM openjdk:17

    • ✅ Use slim or Alpine variants (eclipse-temurin:17-jdk-alpine, eclipse-temurin:17-jre)






  • Installing unnecessary packages


    • Problem: Leads to bloated images and potential security

    • ✅Install only required packages with --no-install-recommends
      vulnerabilities.






  • Failing to use multi-stage builds


    • Problem: Development tools remain in the final image.

    • ❌ Build tools and source code included in final image

    • ✅ Separate build and runtime stages






  • Ignoring layer caching


    • ❌ Forces Maven to re-download dependencies and rebuild everything.









COPY . .
RUN mvn clean install







  • ✅ Order COPY and RUN to isolate stable steps (e.g., dependencies first)




# Copy only dependency-related files first
COPY pom.xml ./
RUN mvn dependency:go-offline
# Then copy the rest of the source
COPY src/ ./src/
RUN mvn clean package








  • Using latest tag for base images




    • Problem: Builds can break due to unexpected updates.

    • ❌ FROM node:latest

    • ✅ Pin exact versions (FROM node:18.16.0)








  • Running as Root




    • Unnecessary Privileges and Security Vulnerability

    • ❌ Default user is root

    • ✅ Create and switch to a non-root user (USER appuser)








  • Not specifying a working directory




    • Problem: Commands may run in unexpected directories.

    • ✅ Use WORKDIR /app before COPY or RUN








  • Not cleaning up temporary files




    • Problem: Increases image size.

    • ✅ Delete temp files (rm -rf /tmp/, /build/) after use








  • Not Using .dockerignore




    • ❌ Sending unnecessary files (e.g., .git, target/, node_modules/)

    • ✅ Add a .dockerignore file








  • Missing Health Checks




    • ❌ No visibility into container health

    • ✅ Use HEALTHCHECK with /actuator/health or similar








  • Hardcoding secrets




    • ✅Inject secrets via CI/CD or use secret managers.











References



💡 Buildpacks & Spring Boot Integration — Spring Boot Documentation

🧠 AI Assistance — Content and explanations are partially supported by ChatGPT, Microsoft Copilot, and GitLab Duo, following Spring Boot and Docker best practices and OCI standards.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Build Better Containers🐳

Thematisch verwandte Begriffe: Build, Better, Containers · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94494 | jshERP through 3.6 contains a tenant isolation bypass vulnerability that…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick