Docker image build failed on Mac M1 chip - java

I'm trying to build a simple docker image, inside a maven project, adding the image build as part of the maven build process:
<build>
<finalName>my-api</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Docker -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.6</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<!-- <goal>push</goal> -->
</goals>
</execution>
</executions>
<configuration>
<repository>reponame/${project.name}</repository>
<tag>${project.version}</tag>
<skipDockerInfo>true</skipDockerInfo>
</configuration>
</plugin>
</plugins>
</build>
FROM openjdk:8-jdk-alpine
VOLUME /tmp
EXPOSE 8080
ADD target/*.jar app.jar
ENTRYPOINT [ "sh", "-c", "java -jar /app.jar" ]
But it fails, always get the same error trace, no matter which image I use, the error persists.
Error:
Caused by:
com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException:
java.lang.UnsatisfiedLinkError: could not load FFI provider
jnr.ffi.provider.jffi.Provider
Caused by: java.lang.UnsatisfiedLinkError:
java.lang.UnsatisfiedLinkError:
/private/var/folders/hz/rgppp8250rsdp86kf_tfjvqw0000gp/T/jffi8502916075702391528.dylib:
dlopen(/private/var/folders/hz/rgppp8250rsdp86kf_tfjvqw0000gp/T/jffi8502916075702391528.dylib,
0x0001): tried:
'/private/var/folders/hz/rgppp8250rsdp86kf_tfjvqw0000gp/T/jffi8502916075702391528.dylib'
(fat file, but missing compatible architecture (have 'i386,x86_64',
need 'arm64e')), '/usr/lib/jffi8502916075702391528.dylib' (no such
file)
Other images I tried:
openjdk:13-alpine3.9
openjdk:8-jre-alpine3.9
azul/zulu-openjdk-alpine:17.0.2-17.32.13-arm64
My java version: openjdk version "11.0.13" 2021-10-19 LTS
My Docker version: Docker version 20.10.11, build dea9396
Thanks in advance.

It looks like the dockerfile-maven-plugin uses a runtime based on x86 architecture and won't run on Apple M1 (Arm).
The plugin is now inactive so you should try something else, for example the fabric8-maven-plugin
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.38.1</version>
<executions>
<execution>
<id>build</id>
<phase>pre-integration-test</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>

Both of the spotify docker maven plugins are no longer maintained. They need to upgrade their dependency to a version that supports aarch64.
In our case there was significant refactoring needed to move to fabric8's plugin or to use maven exec so we wanted to continue to use spotify plugin.
Fortunately, you can force the plugin to use a particular dependency by adding a <dependencies> section to your plugin section.
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.6</version>
<dependencies>
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-unixsocket</artifactId>
<version>0.38.14</version>
</dependency>
</dependencies>
</plugin>

I met the same problem.According to the error message, it should be a connection error with the docker daemon.It seems that the plugin won't support Arm socket and you can do this:
(1) install socat
brew install socat
(2) set port forwarding
socat TCP-LISTEN:2375,range=127.0.0.1/32,reuseaddr,fork UNIX-CLIENT:/var/run/docker.sock
(3) set environment variable
export DOCKER_HOST=tcp://127.0.0.1:2375

Related

How to set Jmeter home in pom.xml?

The following is my pom.xml
<build>
<plugins>
<plugin>
<groupId>com.lazerycode.jmeter</groupId>
<artifactId>jmeter-maven-plugin</artifactId>
<version>2.2.0</version>
<executions>
<execution>
<id>jmeter-tests</id>
<goals>
<goal>jmeter</goal>
</goals>
</execution>
</executions>
<configuration>
<propertiesJMeter>
</propertiesJMeter>
</configuration>
</plugin>
</plugins>
</build>
When I run the .jmx, I get the following message:
Error: Could not find or load main class org.apache.jmeter.NewDriver
I notice that the classpath for org.apache.jmeter.NewDriver is wrong. How do I set it to Jmeter's home in the pom.xml, or in the .jmx file?
There is no such concept as JMeter home when it comes to executing tests via Maven plugin, all you need to do is to:
Set up your pom.xml file to look like:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.blazemeter</groupId>
<artifactId>mvn-jmeter</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>maven-jmeter-demo</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>com.lazerycode.jmeter</groupId>
<artifactId>jmeter-maven-plugin</artifactId>
<version>2.2.0</version>
<executions>
<execution>
<id>jmeter-tests</id>
<phase>verify</phase>
<goals>
<goal>jmeter</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Set up your project to look like:
src
test
jmeter
test.jmx
here you can put another jmx if needed
pom.xml
Run your test like mvn clean verify
JMeter Maven plugin will download JMeter along with dependencies (you will be able to find in under target/jmeter folder along with JMeter logs (logs folder) and test results (results folder)
More information:
JMeter Maven Plugin - official documentation
JMeter Maven Plugin - JMeter Wiki
Five Ways To Launch a JMeter Test without Using the JMeter GUI - aggregate information on different approaches to running a headless JMeter inlcuding (but not limited to) Maven Plugin
You CAN use Jmeter home with the Maven plugin. You just have to take one more step after editing your pom as described above.
In your projects directory, open up your cmd and run a specific execution to the Jmeter goal; e.g. : mvn com.lazerycode.jmeter:jmeter-maven-plugin:2.7.0:jmeter
Equivalent statement : mvn groupId:artifactId:version:goal (based on POM structure of plugin)
This will generate the Jmeter directory inside of your target directory. You can then use it as the Jmeter home for the code you're trying to use.

Is there a maven jigsaw jlink plugin?

Does maven have a plugin for the new Java 9 jlink I have searched online but have not been able to find anything official from the maven team.
Yes. There has been some progress made to create one on Github/maven-plugins for the same.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jlink-plugin</artifactId>
<version>3.0.0-SNAPSHOT</version>
</plugin>
The plugin in its code reads to be adaptive to JEP-282 and JEP-220 from the proposals.
And though this might look like a link too many answer. There is a working example from #khmarbaise on Github as well for this, which requires a toolchain with -
<configuration>
<jdkHome>/Library/Java/JavaVirtualMachines/jdk1.9.0_ea+170.jdk/Contents/Home</jdkHome>
</configuration>
Plus a side note from the author quoting -
Currently not more than a Proof of Concept. Everything here is speculative!
Edit1:- As shared in the comments, additional details could be found # How to create a Java runtime with Maven.
Edit2:- Dated 10 November, 2018 one can upgrade to using maven-jlink-plugin:3.0.0-alpha-1 and still provide some valuable feedback.
I'm working on ModiTect, general tooling around Java 9 modules. One of the goals of the ModiTect Maven plug-in lets you create module runtime images via jlink:
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
<executions>
<execution>
<id>create-runtime-image</id>
<phase>package</phase>
<goals>
<goal>create-runtime-image</goal>
</goals>
<configuration>
<modulePath>
<path>${project.build.directory}/modules</path>
</modulePath>
<modules>
<module>com.example.module1</module>
<module>com.example.module2</module>
</modules>
<launcher>
<name>helloWorld</name>
<module>com.example.module1</module>
</launcher>
<outputDirectory>
${project.build.directory}/jlink-image
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
The plug-in is under active development right now and must be built from source for the time being (will deploy a first version to Maven Central soon).
there is mvn-jlink plugin which allows to call jdeps and jlink (and any tool provided by jdk), also it can download and unpack needed openjdk version from ADOPT and LIBERICA, such way allows build cross-platform images
<plugin>
<groupId>com.igormaznitsa</groupId>
<artifactId>mvn-jlink-wrapper</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>call-jlink</id>
<goals>
<goal>jlink</goal>
</goals>
<configuration>
<jdepsReportPath>${project.build.directory}${file.separator}jdeps.out</jdepsReportPath>
<output>${project.build.directory}${file.separator}preparedJDK</output>
<addModules>
<module>java.compiler</module>
</addModules>
<options>
<option>--compress=2</option>
<option>--no-header-files</option>
<option>--no-man-pages</option>
</options>
</configuration>
</execution>
</executions>
</plugin>
Maybe check out https://github.com/ghackenberg/jigsaw-maven-plugin. The plugin also supports
jdeps --generate-module-info + javac + jar for patching unnamed modules,
jlink for creating runtime images, and
jpackage for creating application installers (only available since JDK 14 though).
You find the plugin documentation on the Github README page.
<plugin>
<groupId>io.github.ghackenberg</groupId>
<artifactId>jigsaw-maven-plugin</artifactId>
<version>1.1.3</version>
</plugin>

What Docker base image (`FROM`) for Java Spring Boot?

What Docker base image (FROM) for Java Spring Boot application?
I am just starting with docker, and I see that FROM inside Dockerfile can define image for Java like
FROM java:8
If I am building using Gradle (or Maven) is the better base image to start to avoid configuring later what is common for Gradle/Maven project?
And of course Spring Boot application is just .jar file inside build output folder, there should be less questions about how to run with Docker (for Java project built with standard build tools)
There's a nice documentation on how to integrate Spring-Boot with Docker: https://spring.io/guides/gs/spring-boot-docker/
Basically you define your dockerfile in src/main/docker/Dockerfile and configure the docker-maven-plugin like this:
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.11</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
Dockerfile:
FROM frolvlad/alpine-oraclejre8:slim
VOLUME /tmp
ADD gs-spring-boot-docker-0.1.0.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
Note that in this example FROM frolvlad/alpine-oraclejre8:slim is a small-footprinted image which is based on Alpine Linux.
You should also be able to use the standard Java 8 image (which is based on Debian and might have an increased footprint) as well. An extensive list of available Java Baseimages can be found here: https://github.com/docker-library/docs/tree/master/openjdk.
I am using the fabric plugin which uses the base docker image fabric8/java-alpine-openjdk8-jdk:1.2. There is no need for a Dockerfile, it is created by the plugin.
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<version>3.2.28</version>
</plugin>
</plugins>
</build>
Targets are fabric8:build to create docker image and fabric8:push to push docker image registry.
mvn clean install fabric8:build fabric8:push

The command line is too long Standard error from the DataNucleus tool

I am getting this error
The command line is too long.
mvn install
Standard error from the DataNucleus tool org.datanucleus.enhancer.DataNucleusEnhancer
The command line is too long.
If you is using datanucleus-maven-plugin in windows simply set fork property as false in configuration of plugin as follow:
<plugins>
...
<plugin>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-maven-plugin</artifactId>
<version>3.3.0-release</version>
<configuration>
<verbose>true</verbose>
<fork>false</fork> <!-- Solve windows line too long error -->
</configuration>
</plugin>
...
</plugins>
See the datanucleus enhancer page for more datails.
You may look at http://www.datanucleus.org/products/accessplatform/troubleshooting.html.
and here: http://code.google.com/p/vosao/issues/detail?id=47.
==============QUOTE==============
Problem
CreateProcess error=87 when running DataNucleus tools under Microsoft Windows OS.
Windows has a command line length limitation, between 8K and 64K characters depending
on the Windows version, that may be triggered when running tools such as the Enhancer
or the SchemaTool with too many arguments.
Solution
When running such tools from Maven or Ant, disable the fork mechanism by setting the
option fork="false".
==============END==============
pom.xml file needs to be adjusted as follows:
==============WAS==============
<plugin>
<groupId>org.datanucleus</groupId>
....
<configuration>
<mappingIncludes>**/*.class</mappingIncludes>
<verbose>true</verbose>
<enhancerName>ASM</enhancerName>
<api>JDO</api>
</configuration>
...
</plugin>
==============END WAS==============
==============SHOULD BE==============
<plugin>
<groupId>org.datanucleus</groupId>
....
<configuration>
<fork>false</fork>
<mappingIncludes>org/vosao/entity/*.class</mappingIncludes>
<verbose>true</verbose>
<enhancerName>ASM</enhancerName>
<api>JDO</api>
</configuration>
...
</plugin>
==============SHOULD BE==============
My suggested change to pom.xml also specifies limiting scope of Enhancer work area.

Get sources of a snapshot dependency on Eclipse

Something bother me a lot...
On a big project with many dependencies, some of them are set as SNAPSHOT in Maven2.
The matter is that it seems i can't get the sources through Eclipse without loading the project or fixing the dependency to the last release.
For debugging, it's really annoying me...
EDIT
This is what i get in eclipse maven console:
26/08/10 11:31:46 CEST: Downloading http://repo-maven/archiva/repository/snapshots/com/blabla/1.1-SNAPSHOT/blabla-1.1-20100824.213711-80-javadoc.jar
26/08/10 11:31:47 CEST: Could not download sources for com.blabla:blabla:1.1-20100824.213711-80
On archiva i can see the deployed stuff i want to retrieve in eclipse...
Repository snapshots
Group ID com.blabla
Artifact ID blabla
Version 1.1-20100824.213711-80
Packaging jar
Parent com.blabla bla 1.1-SNAPSHOT (View)
Other Versions 1.1-20100824.213535-79
I can download sources of this artifact with my browser but not within Eclipse... Any idea?
The matter is that it seems I can't get the sources through Eclipse without loading the project or fixing the dependency to the last release. For debugging, it's really annoying me...
Well, these modules are probably not publishing source JARs as part of the "regular" build process (i.e. outside the release). If these modules are under your control (which is my understanding), configuring the Maven Source Plugin to produce source JARs for them and deploying them in your corporate repo should solve the problem. From the Usage page:
Installing the sources along with your artifact
There are two ways to do this. You can
either bind this plugin to a phase or
you can add it to a profile. The goals
source:jar-no-fork and
source:test-jar-no-fork are preferred
for binding the goal to the build
lifecycle.
Installing the sources using a phase binding
Here is how you would configure the
plugin in your pom.xml to run
automatically during the verify phase:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
We are using the verify phase here
because it is the phase that comes
before the install phase, thus making
sure that the sources jar has been
created before the install takes
place.
Installing the sources using a profile
If you want to install a jar of your
sources along with your artifact
during the release process, you can
add this to your pom.xml file:
<project>
...
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
...
</project>
Using a profile would probably be a good idea so that building source JARs will only be done by the build running at the CI server level but not on developer machines.

Categories

Resources