61928

gradle build local works. In docker container it doesn't. WHY?

The situation is simple:

here is my local env:

cbongiorno at wa-cbongiorno-mba in /Volumes/dev/sterling/java-user-login-service on master [!$] $ gradle -v ------------------------------------------------------------ Gradle 4.0 ------------------------------------------------------------ Build time: 2017-06-14 15:11:08 UTC Revision: 316546a5fcb4e2dfe1d6aa0b73a4e09e8cecb5a5 Groovy: 2.4.11 Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015 JVM: 1.8.0_131 (Oracle Corporation 25.131-b11) OS: Mac OS X 10.12.5 x86_64

here is the build command I run:

gradle compileJava check assemble && history | tail -3

here are the results:

BUILD SUCCESSFUL in 3m 3s 38 actionable tasks: 38 executed 1496 gradle clean 1497 gradle compileJava check assemble && history | tail -2

Now, when I run this identical arrangement in docker:

docker run --rm gradle:alpine gradle -v ------------------------------------------------------------ Gradle 4.0 ------------------------------------------------------------ Build time: 2017-06-14 15:11:08 UTC Revision: 316546a5fcb4e2dfe1d6aa0b73a4e09e8cecb5a5 Groovy: 2.4.11 Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015 JVM: 1.8.0_131 (Oracle Corporation 25.131-b11) OS: Linux 4.9.36-moby amd64 docker run --rm -v "$PWD":/project -w /project gradle:alpine gradle compileJava check assemble

The tests fail and in the logs I get:

Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.xerial.snappy.Snappy build_1 | at org.redisson.codec.SnappyCodec$2.encode(SnappyCodec.java:68) build_1 | at org.redisson.client.handler.CommandEncoder.encode(CommandEncoder.java:103) build_1 | at org.redisson.client.handler.CommandEncoder.encode(CommandEncoder.java:45) build_1 | at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107) build_1 | ... 31 more build_1 | build_1 | build_1 | io.netty.handler.codec.EncoderException: java.lang.NoClassDefFoundError: Could not initialize class org.xerial.snappy.Snappy

When my app attempts to engage with Redis.

How on earth is this possible? Is this a red-herring and the issues is related to the docker environment itself? I would guess an archive is corrupt/wrong but the docker container would pull from the same artifact repositories. So, I don't even know where to start

I used the answer from here to dump the hash values of every jar into a file with:

docker run --rm -v "$PWD":/project -w /project gradle:alpine gradle printDependencyHashes | sort > hashes-docker.log gradle printDependencyHashes | sort > hashes.log

respectively. The results are identical. I even thought about how jar load order from the files system could effect class loading and compared dependencies. Identical. Omitted for brevity.

<img src=https://www.e-learn.cn/content/wangluowenzhang/"https://i.stack.imgur.com/ON2Ev.jpg" alt="MD5 hash of all dependencies compared">

Answer1:

Java Snappy's native library (loaded through JNI) is compiled against glibc. Alpine Linux (what your container is based on) uses the musl libc which is source-compatible but not binary-compatible (basically means if you compile the native library against musl it will work, but if it is compiled against glibc it will not work with musl).

You have three options:

<ol> <li>Install java-snappy-native (which contains a native library built for musl) in your Alpine container and set org.xerial.snappy.use.systemlib=true (tells the Java library to use the preinstalled native lbrary). <strike>Currently you also need to install snappy since somebody failed to add that dependency to the above package.</strike></li> <li>Use a base container with glibc</li> <li>Install glibc in your Alpine container (not really recommended)</li> </ol>

Recommend

  • How do I download Docker images without using the pull command?
  • How to make a select list with multiple columns of options
  • Unable to understand the working of Threads- Runnable Interface
  • JUnit: selectively not run a few test cases as default
  • Which should I use: preceding:: or preceding-sibling::?
  • How to get rid of MemoryError while dealing with a large dictionary?
  • Can we stream only flash videos throught RTMP?
  • xp_regread() returned error 5, 'Access is denied.'
  • Exclude fields from JSON using JSONPath
  • @IfProfileValue import set from env variable, test not executing
  • How can I pass arguments to ranlib using cmake?
  • How to mount volume into the source code of the app?
  • Error:Execution failed for task ':app:dexDebug'. when importing ParseLoginUI as a module
  • does the FROM directive in a dockerfile allways pull the latest version of an image
  • Creating new docker-machine instance always fails validating certs using openstack driver
  • Can I apply the Git-Flow workflow on GitHub
  • How to update docker-compose on Docker for Windows?
  • Implicit cast from const string to bool [duplicate]
  • Modifying files nested in tar archive
  • twisted.internet.error.ConnectError when run scrapy spider
  • Is there a equivalent to JSON.Net in Java? [duplicate]
  • How to get the index of element in the List in c#
  • Attemping to change attributes of $(this) inside success function
  • Autohotkey script running program with command line arguments
  • get all processes in parallel
  • How to get real device model in Android?
  • end daemon processes with multiprocessing module
  • Thread synchronization with syncwarp
  • Portable JRE on Linux - possible?
  • Less Conflicting Session Manager for Zope 2
  • How can I run DataNucleus Bytecode Enhancer from SBT?
  • Jquery Knockout: ko.computed() vs classic function?
  • Bash if statement with multiple conditions
  • What is the purpose of TaskExecutor in spring?
  • print() is showing quotation marks in results
  • Moving mysql files across servers
  • ActionScript 2 vs ActionScript 3 performance
  • Function pointer “assignment from incompatible pointer type” only when using vararg ellipsis
  • coudnt use logback because of log4j