From 6599366fd2d0e7ab7a84a3036b3deb088d53dcda Mon Sep 17 00:00:00 2001 From: Lari Hotari Date: Mon, 30 Sep 2024 09:24:54 +0300 Subject: [PATCH] [fix] Switch docker base image to avoid mixing musl & glibc libraries at runtime Mixing musl & glibc libraries at runtime will result in compatibility issues. We need a solution with real glibc because of compatibility reasons. The previous solution with the Alpine base image has a critical issue since it mixes musl compiled and glibc compiled libraries at runtime while using real glibc. This is why the switch is needed. For example, snappy-java and Conscrypt show that this problem occurs. --- .github/workflows/pulsar-ci.yaml | 4 +- docker/glibc-package/Dockerfile | 80 ------------------- docker/glibc-package/README.md | 39 --------- docker/glibc-package/scripts/APKBUILD | 53 ------------ .../glibc-package/scripts/glibc-bin.trigger | 21 ----- docker/glibc-package/scripts/ld.so.conf | 23 ------ docker/pulsar/Dockerfile | 65 +++------------ .../remove-unnecessary-native-binaries.sh | 4 +- docker/pulsar/pom.xml | 2 +- pom.xml | 8 +- .../docker-images/java-test-image/Dockerfile | 2 +- .../latest-version-image/Dockerfile | 2 +- 12 files changed, 24 insertions(+), 279 deletions(-) delete mode 100644 docker/glibc-package/Dockerfile delete mode 100644 docker/glibc-package/README.md delete mode 100644 docker/glibc-package/scripts/APKBUILD delete mode 100755 docker/glibc-package/scripts/glibc-bin.trigger delete mode 100644 docker/glibc-package/scripts/ld.so.conf diff --git a/.github/workflows/pulsar-ci.yaml b/.github/workflows/pulsar-ci.yaml index ad017674ac6ee..11915a9a15cf9 100644 --- a/.github/workflows/pulsar-ci.yaml +++ b/.github/workflows/pulsar-ci.yaml @@ -474,7 +474,7 @@ jobs: env: DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }} CI_JDK_MAJOR_VERSION: ${{ needs.preconditions.outputs.jdk_major_version }} - IMAGE_JDK_MAJOR_VERSION: ${{ needs.preconditions.outputs.jdk_major_version }} + PULSAR_BASE_IMAGE: bellsoft/liberica-runtime-container:jdk-${{ needs.preconditions.outputs.jdk_major_version }}-cds-stream-glibc steps: - name: checkout uses: actions/checkout@v4 @@ -830,7 +830,7 @@ jobs: env: DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }} CI_JDK_MAJOR_VERSION: ${{ needs.preconditions.outputs.jdk_major_version }} - IMAGE_JDK_MAJOR_VERSION: ${{ needs.preconditions.outputs.jdk_major_version }} + PULSAR_BASE_IMAGE: bellsoft/liberica-runtime-container:jdk-${{ needs.preconditions.outputs.jdk_major_version }}-cds-stream-glibc steps: - name: checkout uses: actions/checkout@v4 diff --git a/docker/glibc-package/Dockerfile b/docker/glibc-package/Dockerfile deleted file mode 100644 index 016e5c622365f..0000000000000 --- a/docker/glibc-package/Dockerfile +++ /dev/null @@ -1,80 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -ARG GLIBC_VERSION=2.38 -ARG ALPINE_VERSION=3.20 - -FROM ubuntu:22.04 as build -ARG GLIBC_VERSION - -RUN apt-get -q update \ - && apt-get -qy install \ - bison \ - build-essential \ - gawk \ - gettext \ - openssl \ - python3 \ - texinfo \ - wget - -# Build GLibc -RUN wget -qO- https://ftpmirror.gnu.org/libc/glibc-${GLIBC_VERSION}.tar.gz | tar zxf - -RUN mkdir /glibc-build -WORKDIR /glibc-build -RUN /glibc-${GLIBC_VERSION}/configure \ - --prefix=/usr/glibc-compat \ - --libdir=/usr/glibc-compat/lib \ - --libexecdir=/usr/glibc-compat/lib \ - --enable-multi-arch \ - --enable-stack-protector=strong -RUN make -j$(nproc) -RUN make install -RUN tar --dereference --hard-dereference -zcf /glibc-bin.tar.gz /usr/glibc-compat - - -################################################ -## Build the APK package -FROM alpine:$ALPINE_VERSION as apk -ARG GLIBC_VERSION - -RUN apk add abuild sudo build-base - -RUN mkdir /build -WORKDIR build - -COPY --from=build /glibc-bin.tar.gz /build - -COPY ./scripts /build - -RUN echo "pkgver=\"${GLIBC_VERSION}\"" >> /build/APKBUILD -RUN echo "sha512sums=\"$(sha512sum glibc-bin.tar.gz ld.so.conf)\"" >> /build/APKBUILD - -RUN abuild-keygen -a -i -n -RUN abuild -F -c -r - -################################################ -## Last stage - Only leaves the packages -FROM busybox -ARG GLIBC_VERSION - -RUN mkdir -p /root/packages -COPY --from=apk /root/packages/*/glibc-${GLIBC_VERSION}-r0.apk /root/packages -COPY --from=apk /root/packages/*/glibc-bin-${GLIBC_VERSION}-r0.apk /root/packages diff --git a/docker/glibc-package/README.md b/docker/glibc-package/README.md deleted file mode 100644 index ee1f643705ad2..0000000000000 --- a/docker/glibc-package/README.md +++ /dev/null @@ -1,39 +0,0 @@ - - -# GLibc compatibility package - -This directory includes the Docker scripts to build an image with GLibc compiled for Alpine Linux. - -This is used to ensure plugins that are going to be used in the Pulsar image and that are depeding on GLibc, will -still be working correctly in the Alpine Image. (eg: Netty Tc-Native and Kinesis Producer Library). - -This image only needs to be re-created when we want to upgrade to a newer version of GLibc. - -# Steps - -1. Change the version in the Dockerfile for this directory. -2. Rebuild the image and push it to Docker Hub: -``` -docker buildx build --platform=linux/amd64,linux/arm64 -t apachepulsar/glibc-base:2.38 . --push -``` - -The image tag is then used in `docker/pulsar/Dockerfile`. diff --git a/docker/glibc-package/scripts/APKBUILD b/docker/glibc-package/scripts/APKBUILD deleted file mode 100644 index 0545508f0a7d4..0000000000000 --- a/docker/glibc-package/scripts/APKBUILD +++ /dev/null @@ -1,53 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkgname="glibc" -pkgrel="0" -pkgdesc="GNU C Library compatibility layer" -arch="all" -url="https:/pulsar.apache.org" -license="LGPL" -options="!check" -source="glibc-bin.tar.gz -ld.so.conf" -subpackages="${pkgname}-bin ${pkgname}-dev" -triggers="glibc-bin.trigger=/lib:/usr/lib:/usr/glibc-compat/lib" -depends="libuuid libgcc" - -package() { - mkdir -p $pkgdir/lib $pkgdir/usr/glibc-compat/lib/locale $pkgdir/usr/glibc-compat/lib64 $pkgdir/etc $pkgdir/usr/glibc-compat/etc/ - cp -a $srcdir/usr $pkgdir - cp $srcdir/ld.so.conf $pkgdir/usr/glibc-compat/etc/ld.so.conf - cd $pkgdir/usr/glibc-compat - rm -rf etc/rpc bin sbin lib/gconv lib/getconf lib/audit share var include - - FILENAME=$(ls $pkgdir/usr/glibc-compat/lib/ld-linux-*.so.*) - LIBNAME=$(basename $FILENAME) - ln -s /usr/glibc-compat/lib/$LIBNAME $pkgdir/lib/$LIBNAME - ln -s /usr/glibc-compat/lib/$LIBNAME $pkgdir/usr/glibc-compat/lib64/$LIBNAME - ln -s /usr/glibc-compat/etc/ld.so.cache $pkgdir/etc/ld.so.cache -} - -bin() { - depends="$pkgname libc6-compat" - mkdir -p $subpkgdir/usr/glibc-compat - cp -a $srcdir/usr/glibc-compat/bin $subpkgdir/usr/glibc-compat - cp -a $srcdir/usr/glibc-compat/sbin $subpkgdir/usr/glibc-compat -} - diff --git a/docker/glibc-package/scripts/glibc-bin.trigger b/docker/glibc-package/scripts/glibc-bin.trigger deleted file mode 100755 index 5bae5d7ca2bda..0000000000000 --- a/docker/glibc-package/scripts/glibc-bin.trigger +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -/usr/glibc-compat/sbin/ldconfig \ No newline at end of file diff --git a/docker/glibc-package/scripts/ld.so.conf b/docker/glibc-package/scripts/ld.so.conf deleted file mode 100644 index 6548b9300bb9c..0000000000000 --- a/docker/glibc-package/scripts/ld.so.conf +++ /dev/null @@ -1,23 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -/usr/local/lib -/usr/glibc-compat/lib -/usr/lib -/lib diff --git a/docker/pulsar/Dockerfile b/docker/pulsar/Dockerfile index f3b0f3d944bdc..f835494071fda 100644 --- a/docker/pulsar/Dockerfile +++ b/docker/pulsar/Dockerfile @@ -17,8 +17,11 @@ # under the License. # +# Final image uses the Liberica JDK image running on Alpaquita Linux as the base image +# maven build passes PULSAR_BASE_IMAGE environment variable to the build as PULSAR_BASE_IMAGE argument +ARG PULSAR_BASE_IMAGE=bellsoft/liberica-runtime-container:jdk-17-cds-stream-glibc +# Alpine is used for intermediate stages ARG ALPINE_VERSION=3.20 -ARG IMAGE_JDK_MAJOR_VERSION=21 # First create a stage with just the Pulsar tarball and scripts FROM alpine:$ALPINE_VERSION as pulsar @@ -51,56 +54,29 @@ RUN for SUBDIRECTORY in conf data download logs instances/deps packages-storage; RUN chmod -R g+rx /pulsar/bin RUN chmod -R o+rx /pulsar -# Enable snappy-java to use system lib -RUN echo 'OPTS="$OPTS -Dorg.xerial.snappy.use.systemlib=true"' >> /pulsar/conf/bkenv.sh - -### Create one stage to include JVM distribution -FROM amazoncorretto:${IMAGE_JDK_MAJOR_VERSION}-alpine AS jvm - -RUN apk add --no-cache binutils - -# Use JLink to create a slimmer JDK distribution (see: https://adoptium.net/blog/2021/10/jlink-to-produce-own-runtime/) -# This still includes all JDK modules, though in the future we could compile a list of required modules -RUN /usr/lib/jvm/default-jvm/bin/jlink --add-modules ALL-MODULE-PATH --compress zip-9 --no-man-pages --no-header-files --strip-debug --output /opt/jvm -RUN echo networkaddress.cache.ttl=1 >> /opt/jvm/conf/security/java.security -RUN echo networkaddress.cache.negative.ttl=1 >> /opt/jvm/conf/security/java.security - -## Create one stage to include snappy-java native lib -# Fix the issue when using snappy-java in x86 arch alpine -# See https://github.com/xerial/snappy-java/issues/181 https://github.com/xerial/snappy-java/issues/579 -# We need to ensure that the version of the native library matches the version of snappy-java imported via Maven -FROM alpine:$ALPINE_VERSION AS snappy-java - -ARG SNAPPY_VERSION -RUN apk add git alpine-sdk util-linux cmake autoconf automake libtool openjdk17 maven curl bash tar -ENV JAVA_HOME=/usr -RUN curl -Ls https://github.com/xerial/snappy-java/archive/refs/tags/v$SNAPPY_VERSION.tar.gz | tar zxf - && cd snappy-java-$SNAPPY_VERSION && make clean-native native -FROM apachepulsar/glibc-base:2.38 as glibc - -## Create final stage from Alpine image -## and add OpenJDK and Python dependencies (for Pulsar functions) -FROM alpine:$ALPINE_VERSION +## Create final stage from liberica-runtime-container image +## and add Python dependencies (for Pulsar functions) +FROM $PULSAR_BASE_IMAGE ENV LANG C.UTF-8 +# Upgrade all packages to get latest versions with security fixes # Install some utilities, some are required by Pulsar scripts -RUN apk add --no-cache \ +RUN apk update && apk upgrade --no-cache && apk add --no-cache \ bash \ python3 \ py3-pip \ py3-grpcio \ py3-yaml \ - gcompat \ ca-certificates \ procps \ curl \ bind-tools \ openssl -# Upgrade all packages to get latest versions with security fixes -RUN apk upgrade --no-cache +# adjust default DNS caching TTL to 1 second +RUN echo networkaddress.cache.ttl=1 >> $JAVA_HOME/conf/security/java.security && echo networkaddress.cache.negative.ttl=1 >> $JAVA_HOME/conf/security/java.security # Python dependencies - # The grpcio@1.59.3 is installed by apk, and Pulsar-client@3.4.0 requires grpcio>=1.60.0, which causes the grocio to be reinstalled by pip. # If pip cannot find the grpcio wheel that the doesn't match the OS, the grpcio will be compiled locally. # Once https://github.com/apache/pulsar-client-python/pull/211 is released, keep only the pulsar-client[all] and kazoo dependencies, and remove comments. @@ -118,31 +94,16 @@ prometheus_client\n\ ratelimit\n\ # avro\n\ fastavro>=1.9.2\n\ -" > /requirements.txt - -RUN pip3 install --break-system-packages --no-cache-dir --only-binary grpcio -r /requirements.txt -RUN rm /requirements.txt - -# Install GLibc compatibility library -COPY --from=glibc /root/packages /root/packages -RUN apk add --allow-untrusted --force-overwrite /root/packages/glibc-*.apk - -COPY --from=jvm /opt/jvm /opt/jvm -ENV JAVA_HOME=/opt/jvm - -COPY --from=snappy-java /tmp/libsnappyjava.so /usr/lib/libsnappyjava.so +" > /tmp/requirements.txt && pip3 install --break-system-packages --no-cache-dir --only-binary grpcio -r /tmp/requirements.txt && rm /tmp/requirements.txt # The default is /pulsat/bin and cannot be written. ENV PULSAR_PID_DIR=/pulsar/logs - ENV PULSAR_ROOT_LOGGER=INFO,CONSOLE - COPY --from=pulsar /pulsar /pulsar - WORKDIR /pulsar ENV PATH=$PATH:$JAVA_HOME/bin:/pulsar/bin # The UID must be non-zero. Otherwise, it is arbitrary. No logic should rely on its specific value. ARG DEFAULT_USERNAME=pulsar RUN adduser ${DEFAULT_USERNAME} -u 10000 -G root -D -H -h /pulsar/data -USER 10000 +USER 10000 \ No newline at end of file diff --git a/docker/pulsar/build-scripts/remove-unnecessary-native-binaries.sh b/docker/pulsar/build-scripts/remove-unnecessary-native-binaries.sh index fe97b71179d43..8078c78900a12 100755 --- a/docker/pulsar/build-scripts/remove-unnecessary-native-binaries.sh +++ b/docker/pulsar/build-scripts/remove-unnecessary-native-binaries.sh @@ -41,9 +41,9 @@ unzip $ROCKSDB_JAR > /dev/null if [ "$ARCH" = "x86_64" ] then - ROCKSDB_TO_KEEP=linux64-musl + ROCKSDB_TO_KEEP=linux64 else - ROCKSDB_TO_KEEP=linux-$ARCH-musl + ROCKSDB_TO_KEEP=linux-$ARCH fi ls librocksdbjni-* | grep -v librocksdbjni-${ROCKSDB_TO_KEEP}.so | xargs rm diff --git a/docker/pulsar/pom.xml b/docker/pulsar/pom.xml index 481fc319be732..c14b7a470e9ca 100644 --- a/docker/pulsar/pom.xml +++ b/docker/pulsar/pom.xml @@ -83,7 +83,7 @@ target/pulsar-server-distribution-${project.version}-bin.tar.gz ${pulsar.client.python.version} ${snappy.version} - ${IMAGE_JDK_MAJOR_VERSION} + ${PULSAR_BASE_IMAGE} ${project.basedir} diff --git a/pom.xml b/pom.xml index 9f2330d7c75e1..158f0aa746c87 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ flexible messaging model and an intuitive client API. 3.4.0 - 21 + bellsoft/liberica-runtime-container:jdk-17-cds-stream-glibc **/Test*.java,**/*Test.java,**/*Tests.java,**/*TestCase.java @@ -2747,15 +2747,15 @@ flexible messaging model and an intuitive client API. - jdk-major-version-set + pulsar-base-image-set - env.IMAGE_JDK_MAJOR_VERSION + env.PULSAR_BASE_IMAGE - ${env.IMAGE_JDK_MAJOR_VERSION} + ${env.PULSAR_BASE_IMAGE} diff --git a/tests/docker-images/java-test-image/Dockerfile b/tests/docker-images/java-test-image/Dockerfile index 805f20a0570db..55ed281c96c19 100644 --- a/tests/docker-images/java-test-image/Dockerfile +++ b/tests/docker-images/java-test-image/Dockerfile @@ -26,7 +26,7 @@ USER root COPY target/scripts /pulsar/bin RUN chmod a+rx /pulsar/bin/* -RUN apk add --no-cache supervisor +RUN pip3 install --break-system-packages supervisor RUN mkdir -p /var/log/pulsar \ && mkdir -p /var/run/supervisor/ \ diff --git a/tests/docker-images/latest-version-image/Dockerfile b/tests/docker-images/latest-version-image/Dockerfile index 0645dd2e78aab..51f18a9ba1ac6 100644 --- a/tests/docker-images/latest-version-image/Dockerfile +++ b/tests/docker-images/latest-version-image/Dockerfile @@ -42,7 +42,7 @@ FROM $PULSAR_IMAGE # However, any processes exec'ing into the containers will run as root, by default. USER root -RUN apk add --no-cache supervisor procps curl +RUN apk add --no-cache procps curl && pip3 install --break-system-packages supervisor RUN mkdir -p /var/log/pulsar && mkdir -p /var/run/supervisor/