mirror of
https://github.com/docker/docs.git
synced 2026-04-05 10:48:55 +07:00
The build guide that I once wrote now duplicates a lot of content with the concept guide launched a few months back. It doesn't make sense to cover the same topics multiple times, so I'm removing the older build guide and incorporating some of the topics into the build manual instead. Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
122 lines
4.6 KiB
Markdown
122 lines
4.6 KiB
Markdown
---
|
||
title: Run your Java tests
|
||
keywords: Java, build, test
|
||
description: How to build and run your Java tests
|
||
---
|
||
|
||
## Prerequisites
|
||
|
||
Complete all the previous sections of this guide, starting with [Containerize a Java application](containerize.md).
|
||
|
||
## Overview
|
||
|
||
Testing is an essential part of modern software development. Testing can mean a lot of things to different development teams. There are unit tests, integration tests and end-to-end testing. In this guide you'll take a look at running your unit tests in Docker.
|
||
|
||
### Multi-stage Dockerfile for testing
|
||
|
||
In the following example, you'll pull the testing commands into your Dockerfile.
|
||
Replace the contents of your Dockerfile with the following.
|
||
|
||
```dockerfile {hl_lines="3-19"}
|
||
# syntax=docker/dockerfile:1
|
||
|
||
FROM eclipse-temurin:17-jdk-jammy as base
|
||
WORKDIR /build
|
||
COPY --chmod=0755 mvnw mvnw
|
||
COPY .mvn/ .mvn/
|
||
|
||
FROM base as test
|
||
WORKDIR /build
|
||
COPY ./src src/
|
||
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
|
||
--mount=type=cache,target=/root/.m2 \
|
||
./mvnw test
|
||
|
||
FROM base as deps
|
||
WORKDIR /build
|
||
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
|
||
--mount=type=cache,target=/root/.m2 \
|
||
./mvnw dependency:go-offline -DskipTests
|
||
|
||
FROM deps as package
|
||
WORKDIR /build
|
||
COPY ./src src/
|
||
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
|
||
--mount=type=cache,target=/root/.m2 \
|
||
./mvnw package -DskipTests && \
|
||
mv target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar target/app.jar
|
||
|
||
FROM package as extract
|
||
WORKDIR /build
|
||
RUN java -Djarmode=layertools -jar target/app.jar extract --destination target/extracted
|
||
|
||
FROM extract as development
|
||
WORKDIR /build
|
||
RUN cp -r /build/target/extracted/dependencies/. ./
|
||
RUN cp -r /build/target/extracted/spring-boot-loader/. ./
|
||
RUN cp -r /build/target/extracted/snapshot-dependencies/. ./
|
||
RUN cp -r /build/target/extracted/application/. ./
|
||
ENV JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000"
|
||
CMD [ "java", "-Dspring.profiles.active=postgres", "org.springframework.boot.loader.launch.JarLauncher" ]
|
||
|
||
FROM eclipse-temurin:17-jre-jammy AS final
|
||
ARG UID=10001
|
||
RUN adduser \
|
||
--disabled-password \
|
||
--gecos "" \
|
||
--home "/nonexistent" \
|
||
--shell "/sbin/nologin" \
|
||
--no-create-home \
|
||
--uid "${UID}" \
|
||
appuser
|
||
USER appuser
|
||
COPY --from=extract build/target/extracted/dependencies/ ./
|
||
COPY --from=extract build/target/extracted/spring-boot-loader/ ./
|
||
COPY --from=extract build/target/extracted/snapshot-dependencies/ ./
|
||
COPY --from=extract build/target/extracted/application/ ./
|
||
EXPOSE 8080
|
||
ENTRYPOINT [ "java", "-Dspring.profiles.active=postgres", "org.springframework.boot.loader.launch.JarLauncher" ]
|
||
```
|
||
|
||
First, you added a new base stage. In the base stage, you added common instructions that both the test and deps stage will need.
|
||
|
||
Next, you added a new test stage labeled `test` based on the base stage. In this
|
||
stage you copied in the necessary source files and then specified `RUN` to run
|
||
`./mvnw test`. Instead of using `CMD`, you used `RUN` to run the tests. The
|
||
reason is that the `CMD` instruction runs when the container runs, and the `RUN`
|
||
instruction runs when the image is being built. When using `RUN`, the build will
|
||
fail if the tests fail.
|
||
|
||
Finally, you updated the deps stage to be based on the base stage and removed
|
||
the instructions that are now in the base stage.
|
||
|
||
Run the following command to build a new image using the test stage as the target and view the test results. Include `--progress=plain` to view the build output, `--no-cache` to ensure the tests always run, and `--target-test` to target the test stage.
|
||
|
||
Now, build your image and run your tests. You'll run the `docker build` command and add the `--target test` flag so that you specifically run the test build stage.
|
||
|
||
```console
|
||
$ docker build -t java-docker-image-test --progress=plain --no-cache --target=test .
|
||
```
|
||
|
||
You should see output containing the following
|
||
```console
|
||
...
|
||
|
||
#15 101.3 [WARNING] Tests run: 45, Failures: 0, Errors: 0, Skipped: 2
|
||
#15 101.3 [INFO]
|
||
#15 101.3 [INFO] ------------------------------------------------------------------------
|
||
#15 101.3 [INFO] BUILD SUCCESS
|
||
#15 101.3 [INFO] ------------------------------------------------------------------------
|
||
#15 101.3 [INFO] Total time: 01:39 min
|
||
#15 101.3 [INFO] Finished at: 2024-02-01T23:24:48Z
|
||
#15 101.3 [INFO] ------------------------------------------------------------------------
|
||
#15 DONE 101.4s
|
||
```
|
||
|
||
## Next steps
|
||
|
||
In the next section, you’ll take a look at how to set up a CI/CD pipeline using
|
||
GitHub Actions.
|
||
|
||
{{< button text="Configure CI/CD" url="configure-ci-cd.md" >}}
|