Search code examples
javaconsulmicronautgraalvm

Micronaut: Build native image with Consul dependency does not work


I am trying to build a native image of a micronaut (v1.0.4) application.

This application uses Consul as service discovery.

I've created the app using --features option:

$ mn create-app my-app --features discovery-consul --features graal-native-image --build maven

The application works perfectly on my local machine, but when I try to build a docker container with the native image I get an error:

$ ./docker-build.sh 
error: No instances are allowed in the image heap for a class that is initialized or reinitialized at image runtime: 
sun.security.provider.NativePRNG
Detailed message:
Error: No instances are allowed in the image heap for a class that is initialized or reinitialized at image runtime: sun.security.provider.NativePRNG
Trace:  object java.security.SecureRandom
    method com.sun.jndi.dns.DnsClient.query(DnsName, int, int, boolean, boolean)
Call path from entry point to com.sun.jndi.dns.DnsClient.query(DnsName, int, int, boolean, boolean): 
    at com.sun.jndi.dns.DnsClient.query(DnsClient.java:178)
    at com.sun.jndi.dns.Resolver.query(Resolver.java:81)
    at com.sun.jndi.dns.DnsContext.c_getAttributes(DnsContext.java:434)
    at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_getAttributes(ComponentDirContext.java:235)
    at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:141)
    at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:129)
    at javax.naming.directory.InitialDirContext.getAttributes(InitialDirContext.java:142)
    at io.micronaut.discovery.client.DnsResolver.getCNamesFromTxtRecord(DnsResolver.java:59)
    at io.micronaut.discovery.client.EndpointUtil.getEC2DiscoveryUrlsFromZone(EndpointUtil.java:197)
    at io.micronaut.discovery.client.EndpointUtil.getServiceUrlsFromDNS(EndpointUtil.java:141)

If I remove Consul integration, it works without any problem.

I could not find anything useful on the official documentation:

Microservices as GraalVM native images

Consul Support

Does anyone know where the problem is?


Solution

  • After going over several issues and posts, I ended up finding the answer.

    To remove this failure, just add this class com.sun.jndi.dns.DnsClient to the list of classes under the option --delay-class-initialization-to-runtime when you create the native image in you Dockerfile:

    Dockerfile

    RUN native-image --no-server \
                     ...
                     --delay-class-initialization-to-runtime=...,com.sun.jndi.dns.DnsClient \
                     -H:-UseServiceLoaderFeature \
                     --allow-incomplete-classpath \
                     -H:Name=model-quotes \
                     -H:Class=model.quotes.Application
    ...
    

    After doing that, everything works ok and the docker image is generated successfully.

    It should be a good idea to add this class in Dockerfile generated by default. It is a bit annoying to generate a new project using Micronaut CLI and find that native images does not work without changing anything.