build spring boot (mvnw) with docker can not use cache - spring-boot

Spring Boot Docker Experimental Features
Docker 18.06 comes with some “experimental” features, including a way to cache build dependencies. To switch them on, you need a flag in the daemon (dockerd) and an environment variable when you run the client.
With the experimental features, you get different output on the console, but you can see that a Maven build now only takes a few seconds instead of minutes, provided the cache is warm.
my dockerfile can not use cache.
dockerfile
# syntax=docker/dockerfile:experimental
FROM openjdk:8-jdk-alpine as build
WORKDIR /workspace/app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN --mount=type=cache,target=/root/.m2 ./mvnw install -DskipTests -s .mvn/wrapper/settings.xml
RUN mkdir -p target/extracted && java -Djarmode=layertools -jar target/*.jar extract --destination target/extracted
FROM openjdk:8-jre-alpine
ENV TZ Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG EXTRACTED=/workspace/app/target/extracted
ARG JAVA_OPTS="-Xmx100m -Xms100m"
COPY --from=build ${EXTRACTED}/dependencies/ ./
COPY --from=build ${EXTRACTED}/spring-boot-loader/ ./
COPY --from=build ${EXTRACTED}/snapshot-dependencies/ ./
COPY --from=build ${EXTRACTED}/application/ ./
ENTRYPOINT ["sh", "-c","java ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher"]
run shell
DOCKER_BUILDKIT=1 docker build -t org/spring-boot .
every time use many minutes

Related

deploy golang app on docker from ubuntu image (multistage)

using cmd docker compose up inside testdocker folder.
getting below error
here is my dockerfile
# golang base image
FROM golang:1.19-alpine as golangBase
RUN mkdir /app
ADD . /app
WORKDIR /app
RUN go mod tidy && go build -o handlerBuild main.go
FROM ubuntu:latest
RUN mkdir /app
WORKDIR /app
COPY --from=golangBase /app .
ENTRYPOINT [ "/app/handlerBuild" ]
here is my docker-compose.yml
having file structure like below
/testdocker
/testdocker/main.go
/testdocker/go.mod
/testdocker/dockerfild
/testdocker/docker-compose.yml
Edit:
found the solution here, needed flag CGO_ENABLED=0, while building.
Go-compiled binary won't run in an alpine docker container on Ubuntu host
I think that when you COPY --from=golangBase /app . from golangBase, because golangBase already has WORKDIR app, Docker tries to copy from /app/app on golangBase (resulting in a file not found error).
Can you try COPY --from=golangBase . .? Additionally, because you set WORKDIR app on the ubuntu image, I think your entrypoint should just be ENTRYPOINT ["/handlerBuild"]. In other words, you can think of WORKDIR appas telling the Docker imagecd appso all commands thereafter should be run relative to the/app` path.
Unrelated note: I'm pretty sure WORKDIR app creates the directory app and also adds it. So instead of
RUN mkdir /app
ADD . /app
WORKDIR /app
I'm pretty sure you could just put
WORKDIR /app
and have the same effect. Correct me if I'm wrong though — I couldn't actually run the Docker build commands because I don't have your source code.

Spring boot - Jasypt - Dockerfile - Build - how to pass environemnt variables

I am following spring io article on how to use docker for spring boot. So using Dockerfile
https://github.com/spring-guides/top-spring-boot-docker/tree/main/demo
Issue: Test failing
Caused by: java.lang.IllegalArgumentException at
PropertyPlaceholderHelper.java:178
My application has a few environment variables dependency
jasypt.encryptor.password=${mjasypt.secret}
jasypt.encryptor.algorithm=${mjasypt.algo}
I am running build as below
docker build --build-arg DEPENDENCY=build/dependency -t ....
I tried 3 new env args into dockerfile
ARG CBS=a
ARG JSP=b
ARG JSA=c
and update entry point
ENTRYPOINT ["java","-noverify","-XX:TieredStopAtLevel=1","-cp","app:app/lib/*","-Dspring.main.lazy-initialization=true","-Dv1=${CBS}", "-Dv2=${JSP}", "-Dv3=${JSA}",...
and running command as, but didn't work
docker build --build-arg DEPENDENCY=build/dependency --build-arg CBS=.. --build-arg JSP=..1 --build-arg JSA=P..ES -t ...
Ive added RUN echo ${CBS} in the dockerfile and I can see the value that I passed from docker build (not a), but how can I know if that is inside ENTRY POINT too
CORRECTION:
Dockerfile is multistage and also has
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean build
How can I pass values to this command , as it runs tests
ARG in Dockerfile is only available in the build stage.
When you want to run it as a container, ARG values will not be available but ENV will be. This means you can not directly access those values in ENTRYPOINT (also not available in CMD). You can read this similar question for more info.
If you want to pass environment parameters to the container using the build arguments (ARG), the simple solution will be to do something like this:
ARG CBS=a
ARG JSP=b
ARG JSA=c
ENV CBS_ENV=$CBS
ENV JSP_ENV=$JSP
ENV JSA_ENV=$JSA
Then update your ENTRYPOINT
ENTRYPOINT ["java","-noverify","-XX:TieredStopAtLevel=1","-cp","app:app/lib/*","-Dspring.main.lazy-initialization=true","-Dv1=${CBS_ENV}", "-Dv2=${JSP_ENV}", "-Dv3=${JSA_ENV}",...
If your values are only used when the container is running, then you can remove ARG entirely, and pass it as arguments when the container is starting. Read this similar question for more info.
e.g.:
docker run -e CBS='a' -e JSP='b' -e JSA='c' mynicevue
UPDATE:
ARG CBS=a
ARG JSP=b
ARG JSA=c
# First stage
FROM openjdk:8-jdk-alpine AS build
WORKDIR /workspace/app
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean build
RUN mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*.jar)
# Second stage
FROM openjdk:8-jdk-alpine
ARG DEPENDENCY=/workspace/app/build/dependency
ARG CBS
ARG JSP
ARG JSA
ENV CBS=$CBS
ENV JSP=$JSP
ENV JSA=$JSA
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java", "-cp", "app:app/lib/*", "hello.Application", "-Dv1=${CBS}", "-Dv2=${JSP}", "-Dv3=${JSA}"]

How to execute gradle build before the Docker build on Heroku?

I want to deploy a dockerized Spring-Boot application built with gradle on the Heroku platform when a commit is pushed on github.
I deployed successfully the docker image with CLI, by building the image locally and then deploying it
I deployed successfully "on github push" with the "heroku-18" stack. After each commit, Heroku detects that my project is a gradle one, build it and deploys it with no problem. This method doesn't trigger Docker.
Now, I want to switch to the "container" stack, for Heroku to build my Dockerfile and deploys my app after each commit. The Dockerfile is correctly detected, but because the JAR is not generated, the Dockerfile step fails.
How can I trigger the generation of the JAR on Heroku side for the Dockerfile to be able to copy this JAR to the container ?
Heroku logs
=== Fetching app code
=== Building web (Dockerfile)
Sending build context to Docker daemon 50.69kBStep 1/11 : FROM openjdk:11-jre-slim
11-jre-slim: Pulling from library/openjdk
...
Step 4/11 : ADD build/libs/myapp-1.0-SNAPSHOT.jar /app/myapp.jar
ADD failed: stat /var/lib/docker/tmp/docker-builder545575378/build/libs/myapp-1.0-SNAPSHOT.jar: no such file or directory
heroku.yml
build:
docker:
web: Dockerfile
Dockerfile
FROM openjdk:11-jre-slim
VOLUME /var/log/my-app
ARG JAR_FILE
ADD build/libs/my-app-1.0-SNAPSHOT.jar /app/my-app.jar
RUN chgrp -R 0 /app
RUN chmod -R g+rwX /app
RUN chgrp -R 0 /var/log/my-app
RUN chmod -R g+rwX /var/log/my-app
CMD [ "-jar", "/app/my-app.jar" ]
ENTRYPOINT ["java"]
EXPOSE 8080
Probably you can't do that outside your Dockerfile.
But you can use Docker multi-stage builds like this:
FROM adoptopenjdk/openjdk14-openj9:alpine as build
COPY . /opt/app/src
WORKDIR /opt/app/src
RUN ./gradlew clean bootJar
FROM adoptopenjdk/openjdk14-openj9:alpine-jre
COPY --from=build opt/app/app.jar /opt/app/app.jar
CMD ["java", "-server", "-XX:MaxRAM=256m", "-jar", "/opt/app/app.jar"]

Docker Desktop for Windows + ASP.NET Core Error

I have recently decided to give docker a try and I'm running into this error for 2 days now. No matter what I do, I can't seem to get rid of it.
For a .NET Core 2.2 application:
2>C:\Users\Russell\.nuget\packages\microsoft.visualstudio.azure.containers.tools.targets\1.4.4\build\Container.targets(256,5): error : An item with the same key has already been added.
This is freshly added Docker support for the project, no config changes. I've tried a clean, rebuild, updated all nugets, etc. If I run the project in IIS express it runs fine.
Anyone have any thoughts?
Edit 1: Docker file:
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY ["SearchAPICore_Search/SearchAPICore_Search.csproj", "SearchAPICore_Search/"]
COPY ["SearchAPICore_Models/SearchAPICore_Models.csproj", "SearchAPICore_Models/"]
RUN dotnet restore "SearchAPICore_Search/SearchAPICore_Search.csproj"
COPY . .
WORKDIR "/src/SearchAPICore_Search"
RUN dotnet build "SearchAPICore_Search.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "SearchAPICore_Search.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "SearchAPICore_Search.dll"]```
You probably have a left over container that's causing the issue. Try cleaning your environment with the following commands:
Linux:
# Clean exited containers
docker ps --filter status=exited -q | xargs docker rm
# Clean dangling images
docker images --filter dangling=true -q | xargs docker rmi
# Clean old tagged images
docker images --filter reference="$ContainerTag" -q | xargs docker rmi
Windows PowerShell:
# Clean exited containers
docker ps --filter status=exited -q | %{ docker rm }
# Clean dangling images
docker ps --filter dangling=true -q | %{ docker rmi }
# Clean old tagged images
docker images --filter reference="$ContainerTag" -q | %{ docker rmi }
The last one might not be necessary but it can't hurt. Just make sure to either replace $ContainerTag with the name of the image, or create a variable with that value before hand.

Error in running Spring-Boot Application on Docker

I tried to run my simple Spring Web application jar on docker but I always get the following error. ubuntu & openjdk images exist and their state is UP. I could not run my jar file on docker? How can I get rid of this error?
ubuntu#ip-172-31-16-5:~/jar$ **docker run -d -p 8080:8080 spring-docker tail -f /dev/null**
c8eb92e5315adbaccfd894ed9e74b8e0d0eed88a81eaa07037cf8ada133c81fd
docker: **Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"java\": executable file not found in $PATH": unknown.**
Related DockerFile:
FROM ubuntu
FROM openjdk
VOLUME /tmp
ADD /spring-boot-web-0.0.1-SNAPSHOT.jar myapp.jar
RUN sh -c 'touch /myapp.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/myapp.jar"]
Check with below sequence which works for me.
Build image using below command.
docker build -t demo-img .
DockerFile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY demo-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
then run like below.
docker run --name demo-container -d -p 8080:8080 demo-img
Make sure you are running all these command from the directory in which DockerFile and jar is present.

Resources