Running test with testcontainers as part of a Dockerfile - java

My dockerfile looks something like this:
FROM maven:3-jdk-11-slim
COPY pom.xml .
COPY src src
RUN mvn clean install
That means that part of the build is the execution of the unit tests. Some of the unit tests use a testcontainer. Running mvn clean install on my local machine works fine, but running docker build . -t my-app doesn't because the testcontainers won't start.
(...)
15:54:38.793 [ducttape-0] DEBUG org.testcontainers.dockerclient.DockerClientProviderStrategy - Pinging docker daemon...
15:54:38.794 [ducttape-0] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: org.testcontainers.dockerclient.transport.okhttp.OkHttpDockerCmdExecFactory$1#355cb260
15:54:39.301 [ducttape-0] DEBUG org.testcontainers.dockerclient.DockerClientProviderStrategy - Pinging docker daemon...
15:54:39.301 [ducttape-0] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: org.testcontainers.dockerclient.transport.okhttp.OkHttpDockerCmdExecFactory$1#1c1a1359
15:54:39.469 [main] ERROR org.testcontainers.dockerclient.EnvironmentAndSystemPropertyClientProviderStrategy - ping failed with configuration Environment variables, system properties and defaults. Resolved dockerHost=unix:///var/run/docker.sock due to org.rnorth.ducttape.TimeoutException: Timeout waiting for result with exception
org.rnorth.ducttape.TimeoutException: Timeout waiting for result with exception
(...)
I've seen examples of running docker run with working testcontainers, but how do I make my docker build work?
Help is much appreciated.

