Dockerfile中Nexus制品与构建指令的最佳实践咨询
Great question! Since you’re already comfortable with the traditional Java/Maven/Nexus workflow, transitioning to Docker will feel intuitive once you map those existing steps to containerized builds. Here are my go-to best practices tailored exactly to your use case:
This is the single most impactful practice for Java Docker images. It separates your build environment (with JDK, Maven, build tools) from your runtime environment (only JRE or slimmed-down runtime), drastically reducing image size and attack surface.
For your workflow, this means:
- First stage: Use a Maven base image to pull dependencies from Nexus, build your
.war, and generate the artifact. - Second stage: Copy only the built
.warinto a lightweight JRE or Tomcat image (no build tools included).
Example Dockerfile snippet:
# Build stage - handles compilation and dependency resolution FROM maven:3.8.6-openjdk-17 AS builder # Copy your Maven settings to point to your internal Nexus repo COPY settings.xml /root/.m2/settings.xml # Copy pom.xml first to leverage Docker's layer caching COPY pom.xml /app/ WORKDIR /app # Pre-download dependencies (cached as long as pom.xml doesn't change) RUN mvn dependency:go-offline # Copy source code and build the war COPY src /app/src RUN mvn package -DskipTests # Runtime stage - minimal image for running the app FROM eclipse-temurin:17-jre-alpine # If using Tomcat, you could use `tomcat:10-jre-slim` instead RUN apk add --no-cache tomcat-native # Copy the built war from the builder stage COPY --from=builder /app/target/your-app.war /usr/local/tomcat/webapps/ROOT.war # Create a non-root user to run the container (security best practice) RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser EXPOSE 8080 CMD ["catalina.sh", "run"]
Docker caches layers, so we can use this to avoid re-downloading Nexus dependencies every time you change source code. The key is to:
- Copy your
pom.xml(andsettings.xmlfor Nexus) before copying your source code. - Run
mvn dependency:go-offlineto pre-fetch all dependencies into the cache layer.
This way, only changes to pom.xml will trigger a full dependency pull—source code changes will reuse the cached dependencies, cutting down build time significantly.
If you already have a pipeline that builds the .war and pushes it to Nexus’s release directory, you don’t need to rebuild the app in Docker. Instead, pull the artifact directly from Nexus in your Dockerfile:
Example for pulling a pre-built war:
FROM eclipse-temurin:17-jre-alpine # Define build arguments for flexibility (easily swap versions/envs) ARG NEXUS_ARTIFACT_URL=http://your-nexus-server/repository/releases/com/your-org/your-app/1.0.0/your-app-1.0.0.war ARG ENVIRONMENT=dev # Install curl to pull the artifact (Alpine uses apk) RUN apk add --no-cache curl # Pull the war from Nexus RUN curl -o /usr/local/tomcat/webapps/ROOT.war ${NEXUS_ARTIFACT_URL} # Copy environment-specific config (matches your dev/qa/prod setup) COPY config/${ENVIRONMENT}/application.properties /usr/local/tomcat/webapps/ROOT/WEB-INF/classes/ # Non-root user setup RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser EXPOSE 8080 CMD ["catalina.sh", "run"]
Use ARG to pass in the Nexus URL and environment—this lets you reuse the same Dockerfile for dev, qa, and prod by just changing the build arguments.
Avoid heavy base images like full JDKs or bloated Tomcat distributions. Instead:
- Use slimmed-down JRE images like
eclipse-temurin:17-jre-alpineoropenjdk:17-jre-slim. - If using Tomcat, opt for
tomcat:10-jre-sliminstead of the default full image. - Remove unnecessary packages (Alpine’s
apk add --no-cachehelps with this).
Smaller images mean faster pulls, less storage usage, and fewer security vulnerabilities.
Just like your traditional workflow, don’t hardcode dev/qa/prod settings into the Docker image. Instead:
- Use
ARGandENVvariables to inject config at build or runtime. - Mount config files from a volume or config map when deploying (ideal for Kubernetes/Docker Swarm).
- Copy environment-specific configs into the image at build time (as shown in the Nexus artifact example) if you prefer image-per-environment.
This keeps your base image consistent across environments while allowing for environment-specific tweaks.
- Run containers as a non-root user: Create a dedicated user in your Dockerfile (as shown in examples) to avoid running apps with root privileges.
- Don’t hardcode secrets: If Nexus requires authentication, use Docker build secrets or CI/CD secrets managers instead of writing credentials into your Dockerfile.
- Scan images for vulnerabilities: Use tools like Trivy or Docker Scan to check for outdated packages in your base images.
You don’t need to overhaul your current workflow—just add a Docker step:
- Keep your existing pipeline that builds the
.warand pushes it to Nexus. - Add a stage that uses your Dockerfile to build the image (either by pulling the Nexus artifact or running the Maven build in the first stage).
- Push the Docker image to your container registry (like Docker Hub, AWS ECR, or a private registry).
- Deploy the image to dev/qa/prod using your existing deployment tools.
This way, you leverage your existing investments in Maven, Nexus, and config management while adding containerization benefits.
内容的提问来源于stack exchange,提问作者mritprofessional1

