diff --git a/README.md b/README.md index 660d1a6..6bd1310 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Very experimental. NOPUSH=true IMAGE_NAME=solsson/kafka:nativeagent ./hooks/build docker-compose -f native/docker-compose.yml down docker run --rm --entrypoint chown -v $(pwd)/native/configs:/configs busybox -R $(id -u) /configs +# after reviewing config changes with git add -p native/configs NOPUSH=true IMAGE_NAME=solsson/kafka:native ./hooks/build ``` diff --git a/jdk-oracle-open/Dockerfile b/jdk-oracle-open/Dockerfile deleted file mode 100644 index 7205296..0000000 --- a/jdk-oracle-open/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -FROM debian:stretch-slim@sha256:6c31161e090aa3f62b9ee1414b58f0a352b42b2b7827166e57724a8662fe4b38 - -# See https://jdk.java.net/11/ -ENV JDK11_VERSION=11.0.2 \ - JDK11_BUILD=7 \ - JDK11_TGZ_SHA256=62ee5758af12bbad04f376bf2b61f114076f6d8ffe4ba8db13bb5a63b5ef0d29 - -RUN set -ex; \ - export DEBIAN_FRONTEND=noninteractive; \ - runDeps=''; \ - buildDeps='curl ca-certificates'; \ - apt-get update && apt-get install -y $runDeps $buildDeps --no-install-recommends; \ - \ - cd /usr/lib; \ - mkdir jvm; \ - cd jvm; \ - curl -SLs -o jdk.tar.gz https://download.java.net/java/GA/jdk11/${JDK11_BUILD}/GPL/openjdk-${JDK11_VERSION}_linux-x64_bin.tar.gz; \ - echo "${JDK11_TGZ_SHA256} jdk.tar.gz" | sha256sum -c -; \ - tar xvzf jdk.tar.gz; \ - rm jdk.tar.gz; \ - mv jdk-11.0.2 jdk-11; \ - \ - rm -v jdk-11/lib/src.zip; \ - \ - apt-get purge -y --auto-remove $buildDeps; \ - rm -rf /var/lib/apt/lists/*; \ - rm -rf /var/log/dpkg.log /var/log/alternatives.log /var/log/apt - -# Instead of: find /usr/lib/jvm/jdk-11/bin/ -executable -exec ln -s '{}' /usr/local/bin/ -ENV PATH="$PATH:/usr/lib/jvm/jdk-11/bin" diff --git a/jdk-zulu/Dockerfile b/jdk-zulu/Dockerfile deleted file mode 100644 index 7ee2ae3..0000000 --- a/jdk-zulu/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -FROM debian:stretch-slim@sha256:bade11bf1835c9f09b011b5b1cf9f7428328416410b238d2f937966ea820be74 - -ENV ZULU_OPENJDK_VERSION="11=11.31+11" - -RUN set -ex; \ - runDeps='locales procps'; \ - buildDeps='gnupg dirmngr'; \ - export DEBIAN_FRONTEND=noninteractive; \ - apt-get update && apt-get install -y $runDeps $buildDeps --no-install-recommends; \ - \ - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0x219BD9C9; \ - echo 'deb http://repos.azulsystems.com/debian stable main' > /etc/apt/sources.list.d/zulu.list; \ - mkdir /usr/share/man/man1; \ - apt-get update; \ - apt-get -s install zulu-8 | grep zulu-; \ - apt-get -s install zulu-11 | grep zulu-; \ - apt-get -s install zulu-12 | grep zulu-; \ - apt-get install -y zulu-${ZULU_OPENJDK_VERSION} --no-install-recommends; \ - rm -rf /usr/share/man/man1; \ - \ - cd /usr/lib/jvm/zulu-11-amd64/; \ - rm -rf demo man sample src.zip; \ - \ - apt-get purge -y --auto-remove $buildDeps; \ - rm -rf /var/lib/apt/lists/*; \ - rm -rf /var/log/dpkg.log /var/log/alternatives.log /var/log/apt - -ENV JAVA_HOME=/usr/lib/jvm/zulu-11-amd64 - -# If a downstream image changes these values it must also re-run locale-gen as below -ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8 - -RUN set -ex; \ - sed -i -e "s/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/" /etc/locale.gen; \ - sed -i -e "s/# $LANG/$LANG/" /etc/locale.gen; \ - echo "LANG=\"$LANG\"" > /etc/default/locale; \ - \ - cat /etc/locale.gen | grep -v "^#"; \ - cat /etc/default/locale; \ - ls -la /usr/share/locale/locale.alias | grep /etc/locale.alias; \ - LC_ALL=C dpkg-reconfigure --frontend=noninteractive locales; diff --git a/native/.dockerignore b/native/.dockerignore new file mode 100644 index 0000000..814578e --- /dev/null +++ b/native/.dockerignore @@ -0,0 +1,2 @@ +**/.* +**/target diff --git a/native/admincmd.Dockerfile b/native/admincmd.Dockerfile index e70bcb4..34a14c2 100644 --- a/native/admincmd.Dockerfile +++ b/native/admincmd.Dockerfile @@ -1,3 +1,9 @@ +FROM solsson/kafka:graalvm as substitutions + +WORKDIR /workspace +COPY substitutions/admincmd . +RUN mvn package + FROM adoptopenjdk:11.0.8_10-jdk-hotspot-bionic@sha256:0513c0a82a82d1c9f4bfed18ef57bd5551ced2656342426a772c4772286dae1e \ as nonlibs RUN echo "class Empty {public static void main(String[] a){}}" > Empty.java && javac Empty.java && jar --create --file /empty.jar Empty.class @@ -7,12 +13,13 @@ FROM curlimages/curl@sha256:aa45e9d93122a3cfdf8d7de272e2798ea63733eeee6d06bd2ee4 USER root RUN curl -sLS -o /slf4j-nop-1.7.30.jar https://repo1.maven.org/maven2/org/slf4j/slf4j-nop/1.7.30/slf4j-nop-1.7.30.jar -RUN curl -sLS -o /quarkus-kafka-client-1.6.0.Final.jar https://repo1.maven.org/maven2/io/quarkus/quarkus-kafka-client/1.6.0.Final/quarkus-kafka-client-1.6.0.Final.jar +RUN curl -sLS -o /quarkus-kafka-client-1.7.0.Final.jar https://repo1.maven.org/maven2/io/quarkus/quarkus-kafka-client/1.7.0.Final/quarkus-kafka-client-1.7.0.Final.jar FROM solsson/kafka:nativebase as native ARG classpath=/opt/kafka/libs/extensions/*:/opt/kafka/libs/* +COPY --from=substitutions /workspace/target/*.jar /opt/kafka/libs/extensions/substitutions.jar COPY --from=extralibs /*.jar /opt/kafka/libs/extensions/ # docker run --rm --entrypoint ls solsson/kafka -l /opt/kafka/libs/ | grep log @@ -29,8 +36,7 @@ RUN native-image \ -H:IncludeResourceBundles=joptsimple.ExceptionMessages \ -H:ConfigurationFileDirectories=/home/nonroot/native-config \ # When testing the build for a new version we should remove this one, but then it tends to come back - --allow-incomplete-classpath \ - --report-unsupported-elements-at-runtime \ + --initialize-at-build-time \ # -D options from entrypoint -Djava.awt.headless=true \ -Dkafka.logs.dir=/opt/kafka/bin/../logs \ diff --git a/native/configs-manual-additions/kafka-topics/reflect-config.json b/native/configs-manual-additions/kafka-topics/reflect-config.json index 6530591..f24a429 100644 --- a/native/configs-manual-additions/kafka-topics/reflect-config.json +++ b/native/configs-manual-additions/kafka-topics/reflect-config.json @@ -2,9 +2,6 @@ { "name": "org.apache.log4j.helpers.Loader" }, - { - "name": "io.netty.util.internal.logging.Log4J2Logger" - }, { "name": "sun.security.provider.ConfigFile", "methods": [ diff --git a/native/configs/kafka-configs/reflect-config.json b/native/configs/kafka-configs/reflect-config.json index 4e66b16..bc43994 100644 --- a/native/configs/kafka-configs/reflect-config.json +++ b/native/configs/kafka-configs/reflect-config.json @@ -48,6 +48,9 @@ "name":"java.lang.ThreadLocal", "methods":[{"name":"remove","parameterTypes":[] }] }, +{ + "name":"java.lang.invoke.VarHandle" +}, { "name":"java.util.AbstractMap", "allDeclaredFields":true, @@ -102,16 +105,10 @@ "methods":[{"name":"","parameterTypes":["org.apache.zookeeper.client.ZKClientConfig"] }] }, { - "name":"scala.Serializable", - "allDeclaredMethods":true -}, -{ - "name":"scala.Tuple2[]" -}, -{ - "name":"scala.collection.convert.Wrappers$MapWrapper", + "name":"scala.collection.convert.JavaCollectionWrappers$MapWrapper", "allDeclaredFields":true, - "allDeclaredMethods":true + "allDeclaredMethods":true, + "allDeclaredConstructors":true }, { "name":"sun.security.provider.ConfigFile", diff --git a/native/configs/kafka-consumer-groups/reflect-config.json b/native/configs/kafka-consumer-groups/reflect-config.json index 2534c81..8248bbb 100644 --- a/native/configs/kafka-consumer-groups/reflect-config.json +++ b/native/configs/kafka-consumer-groups/reflect-config.json @@ -11,6 +11,9 @@ "name":"java.lang.Thread", "methods":[{"name":"getContextClassLoader","parameterTypes":[] }] }, +{ + "name":"java.lang.invoke.VarHandle" +}, { "name":"kafka.admin.ConsumerGroupCommand$PartitionAssignmentState[]" }, diff --git a/native/configs/kafka-server-start/reflect-config.json b/native/configs/kafka-server-start/reflect-config.json index bf25a34..57803e8 100644 --- a/native/configs/kafka-server-start/reflect-config.json +++ b/native/configs/kafka-server-start/reflect-config.json @@ -35,9 +35,6 @@ "allDeclaredFields":true, "allDeclaredMethods":true }, -{ - "name":"java.lang.Runnable[]" -}, { "name":"java.lang.Runtime", "methods":[{"name":"version","parameterTypes":[] }] @@ -61,6 +58,9 @@ "name":"java.lang.ThreadLocal", "methods":[{"name":"remove","parameterTypes":[] }] }, +{ + "name":"java.lang.invoke.VarHandle" +}, { "name":"java.util.AbstractCollection", "allDeclaredFields":true, @@ -91,16 +91,10 @@ { "name":"java.util.zip.CRC32C" }, -{ - "name":"kafka.server.DelayedOperationPurgatory$WatcherList[]" -}, { "name":"kafka.utils.Log4jController", "methods":[{"name":"","parameterTypes":[] }] }, -{ - "name":"kafka.utils.timer.TimerTaskList[]" -}, { "name":"org.apache.kafka.common.protocol.types.Struct[]" }, @@ -150,35 +144,32 @@ "allDeclaredMethods":true }, { - "name":"scala.Serializable", - "allDeclaredMethods":true -}, -{ - "name":"scala.Tuple2[]" -}, -{ - "name":"scala.collection.convert.Wrappers$IterableWrapperTrait", + "name":"scala.collection.convert.JavaCollectionWrappers$IterableWrapperTrait", "allDeclaredMethods":true }, { - "name":"scala.collection.convert.Wrappers$MapWrapper", + "name":"scala.collection.convert.JavaCollectionWrappers$MapWrapper", "allDeclaredFields":true, - "allDeclaredMethods":true + "allDeclaredMethods":true, + "allDeclaredConstructors":true }, { - "name":"scala.collection.convert.Wrappers$MutableBufferWrapper", + "name":"scala.collection.convert.JavaCollectionWrappers$MutableBufferWrapper", "allDeclaredFields":true, - "allDeclaredMethods":true + "allDeclaredMethods":true, + "allDeclaredConstructors":true }, { - "name":"scala.collection.convert.Wrappers$MutableMapWrapper", + "name":"scala.collection.convert.JavaCollectionWrappers$MutableMapWrapper", "allDeclaredFields":true, - "allDeclaredMethods":true + "allDeclaredMethods":true, + "allDeclaredConstructors":true }, { - "name":"scala.collection.convert.Wrappers$SeqWrapper", + "name":"scala.collection.convert.JavaCollectionWrappers$SeqWrapper", "allDeclaredFields":true, - "allDeclaredMethods":true + "allDeclaredMethods":true, + "allDeclaredConstructors":true }, { "name":"sun.misc.Signal", diff --git a/native/configs/kafka-topics/reflect-config.json b/native/configs/kafka-topics/reflect-config.json index 1a87c3d..3e79dd6 100644 --- a/native/configs/kafka-topics/reflect-config.json +++ b/native/configs/kafka-topics/reflect-config.json @@ -3,9 +3,6 @@ "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", "methods":[{"name":"","parameterTypes":[] }] }, -{ - "name":"io.netty.util.internal.logging.Log4J2Logger" -}, { "name":"java.lang.Integer", "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] @@ -33,6 +30,9 @@ "name":"java.lang.ThreadLocal", "methods":[{"name":"remove","parameterTypes":[] }] }, +{ + "name":"java.lang.invoke.VarHandle" +}, { "name":"kafka.utils.Log4jController", "methods":[{"name":"","parameterTypes":[] }] @@ -74,9 +74,6 @@ "name":"org.apache.zookeeper.ClientCnxnSocketNIO", "methods":[{"name":"","parameterTypes":["org.apache.zookeeper.client.ZKClientConfig"] }] }, -{ - "name":"scala.Tuple2[]" -}, { "name":"sun.security.provider.ConfigFile", "methods":[{"name":"","parameterTypes":[] }] diff --git a/native/configs/zookeeper-server-start/reflect-config.json b/native/configs/zookeeper-server-start/reflect-config.json index 544a81d..d3643ea 100644 --- a/native/configs/zookeeper-server-start/reflect-config.json +++ b/native/configs/zookeeper-server-start/reflect-config.json @@ -25,17 +25,10 @@ "name":"org.apache.log4j.Category", "methods":[{"name":"getName","parameterTypes":[] }] }, -{ - "name":"org.apache.log4j.CategoryKey" -}, { "name":"org.apache.log4j.ConsoleAppender", "methods":[{"name":"","parameterTypes":[] }] }, -{ - "name":"org.apache.log4j.Hierarchy", - "methods":[{"name":"getCurrentLoggers","parameterTypes":[] }] -}, { "name":"org.apache.log4j.Layout" }, @@ -43,8 +36,7 @@ "name":"org.apache.log4j.Level" }, { - "name":"org.apache.log4j.LogManager", - "methods":[{"name":"getLoggerRepository","parameterTypes":[] }] + "name":"org.apache.log4j.LogManager" }, { "name":"org.apache.log4j.Logger", @@ -57,23 +49,6 @@ { "name":"org.apache.log4j.Priority" }, -{ - "name":"org.apache.log4j.jmx.AppenderDynamicMBean", - "allPublicConstructors":true -}, -{ - "name":"org.apache.log4j.jmx.HierarchyDynamicMBean", - "allPublicConstructors":true, - "methods":[{"name":"addLoggerMBean","parameterTypes":["java.lang.String"] }] -}, -{ - "name":"org.apache.log4j.jmx.LayoutDynamicMBean", - "allPublicConstructors":true -}, -{ - "name":"org.apache.log4j.jmx.LoggerDynamicMBean", - "allPublicConstructors":true -}, { "name":"org.apache.log4j.spi.OptionHandler" }, diff --git a/native/docker-compose.yml b/native/docker-compose.yml index 5fbe428..2619ae2 100644 --- a/native/docker-compose.yml +++ b/native/docker-compose.yml @@ -133,7 +133,8 @@ - --group=testgroup - --topic=topic1 - --reset-offsets - - --to-offset 0 + - --to-offset=0 + #- --execute intentionally left out, for the dry-run use case step7: image: solsson/kafka:nativeagent-kafka-consumer-groups @@ -165,6 +166,12 @@ - --add-config - max.message.bytes=2048 + step10: + image: solsson/kafka:nativeagent-kafka-consumer-groups + volumes: [ ./configs/kafka-consumer-groups:/home/nonroot/native-config ] + command: + - --intentionally wrong + kafkacat: image: edenhill/kafkacat:1.5.0 depends_on: diff --git a/native/native-usecases.sh b/native/native-usecases.sh index a347a4e..55f7f37 100755 --- a/native/native-usecases.sh +++ b/native/native-usecases.sh @@ -33,6 +33,6 @@ $compose up -d kafka-0 $compose up -d kafkacat $compose ps -for step in $(seq 1 9); do +for step in $(seq 1 10); do $compose up step$step done diff --git a/native/substitutions/admincmd/.gitignore b/native/substitutions/admincmd/.gitignore new file mode 100644 index 0000000..beef00d --- /dev/null +++ b/native/substitutions/admincmd/.gitignore @@ -0,0 +1,4 @@ +.classpath +.project +.settings +target diff --git a/native/substitutions/admincmd/pom.xml b/native/substitutions/admincmd/pom.xml new file mode 100644 index 0000000..a4adab8 --- /dev/null +++ b/native/substitutions/admincmd/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + se.repos.substitutions.kafka + admincmd-substitutions + 1.0.0 + + 3.8.1 + true + 8 + 8 + + + + org.graalvm.nativeimage + svm + 20.1.0 + provided + + + com.yammer.metrics + metrics-core + 2.2.0 + + + io.netty + netty-common + 4.1.50.Final + + + diff --git a/native/substitutions/admincmd/src/main/java/se/repos/substitutions/kafka/admincmd/NettyLog4J2LoggerFactory.java b/native/substitutions/admincmd/src/main/java/se/repos/substitutions/kafka/admincmd/NettyLog4J2LoggerFactory.java new file mode 100644 index 0000000..b0ba8fd --- /dev/null +++ b/native/substitutions/admincmd/src/main/java/se/repos/substitutions/kafka/admincmd/NettyLog4J2LoggerFactory.java @@ -0,0 +1,17 @@ +package se.repos.substitutions.kafka.admincmd; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; + +import io.netty.util.internal.logging.InternalLogger; + +@TargetClass(io.netty.util.internal.logging.Log4J2LoggerFactory.class) +final public class NettyLog4J2LoggerFactory { + + @Substitute + public InternalLogger newInstance(String name) { + // InternalLogger is an interface so if needed we could return a stub + throw new UnsupportedOperationException("Log4J2 unsupported in native-image builds, see https://github.com/solsson/dockerfiles/pull/31"); + } + +} diff --git a/native/substitutions/admincmd/src/main/java/se/repos/substitutions/kafka/admincmd/NoJMX.java b/native/substitutions/admincmd/src/main/java/se/repos/substitutions/kafka/admincmd/NoJMX.java new file mode 100644 index 0000000..bdf22e8 --- /dev/null +++ b/native/substitutions/admincmd/src/main/java/se/repos/substitutions/kafka/admincmd/NoJMX.java @@ -0,0 +1,38 @@ +package se.repos.substitutions.kafka.admincmd; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; + +/* +Call path from entry point to kafka.metrics.KafkaYammerMetrics.defaultRegistry(): + at kafka.metrics.KafkaYammerMetrics.defaultRegistry(KafkaYammerMetrics.java:44) + at kafka.metrics.KafkaMetricsGroup.removeMetric(KafkaMetricsGroup.scala:80) + at kafka.metrics.KafkaMetricsGroup.removeMetric$(KafkaMetricsGroup.scala:79) + at kafka.zk.KafkaZkClient.removeMetric(KafkaZkClient.scala:53) + at kafka.zk.KafkaZkClient.close(KafkaZkClient.scala:1450) + at kafka.admin.TopicCommand$ZookeeperTopicService.close(TopicCommand.scala:507) + at kafka.admin.TopicCommand$.main(TopicCommand.scala:77) + at kafka.admin.TopicCommand.main(TopicCommand.scala) + at com.oracle.svm.core.JavaMainWrapper.runCore(JavaMainWrapper.java:149) + at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:184) + at com.oracle.svm.core.code.IsolateEnterStub.JavaMainWrapper_run_5087f5482cc9a6abc971913ece43acb471d2631b(generated:0) + + at com.oracle.graal.pointsto.constraints.UnsupportedFeatures.report(UnsupportedFeatures.java:129) + at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:750) + ... 8 more +*/ + +import com.yammer.metrics.core.MetricsRegistry; + +@TargetClass(className = "kafka.metrics.KafkaYammerMetrics") +final class NoJMX { + + @Substitute + public static MetricsRegistry defaultRegistry() { + throw new UnsupportedOperationException("Metrics unsupported in native-image builds, see https://github.com/solsson/dockerfiles/pull/31"); + } + + // https://github.com/apache/kafka/blob/2.6.0/core/src/main/scala/kafka/metrics/KafkaMetricsGroup.scala#L67 + // ... could be stubbed but we'd need to stub all the return types also + +} diff --git a/native/substitutions/zookeeper-server-start/.gitignore b/native/substitutions/zookeeper-server-start/.gitignore new file mode 100644 index 0000000..beef00d --- /dev/null +++ b/native/substitutions/zookeeper-server-start/.gitignore @@ -0,0 +1,4 @@ +.classpath +.project +.settings +target diff --git a/native/substitutions/zookeeper-server-start/pom.xml b/native/substitutions/zookeeper-server-start/pom.xml new file mode 100644 index 0000000..1a12eda --- /dev/null +++ b/native/substitutions/zookeeper-server-start/pom.xml @@ -0,0 +1,25 @@ + + 4.0.0 + se.repos.substitutions.kafka + zookeeper-substitutions + 1.0.0 + + 3.8.1 + true + 8 + 8 + + + + org.graalvm.nativeimage + svm + 20.1.0 + provided + + + org.apache.zookeeper + zookeeper + 3.5.8 + + + diff --git a/native/substitutions/zookeeper-server-start/src/main/java/se/repos/substitutions/kafka/zookeeper/NoJMX.java b/native/substitutions/zookeeper-server-start/src/main/java/se/repos/substitutions/kafka/zookeeper/NoJMX.java new file mode 100644 index 0000000..c59a211 --- /dev/null +++ b/native/substitutions/zookeeper-server-start/src/main/java/se/repos/substitutions/kafka/zookeeper/NoJMX.java @@ -0,0 +1,49 @@ +package se.repos.substitutions.kafka.zookeeper; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; + +import org.apache.zookeeper.jmx.ZKMBeanInfo; + +import java.util.HashSet; +import java.util.Set; + +import javax.management.JMException; + +/* +zoo-2_1 | [QuorumPeer[myid=3](plain=0.0.0.0:2181)(secure=disabled)] WARN org.apache.zookeeper.server.ZooKeeperServer - Failed to register with JMX +zoo-2_1 | java.lang.NullPointerException +zoo-2_1 | at org.apache.zookeeper.jmx.MBeanRegistry.register(MBeanRegistry.java:108) +zoo-2_1 | at org.apache.zookeeper.server.quorum.LearnerZooKeeperServer.registerJMX(LearnerZooKeeperServer.java:105) +zoo-2_1 | at org.apache.zookeeper.server.ZooKeeperServer.startup(ZooKeeperServer.java:461) +zoo-2_1 | at org.apache.zookeeper.server.quorum.Learner.syncWithLeader(Learner.java:572) +zoo-2_1 | at org.apache.zookeeper.server.quorum.Follower.followLeader(Follower.java:89) +zoo-2_1 | at org.apache.zookeeper.server.quorum.QuorumPeer.run(QuorumPeer.java:1253) +zoo-2_1 | at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:517) +zoo-2_1 | at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193) +*/ + +@TargetClass(org.apache.zookeeper.jmx.MBeanRegistry.class) +final class NoJMX { + + @Substitute + public void register(ZKMBeanInfo bean, ZKMBeanInfo parent) + throws JMException { + } + + @Substitute + private void unregister(String path,ZKMBeanInfo bean) throws JMException { + } + + @Substitute + public Set getRegisteredBeans() { + return new HashSet<>(); + } + + @Substitute + public void unregister(ZKMBeanInfo bean) { + } + + + +} diff --git a/native/zookeeper-server-start.Dockerfile b/native/zookeeper-server-start.Dockerfile index 26953c6..50c010d 100644 --- a/native/zookeeper-server-start.Dockerfile +++ b/native/zookeeper-server-start.Dockerfile @@ -1,3 +1,9 @@ +FROM solsson/kafka:graalvm as substitutions + +WORKDIR /workspace +COPY substitutions/zookeeper-server-start . +RUN mvn package + FROM curlimages/curl@sha256:aa45e9d93122a3cfdf8d7de272e2798ea63733eeee6d06bd2ee4f2f8c4027d7c \ as extralibs @@ -8,29 +14,25 @@ RUN curl -sLS -o /log4j-over-slf4j-1.7.30.jar https://repo1.maven.org/maven2/org FROM solsson/kafka:nativebase as native #ARG classpath=/opt/kafka/libs/slf4j-log4j12-1.7.30.jar:/opt/kafka/libs/log4j-1.2.17.jar:/opt/kafka/libs/slf4j-api-1.7.30.jar:/opt/kafka/libs/zookeeper-3.5.8.jar:/opt/kafka/libs/zookeeper-jute-3.5.8.jar +COPY --from=substitutions /workspace/target/*.jar /opt/kafka/libs/extensions/substitutions.jar COPY --from=extralibs /*.jar /opt/kafka/libs/extensions/ -ARG classpath=/opt/kafka/libs/slf4j-api-1.7.30.jar:/opt/kafka/libs/extensions/slf4j-simple-1.7.30.jar:/opt/kafka/libs/extensions/log4j-over-slf4j-1.7.30.jar:/opt/kafka/libs/zookeeper-3.5.8.jar:/opt/kafka/libs/zookeeper-jute-3.5.8.jar +# For running without JettyAdminServer we're probably fine with only substitutions + slf4j + zokeeper+zookeeper-jute; see https://github.com/solsson/dockerfiles/pull/31 +ARG classpath=/opt/kafka/libs/extensions/substitutions.jar:/opt/kafka/libs/slf4j-api-1.7.30.jar:/opt/kafka/libs/extensions/slf4j-simple-1.7.30.jar:/opt/kafka/libs/extensions/log4j-over-slf4j-1.7.30.jar:/opt/kafka/libs/zookeeper-3.5.8.jar:/opt/kafka/libs/zookeeper-jute-3.5.8.jar:/opt/kafka/libs/jetty-server-9.4.24.v20191120.jar:/opt/kafka/libs/jetty-util-9.4.24.v20191120.jar:/opt/kafka/libs/jetty-io-9.4.24.v20191120.jar:/opt/kafka/libs/jetty-http-9.4.24.v20191120.jar:/opt/kafka/libs/jetty-servlet-9.4.24.v20191120.jar:/opt/kafka/libs/jetty-security-9.4.24.v20191120.jar:/opt/kafka/libs/netty-common-4.1.50.Final.jar:/opt/kafka/libs/netty-handler-4.1.50.Final.jar:/opt/kafka/libs/netty-buffer-4.1.50.Final.jar:/opt/kafka/libs/javax.servlet-api-3.1.0.jar:/opt/kafka/libs/jackson-core-2.10.2.jar:/opt/kafka/libs/jackson-databind-2.10.2.jar:/opt/kafka/libs/jackson-annotations-2.10.2.jar COPY configs/zookeeper-server-start /home/nonroot/native-config -# Remaining issues: -# - java.lang.NoClassDefFoundError: Could not initialize class org.apache.zookeeper.server.admin.JettyAdminServer -# which is fine because https://github.com/apache/zookeeper/blob/release-3.5.7/zookeeper-server/src/main/java/org/apache/zookeeper/server/admin/AdminServerFactory.java -# documents that admin server is optional and it's only at startup -# - WARN org.apache.zookeeper.server.ZooKeeperServer - Failed to register with JMX -# java.lang.NullPointerException at org.apache.zookeeper.jmx.MBeanRegistry.register(MBeanRegistry.java:108) -# is very annoying because it happens a lot so it fills logs - RUN native-image \ --no-server \ --install-exit-handlers \ -H:+ReportExceptionStackTraces \ --no-fallback \ -H:ConfigurationFileDirectories=/home/nonroot/native-config \ - # Added because of org.apache.zookeeper.common.X509Util, org.apache.zookeeper.common.ZKConfig, javax.net.ssl.SSLContext ... + --initialize-at-build-time \ + --initialize-at-run-time=org.apache.zookeeper.server.persistence.FileTxnLog \ + --initialize-at-run-time=org.apache.zookeeper.server.persistence.TxnLogToolkit \ + --initialize-at-run-time=org.apache.zookeeper.server.persistence.FilePadding \ + # Added because of io.netty.buffer.Unpooled.wrappedBuffer(byte[]), org.eclipse.jetty.servlet.ServletContextHandler.(int) --allow-incomplete-classpath \ - # Added because of "ClassNotFoundException: org.apache.zookeeper.server.NIOServerCnxnFactory" - --report-unsupported-elements-at-runtime \ # -D options from entrypoint -Djava.awt.headless=true \ -Dkafka.logs.dir=/opt/kafka/bin/../logs \