For future reference: I believe this is simply not possible.
docker run allows you to mount the Docker socket (and thus access the host's Docker daemon) with -v /var/run/docker.sock:/var/run/docker.sock.
docker build doesn't support such an argument.
My workaround will be to modify my Dockerfile to
RUN mvn clean install -Dmaven.test.skip=true and run the unit tests separately.

In the docker file, you need to have docker installed to run TestContainer.
I have learned this from one of the existing projects in my workplace. hopefully, it can give you some hints to solve your problem.
RUN curl -fsSL get.docker.com | sh
RUN curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose
In the docker-compose file,
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /mnt/cachedata/.m2:/root/.m2
- .:/app

Related

How to prevent docker java spring boot application exited after scheduled task completed?

I have a Java Spring Boot Application which contains controller endpoints and a scheduled task. Scheduled task is scheduled for every midnight. I use docker-compose up -d for this application and it runs without issue.
However, after scheduled task completed docker image exited with code 1 and without any error log. I think docker thinks process is completed after scheduled task but since it is also used as a web application, it is not supposed to exit.
Is there anyway to prevent docker image exit after scheduled task completed?
Here is my DockerFile:
FROM maven:3.6.3-jdk-11-slim AS MAVEN_BUILD
#FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD FOR JAVA 8
ARG SPRING_ACTIVE_PROFILE
MAINTAINER bugurs
COPY pom.xml /build/
COPY src /build/src/
WORKDIR /build/
RUN mvn clean install && mvn package -B -e
FROM openjdk:11-slim
#FROM openjdk:8-alpine FOR JAVA 8
WORKDIR /app
EXPOSE 8000
COPY --from=MAVEN_BUILD /build/target/*.jar /app/appdemo.jar
ENTRYPOINT ["java", "-jar", "appdemo.jar"]
if your app is springboot based then it wont exist using below dockerfile but if its simple java program then you have keep it alive may be infinite looping till process get kill signal .
Dockerfile
COPY ./startApp.sh .
RUN chmod a+x ./startApp.sh
startApp.sh
#!/bin/sh
java -jar ./appname.jar

How to access gradle test reports from a docker container

I'm using a docker container to build and run my java application and I want to see the test results that would usually be available from build/reports/tests/test/index.html.
Here's my Dockerfile:
FROM alpine:latest
RUN apk add gradle openjdk17
WORKDIR /home/proj
COPY . .
RUN gradle build
ENTRYPOINT [ "java", "-jar", "./app/build/libs/app.jar" ]
Here's my docker-compose.yml:
version: "3.8"
services:
app:
build: .
I typically build my container with docker-compose build and run it with docker-compose up and would like this to stay as it is.
EDIT
I've tried changing my docker-compose.yml to:
version: "3.8"
services:
app:
build: .
volumes:
- ./tests:/home/proj/app/build/reports/tests/test
But this just creates an empty directory called tests in my project's root directory. I am 100% sure the right path is /home/proj/app/build/reports/tests/test as you can see here:
I've hit this same issue. Unfortunately volumes are only availible to docker run, they aren't part of the docker build portion of the docker compose process.
I even looked into the new RUN --mount=type=bind,source=.,target=./build/reports,rw gradle build and while in the container I can see (with a RUN ls ./build/reports) the reports being generated, but that mount (even as RW) only puts files in the container as a layer and they never appear on the host machine.
There is a hacky way to recover those test results, in the docker output, just above the failure you'll see this line ---> Running in f98e14dd1ee4. This is the layer ID, with that value you can copy from the failed layer to the local machine using
$ docker cp f98e14dd1ee4:/tmp/build/reports ./
$ ls reports/
checkstyle/ jacoco/ tests/
It shouldn't be to difficult to automate this kind of recover but it feels like it would be fragile automated.
I'm very interested if anyone has a better solution to this, even with an alternative to docker. I know I can build the container with gradle but I'd rather everything happens inside the container build process to keep the build environment defined as code.

Docker image runs on Intel mac but not M1 mac

We have a Java Spring Boot application that runs in a Docker container. It is based on openjdk:13-jdk-alpine. We deploy it to Linux machines, but we are also able to run it locally on Windows machines, as well as on an Intel-based iMac.
We have found, though, that it cannot run properly on an ARM-based MacBook Pro. The exceptions we get are basic Java errors like "Can't find symbol Java.class[]," and other things that look like the JVM is off.
Is there a way to build a Docker image that will work on all these platforms, including the M1 MacBook Pro?
I have a lot of problems with Java containers too on my M1 macbook. For your problem, maybe you need to create your own docker image:
Dockerfile
FROM --platform=linux/arm64/v8 ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive
EXPOSE 8080
RUN apt update \
&& apt upgrade -y \
&& apt install -y openjdk-13-jre git \
&& apt clean
RUN mkdir -pv /app && cd /app && \
git clone https://github.com/spring-guides/gs-spring-boot.git && \
cd /app/gs-spring-boot/initial && ./gradlew build
WORKDIR /app/gs-spring-boot/initial
ENTRYPOINT [ "./gradlew", "bootRun" ]
Build image
docker build -t test .
Run container
docker run --rm -p 8080:8080 test
Go to http://localhost:8080/ on your browser and your Spring-Boot application is running without Rosetta 2.
Disclaimer: I'm not a Java developer and my Dockerfile is for Proof of Concept purpose.
Remember that your Docker image is builded to ARM64 architecture. If you wanna run this container on a Intel/AMD processor, you have to change FROM --platform=linux/amd64 ubuntu:20.04 on your Dockerfile.
I made it work with the following image.
I pulled the image with
docker pull bellsoft/liberica-openjdk-alpine-musl:17
My Dockerfile:
FROM bellsoft/liberica-openjdk-alpine-musl:17
ADD build/libs/app-0.0.1-SNAPSHOT-plain.jar app.jar
ENTRYPOINT ["java","-jar","app.jar"]
Now the docker build command worked
Build your images with multiarch support to get rid of all possible architecture failures in the future. To do this cleanly, avoid using anything related to the platform in your Dockerfile, just old-school Dockerfiles are ok.
If you are using github and github-actions, you may check this to build your images and push them into your image repository. This can be also used for building images which work on RaspberryPi like SBCs.
it's because image is not supported for m1 yet, you can build it for cross platform and run it
docker build --platform=linux/arm64 -t image:latest .

Cannot see Java Maven Tomcat-plugin web application in web browser

I want to build and run my Java Maven web app in a docker container. I tried with a following command:
docker run -it --name my_project -v "$PWD":/usr/src/my_project -w /usr/src/my_project maven:3.5.0-jdk-8 mvn clean install tomcat7:run
It correctly copies the resources, run maven clean install (successful build) and run with tomcat7-maven-plugin that is included in my pom.xml.
Everything works fine and logs are really similar to build and run locally on my windows machine:
Unfortunately on a web browser there is information "connection refused".
What could potentially cause the problem?:
- my application is windows specific and cannot run on linux?
- app is fully app and running but something wrong is with proxy configuration or port is not configured?
How can i proceed further - investigate the logs? Try to build on windows docker container?
P.S. I check IP of a container with Kitematic app for windows docker.
Possibly three issues. Once your used -w instead of -v
docker run -it --name my_project -v "$PWD":/usr/src/my_project -w /usr/src/my_project maven:3.5.0-jdk-8 mvn clean install tomcat7:run
Which I assumed was a Typo while posting. Next you didn't publish the port on your machine
docker run -p 9998:9998 -it --name my_project -v "$PWD":/usr/src/my_project -w /usr/src/my_project maven:3.5.0-jdk-8 mvn clean install tomcat7:run
This would map the port 9998 (right side) from your container to the port 9998 on your localhost.
Third and last one, your INFO log says listening on localhost:9998. This is not good. Because that means your war is listening from traffic generated inside the the container only and not from outside the container. You need to configure your war so it listens on all interfaces inside the container and bind should be 0.0.0.0:9998

need a equal code for docker run with maven to docker compose with maven

I am using the below command to build my maven project.
sudo docker run --rm --name mavenbuild -v /User/myname/.m2:/root/.m2 -v $(pwd):/usr/src/workdir -w /usr/src/workdir maven:3.3.3-jdk-8 mvn clean install
This command working fine.
Now I try to convert the same command to docker compose
version: "2.0"
services:
mavenbuild:
image: maven:3.3.3-jdk-8
volumes:
- /User/myname/.m2:/root/.m2
- ./:/usr/src/workdir
working_dir: /usr/src/workdir
command : mvn clean install
But the docker compose not working in expected way. please tell me if I am doing something wrong.
It works fine , after docker-compose rm, I guess this cached the previous build. I came to know after seeing the docker documentation.

Categories