I have a docker run command, I am just wondering what the part -v "..":".." -w ".." maven mvn clean... is doing?
docker run --rm --name ${DOCKER_IMAGE_NAME}_build -v "$(pwd)":/usr/src/mymaven -w /usr/src/mymaven maven:3.6.0-jdk-8-alpine mvn clean install package
I think it is mapping the local volume on the OS "$(pwd)" to the docker folder inside the docker volume which is /usr/src/mymaven, then it executes the command with "w" inside the /usr/src/mymaven" folder but because of the mapping it executes inside the local $pwd directory right? so it executes the "maven:3.6.0-jdk-8-alpine mvn clean install package" part, which starts the mvn build process, but what is maven:3.6.0-jdk... I know that it is an image, but how does it know where to pull that image from and how is it possible to directly execute that command for maven thereafter for that image?
The -v part of that command binds a volume to the container you're starting. In this case -v "$(pwd)":/usr/src/mymaven
adds your current directory as /usr/src/mymaven to the container.
the -w part of the command sets your working dir within the container to /usr/src/mymaven
and the part after that actually
maven:3.6.0-jdk-8-alpine -> this is the container you're starting
mvn clean install package -> this is the command you're starting inside the container (so in the /usr/src/mymaven working directory)
basically this run command starts up a container, runs maven and does this with your current directory where you started as source to run in.
for more info about the arguments: docker doc on run arguments
Related
I have a Spring boot application in a Docker container and when I run the command to execute tests I see that the app starts correctly but there is no test executed. Looks like the mvn test is completely ignored.
Below my docker commands:
docker build -t cygnetops/react-test -f Dockerfile.dev .
docker run cygnetops/react-test mvn test
Dockerfile.dev
FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
ADD /target/demoCI-CD-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
EXPOSE 5000
Entrypoints and commands are working together in a Docker container, if you specify an entrypoint, your command will be passed as an argument to the entrypoint, and if that entrypoint does nothing with the arguments passed to it, then the behaviour you are observing it totally normal.
The chapter "Understand how CMD and ENTRYPOINT interact" of the documentation provides a nice table explaining in depth how they interact.
In order to run you tests from that image, you could override the entrypoint when running you container:
docker run --entrypoint "" cygnetops/react-test mvn test
Note:
you will also have to install Maven, as it is not part of your base image
as you pointed, you will also need the POM and files of the Java project in order to run the tests, so you need to copy those sources in the image
So, add, in your Dockerfile, the lines:
COPY . .
RUN apk add --no-cache maven
If you want both to work, on the other hand, you will have to write your own entrypoint and make something from the command passed as arguments.
Here is an example:
entrypoint.sh, should be located at the same level as your Dockerfile:
#!/usr/bin/env sh
exec "$#" # execute what is passed as argument
java -Djava.security.egd=file:/dev/./urandom -jar /app.jar
Then, for your Dockerfile
FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
RUN apk add --no-cache maven
COPY . .
COPY /target/demoCI-CD-0.0.1-SNAPSHOT.jar app.jar
COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 5000
Maybe a better solution is to create a docker file that runs a script instead of plain java. for example create a runner.sh file as follow:
#!/bin/bash
CMD="java -jar app.jar"
$CMD &
SERVICE_PID=$!
mvn test
wait "$SERVICE_PID"
and this will be your dockerfile
FROM maven:3.9.0-eclipse-temurin-11-alpine
COPY . .
RUN mvn install
COPY runner.sh /scripts/runner.sh
RUN ["chmod", "+x", "/scripts/runner.sh"]
ENTRYPOINT ["/scripts/runner.sh"]
I am building a Docker container using the following Dockerfile and actually the app is running on the created container.
FROM eclipse-temurin:17-jdk-jammy as builder
RUN addgroup demogroup; adduser --ingroup demogroup --disabled-password demo
USER demo
WORKDIR /app
# copy pom.xml, mvnw and source code
COPY .mvn/ .mvn
COPY mvnw ./
COPY pom.xml ./
COPY src/ src
#RUN dos2unix ./mvnw
RUN ./mvnw clean install <-- this line gives error
# Second stage: minimal runtime environment
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
# copy jar from the first stage
COPY --from=builder /app/target/*.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
When executing RUN ./mvnw clean install line, I get " /bin/sh: 1: ./mvnw: not found" error. I tried many things, but cannot fix it. Is there any problem in my Dockerfile?
RUN mvn
runs mvn inside the docker image.
The docker image is basically a pared down Linux image. Or a Windows image, or whichever OS was used as the base image.
Presuming your base image is Linux, after docker build completed, at your project folder, you can do
docker run -it
and you will be in your dockerized Linux image, where you can run basic Linux commands (provided your image has those basic commands installed).
You can then navigate and inspect if your docker image.
To solve the problem, include Maven build in your Dockerfile instead of running maven command from project folder via mvnv:
COPY src/main/resources/data/ ./src/data
I am building a Docker container using the following Dockerfile and actually the app is running on the created container.
FROM eclipse-temurin:17-jdk-jammy as builder
RUN addgroup demogroup; adduser --ingroup demogroup --disabled-password demo
USER demo
WORKDIR /app
# copy pom.xml, mvnw and source code
COPY .mvn/ .mvn
COPY mvnw ./
COPY pom.xml ./
COPY src/ src
#RUN dos2unix ./mvnw
RUN ./mvnw clean install <-- this line gives error
# Second stage: minimal runtime environment
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
# copy jar from the first stage
COPY --from=builder /app/target/*.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
When executing RUN ./mvnw clean install line, I get " /bin/sh: 1: ./mvnw: not found" error. I tried many things, but cannot fix it. Is there any problem in my Dockerfile?
RUN mvn
runs mvn inside the docker image.
The docker image is basically a pared down Linux image. Or a Windows image, or whichever OS was used as the base image.
Presuming your base image is Linux, after docker build completed, at your project folder, you can do
docker run -it
and you will be in your dockerized Linux image, where you can run basic Linux commands (provided your image has those basic commands installed).
You can then navigate and inspect if your docker image.
To solve the problem, include Maven build in your Dockerfile instead of running maven command from project folder via mvnv:
COPY src/main/resources/data/ ./src/data
I'm building a docker image out of a micronaut application.
But whenever I run the docker build command
docker build -f Dockerfile -t micronaut .
I get this error
/bin/sh: /bin/gu: No such file or directory
Here's the content of my docker file anyway:
FROM oracle/graalvm-ce:20.0.0-java11 as graalvm
RUN $GRAALVM_HOME/bin/gu install native-image
COPY . /home/app/micronautguide
WORKDIR /home/app/micronautguide
RUN $GRAALVM_HOME/bin/native-image --no-server -cp build/libs/complete-*-all.jar
FROM frolvlad/alpine-glibc
RUN apk update && apk add libstdc++
EXPOSE 8080
COPY --from=graalvm /home/app/micronautguide/micronautguide /micronautguide/micronautguide
ENTRYPOINT ["/micronautguide/micronautguide", "-Xmx68m"]
Though by running gu command from the terminal works.
Your context does not contain RUN $GRAALVM_HOME/bin/gu . What is $GRAAL_VM_HOME? Whatever this variable is, it is set as null. Also, $GRAALVM_HOME/bin/gu needs to be part of docker image.
$GRAALVM_HOME does not exists in the oracle/graalvm-ce:20.0.0-java11 container. Thus, make suer to specify the right path. In this case it is /bin/gu
I think $GRAALVM_HOME is a variable you use in the local machine and gu tool is already installed and available at /bin in the docker image. So I have kept the $GRAALVM_HOME unchanged in the second build stage.
So, the Dockerfile should be like below,
FROM oracle/graalvm-ce:20.0.0-java11 as graalvm
RUN /bin/gu install native-image
COPY . /home/app/micronautguide
WORKDIR /home/app/micronautguide
RUN /bin/native-image --no-server -cp build/libs/complete-*-all.jar
FROM frolvlad/alpine-glibc
RUN apk update && apk add libstdc++
EXPOSE 8080
COPY --from=graalvm /home/app/micronautguide/micronautguide /micronautguide/micronautguide
ENTRYPOINT ["/micronautguide/micronautguide", "-Xmx68m"]
I am getting this strange error at the end of the process of creating a docker image from a Dockerfile:
/bin/sh: 1: gradle: not found
INFO[0003] The command [/bin/sh -c gradle test jar] returned a non-zero code: 127
The relevant part of the Dockerfile:
FROM debian:jessie
[...]
RUN curl -L https://services.gradle.org/distributions/gradle-2.4-bin.zip -o gradle-2.4-bin.zip
RUN apt-get install -y unzip
RUN unzip gradle-2.4-bin.zip
RUN echo 'export GRADLE_HOME=/app/gradle-2.4' >> $HOME/.bashrc
RUN echo 'export PATH=$PATH:$GRADLE_HOME/bin' >> $HOME/.bashrc
RUN /bin/bash -c "source $HOME/.bashrc"
RUN gradle test jar
[...]
The command I am using is: docker build -t java_i .
The strange thing is that if:
I run a container from the previous image commenting out RUN gradle test jar (command: docker run -d -p 9093:8080 -p 9094:8081 --name java_c -i -t java_i),
then I log into that container (command: docker exec -it java_c bash),
then I manually check the gradle environment variables finding them,
then I manually run that commented out command from within the running container (gradle test jar):
I eventually get the expected output (the compiled java code in the build folder).
I am using Docker version 1.6.2
I solved the problem using the ENV docker instructions (link to the documentation).
ENV GRADLE_HOME=/app/gradle-2.4
ENV PATH=$PATH:$GRADLE_HOME/bin
This command /bin/bash -c "source $HOME/.bashrc" means that you create a new non-interactive process and run a command in it to set environment variables there. Which does not affect the parent process. As soon as variables are set, process exits. You can check this by running something like this:
RUN /bin/bash -c "source $HOME/.bashrc; env"
RUN env
What should be working is this option:
RUN source ~/.bashrc
And the reason why it works when you log in, is because the new process reads already updated ~/.bashrc.
I was trying to install same version with JDK 11.0.7 but gradle-2.4 does not work. and got below error
FAILURE: Build failed with an exception.
* What went wrong:
Could not determine java version from '11.0.7'.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
I install later version to fix the above issue after installation.
Posting as an answer might help someone else.
FROM openjdk:11.0.7-jdk
RUN apt-get update && apt-get install -y unzip
WORKDIR /gradle
RUN curl -L https://services.gradle.org/distributions/gradle-6.5.1-bin.zip -o gradle-6.5.1-bin.zip
RUN unzip gradle-6.5.1-bin.zip
ENV GRADLE_HOME=/gradle/gradle-6.5.1
ENV PATH=$PATH:$GRADLE_HOME/bin
RUN gradle --version
You can use multi-stage builds and the Gradle Docker image (no need to install Gradle...) to build the application then use the result in the runtime container:
# Build
FROM gradle AS build
WORKDIR /appbuild
COPY . /appbuild
RUN gradle --version
# here goes your build code
Once the Gradle build is done, switch to the runtime container:
# Runtime
FROM openjdk:8-jre-alpine
# more stuff here...
COPY --from=0 appbuild/<somepath>/some.jar application.jar
# more stuff here...
The COPY command copies the build artifacts from the build phase to the runtime container (in this case a jar file).