From 0f22388fa254eb71de376d28dc2c331ea3eef1fb Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 13 Nov 2025 15:16:50 +0800 Subject: [PATCH] perf: update trixie build --- .github/workflows/buildx_release.yml | 99 +++++++++ debian/trixie/Dockerfile | 241 ++++++++++++++++++---- debian/trixie/freerdp.patch | 68 ++++++ debian/trixie/list-dependencies_trixie.sh | 52 +++++ 4 files changed, 419 insertions(+), 41 deletions(-) create mode 100644 .github/workflows/buildx_release.yml create mode 100644 debian/trixie/freerdp.patch create mode 100755 debian/trixie/list-dependencies_trixie.sh diff --git a/.github/workflows/buildx_release.yml b/.github/workflows/buildx_release.yml new file mode 100644 index 0000000..58da8df --- /dev/null +++ b/.github/workflows/buildx_release.yml @@ -0,0 +1,99 @@ + +name: Buildx image and Create Release Version + +on: + workflow_dispatch: + inputs: + version: + description: 'Build Version' + required: true + default: '1.6.0' + freerdp_version: + description: 'FreeRDP Version' + required: true + default: '2' + distro: + description: 'Debian Distro' + required: false + default: 'trixie' + PLATFORMS: + description: "Platforms (comma separated)" + required: true + default: "linux/amd64,linux/arm64" + type: string + + +jobs: + build: + strategy: + matrix: + platform: ${{ fromJson(format('["{0}"]', join(split(inputs.PLATFORMS, ','), '","'))) }} + include: + - platform: linux/amd64 + runner: ubuntu-24.04 + arch: amd64 + - platform: linux/arm64 + runner: ubuntu-24.04-arm + arch: arm64 + + runs-on: ${{ matrix.runner }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: ./debian/${{ github.event.inputs.distro }} + provenance: false + file: debian/${{ github.event.inputs.distro }}/Dockerfile + platforms: ${{ matrix.platform }} + push: true + build-args: | + VERSION=${{ github.event.inputs.version }} + FREERDP_VERSION=${{ github.event.inputs.freerdp_version }} + tags: | + ghcr.io/jumpserver/guacd:${{ github.event.inputs.version }}-${{ github.event.inputs.distro }}-${{ matrix.arch }} + outputs: type=image,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true + + merge-manifest: + runs-on: ubuntu-24.04 + needs: build + # 只有同时包含 amd64 + arm64 时才需要合并,多架构 manifest + if: > + contains(github.event.inputs.PLATFORMS, 'linux/amd64') && + contains(github.event.inputs.PLATFORMS, 'linux/arm64') + + steps: + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Merge manifest + run: | + docker buildx imagetools create \ + -t jumpserver/guacd:${{ github.event.inputs.version }}-${{ github.event.inputs.distro }} \ + -t ghcr.io/jumpserver/guacd:${{ github.event.inputs.version }}-${{ github.event.inputs.distro }} \ + ghcr.io/jumpserver/guacd:${{ github.event.inputs.version }}-${{ github.event.inputs.distro }}-amd64 \ + ghcr.io/jumpserver/guacd:${{ github.event.inputs.version }}-${{ github.event.inputs.distro }}-arm64 \ No newline at end of file diff --git a/debian/trixie/Dockerfile b/debian/trixie/Dockerfile index dac3bdb..a0bf97c 100644 --- a/debian/trixie/Dockerfile +++ b/debian/trixie/Dockerfile @@ -1,21 +1,40 @@ -FROM debian:trixie-slim AS builder -WORKDIR /opt -ENV LC_ALL=C.UTF-8 +# The target architecture of the build. Valid values are "ARM" and "X86". By +# default, this is detected automatically. +ARG BUILD_ARCHITECTURE -ARG PREFIX_DIR=/opt/guacamole +# The number of processes that may run simultaneously during the build. By +# default, this is detected automatically. +ARG BUILD_JOBS +# The directory that will house the guacamole-server source during the build ARG BUILD_DIR=/tmp/guacamole-server -ARG FREERDP_VERSION=3 +# FreeRDP version (default to version 2) +ARG FREERDP_VERSION=2 -ARG WITH_OPENSSL='OpenSSL_1(\_\d+\w*)+' +# The final install location for guacamole-server and all dependencies. NOTE: +# This value is hard-coded in the entrypoint. Any change to this value must be +# propagated there. +ARG PREFIX_DIR=/opt/guacamole + +# +# Automatically select the latest versions of each core protocol support +# library (these can be overridden at build time if a specific version is +# needed) +# ARG WITH_FREERDP="${FREERDP_VERSION}(\.\d+)+" ARG WITH_LIBSSH2='libssh2-\d+(\.\d+)+' ARG WITH_LIBTELNET='\d+(\.\d+)+' ARG WITH_LIBVNCCLIENT='LibVNCServer-\d+(\.\d+)+' ARG WITH_LIBWEBSOCKETS='v\d+(\.\d+)+' -ARG OPENSSL_OPTS="" +# +# Default build options for each core protocol support library, as well as +# guacamole-server itself (these can be overridden at build time if different +# options are needed) +# + +ARG FREERDP_ARM_OPTS="" ARG FREERDP_OPTS="\ -DBUILTIN_CHANNELS=OFF \ @@ -59,19 +78,39 @@ ARG FREERDP_OPTS="\ -DWITH_XV=OFF \ -DWITH_ZLIB=ON" +ARG FREERDP_X86_OPTS="" + +ARG GUACAMOLE_SERVER_ARM_OPTS="" + ARG GUACAMOLE_SERVER_OPTS="\ --disable-guaclog" +ARG GUACAMOLE_SERVER_X86_OPTS="" + +ARG LIBSSH2_ARM_OPTS="" + ARG LIBSSH2_OPTS="\ -DBUILD_EXAMPLES=OFF \ -DBUILD_SHARED_LIBS=ON" +ARG LIBSSH2_X86_OPTS="" + +ARG LIBTELNET_ARM_OPTS="" + ARG LIBTELNET_OPTS="\ --disable-static \ --disable-util" +ARG LIBTELNET_X86_OPTS="" + +ARG LIBVNCCLIENT_ARM_OPTS="" + ARG LIBVNCCLIENT_OPTS="" +ARG LIBVNCCLIENT_X86_OPTS="" + +ARG LIBWEBSOCKETS_ARM_OPTS="" + ARG LIBWEBSOCKETS_OPTS="\ -DDISABLE_WERROR=ON \ -DLWS_WITHOUT_SERVER=ON \ @@ -82,6 +121,19 @@ ARG LIBWEBSOCKETS_OPTS="\ -DLWS_WITHOUT_TEST_SERVER_EXTPOLL=ON \ -DLWS_WITH_STATIC=OFF" +ARG LIBWEBSOCKETS_X86_OPTS="" + +ARG WITH_OPENSSL='OpenSSL_1(\_\d+\w*)+' + +ARG OPENSSL_OPTS="" + +# Base builder image that will be used by subsequent build stages, including +# for building dependencies of guacamole-server. +# + +FROM debian:trixie-slim AS builder +ARG BUILD_DIR + ARG BUILD_DEPENDENCIES=" \ autoconf \ automake \ @@ -114,73 +166,180 @@ ARG DEBIAN_FRONTEND=noninteractive ENV USE_CCACHE=1 \ PATH=/usr/lib/ccache:${PATH} -RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,target=/var/lib/apt,sharing=locked \ - set -ex \ +RUN set -ex \ && rm -f /etc/apt/apt.conf.d/docker-clean \ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \ && apt-get update \ && apt-get install -y --no-install-recommends $BUILD_DEPENDENCIES \ && apt-get install -y --no-install-recommends $TOOLS \ - && apt-get install -y --no-install-recommends gcc-multilib || true \ && echo "no" | dpkg-reconfigure dash -ARG VERSION=main - RUN set -ex \ && git clone -b ${VERSION} --depth=1 https://github.com/apache/guacamole-server ${BUILD_DIR} \ - && rm -f ${BUILD_DIR}/src/guacd-docker/bin/build-all.sh \ - && wget -O ${BUILD_DIR}/src/guacd-docker/bin/build-all.sh https://github.com/wojiushixiaobai/guacamole-server/raw/4f2704ce642d3a8a31d0d92878a92e94a92187dc/src/guacd-docker/bin/build-all.sh \ - && wget -O ${BUILD_DIR}/src/guacd-docker/bin/list-dependencies.sh https://github.com/wojiushixiaobai/guacamole-server/raw/601ee1f81945fd5c1be935a200035c09bbaa9123/src/guacd-docker/bin/list-dependencies.sh \ - && sed -i 's@make check && @@g' ${BUILD_DIR}/src/guacd-docker/bin/build-all.sh \ + && rm ${BUILD_DIR}/src/guacd-docker/bin/autobuild.sh + +# Copy generic, automatic build script +COPY list-dependencies_trixie.sh ${BUILD_DIR}/src/guacd-docker/bin/ +COPY autobuild.sh ${BUILD_DIR}/src/guacd-docker/bin/ +RUN set -ex \ && chmod 755 ${BUILD_DIR}/src/guacd-docker/bin/*.sh - -ENV PATH=/usr/lib/ccache:${PATH} - -RUN --mount=type=cache,target=/root/.cache/ccache \ - ${BUILD_DIR}/src/guacd-docker/bin/build-all.sh - +# Build dependency: openssl +ARG PREFIX_DIR +ARG WITH_OPENSSL +ARG OPENSSL_OPTS="" +RUN ${BUILD_DIR}/src/guacd-docker/bin/autobuild.sh "OPENSSL" \ + "https://github.com/openssl/openssl" + + +# Build dependency: libssh2 +FROM builder AS libssh2 +ARG BUILD_DIR +ARG LIBSSH2_ARM_OPTS +ARG LIBSSH2_OPTS +ARG LIBSSH2_X86_OPTS +ARG PREFIX_DIR +ARG WITH_LIBSSH2 + +RUN ${BUILD_DIR}/src/guacd-docker/bin/autobuild.sh "LIBSSH2" \ + "https://github.com/libssh2/libssh2" + +# +# Build dependency: libtelnet +# + +FROM builder AS libtelnet +ARG BUILD_DIR +ARG LIBTELNET_ARM_OPTS +ARG LIBTELNET_OPTS +ARG LIBTELNET_X86_OPTS +ARG PREFIX_DIR +ARG WITH_LIBTELNET + +RUN ${BUILD_DIR}/src/guacd-docker/bin/autobuild.sh "LIBTELNET" \ + "https://github.com/seanmiddleditch/libtelnet" + +# +# Build dependency: libvncclient +# + +FROM builder AS libvncclient +ARG BUILD_DIR +ARG LIBVNCCLIENT_ARM_OPTS +ARG LIBVNCCLIENT_OPTS +ARG LIBVNCCLIENT_X86_OPTS +ARG PREFIX_DIR +ARG WITH_LIBVNCCLIENT + +RUN ${BUILD_DIR}/src/guacd-docker/bin/autobuild.sh "LIBVNCCLIENT" \ + "https://github.com/LibVNC/libvncserver" + +# +# Build dependency: libwebsockets +# + +FROM builder AS libwebsockets +ARG BUILD_DIR +ARG LIBWEBSOCKETS_ARM_OPTS +ARG LIBWEBSOCKETS_OPTS +ARG LIBWEBSOCKETS_X86_OPTS +ARG PREFIX_DIR +ARG WITH_LIBWEBSOCKETS + +RUN ${BUILD_DIR}/src/guacd-docker/bin/autobuild.sh "LIBWEBSOCKETS" \ + "https://github.com/warmcat/libwebsockets" + +# +# Build dependency: FreeRDP +# + +FROM builder AS freerdp +ARG BUILD_DIR +ARG FREERDP_ARM_OPTS +ARG FREERDP_OPTS +ARG FREERDP_X86_OPTS +ARG PREFIX_DIR +ARG WITH_FREERDP +COPY .freerdp.patch /tmp/freerdp.patch +RUN ${BUILD_DIR}/src/guacd-docker/bin/autobuild.sh "FREERDP" \ + "https://github.com/FreeRDP/FreeRDP" + +# +# STAGE 7: Collect dependencies built by previous stages and build +# guacamole-server. +# +FROM builder AS guacamole-server +ARG BUILD_DIR +ARG FREERDP_VERSION +ARG GUACAMOLE_SERVER_ARM_OPTS +ARG GUACAMOLE_SERVER_OPTS +ARG GUACAMOLE_SERVER_X86_OPTS +ARG PREFIX_DIR + +# Copy dependencies built in previous stages +# COPY --from=openssl ${PREFIX_DIR} ${PREFIX_DIR} +COPY --from=freerdp ${PREFIX_DIR} ${PREFIX_DIR} +COPY --from=libssh2 ${PREFIX_DIR} ${PREFIX_DIR} +COPY --from=libtelnet ${PREFIX_DIR} ${PREFIX_DIR} +COPY --from=libvncclient ${PREFIX_DIR} ${PREFIX_DIR} +COPY --from=libwebsockets ${PREFIX_DIR} ${PREFIX_DIR} +COPY ${BUILD_DIR}/src/guacd-docker/bin/entrypoint.sh ${PREFIX_DIR}/entrypoint.sh +RUN chmod 755 ${PREFIX_DIR}/entrypoint.sh + +RUN ${BUILD_DIR}/src/guacd-docker/bin/autobuild.sh "GUACAMOLE_SERVER" "${BUILD_DIR}" + +# Determine location of the FREERDP library based on the version. ARG FREERDP_LIB_PATH=${PREFIX_DIR}/lib/freerdp${FREERDP_VERSION} -RUN ${BUILD_DIR}/src/guacd-docker/bin/list-dependencies.sh \ +# Record the packages of all runtime library dependencies +RUN ${BUILD_DIR}/src/guacd-docker/bin/list-dependencies_trixie.sh \ ${PREFIX_DIR}/sbin/guacd \ ${PREFIX_DIR}/lib/libguac-client-*.so \ - ${FREERDP_LIB_PATH}/*guac*.so \ + ${PREFIX_DIR}/lib/freerdp2/*guac*.so \ > ${PREFIX_DIR}/DEPENDENCIES FROM debian:trixie-slim +ARG PREFIX_DIR -ARG PREFIX_DIR=/opt/guacamole +# Copy build artifacts into this stage +COPY --from=guacamole-server ${PREFIX_DIR} ${PREFIX_DIR} -ENV LANG="en_US.UTF-8" +# Runtime environment +ENV LC_ALL=C.UTF-8 ENV LD_LIBRARY_PATH=${PREFIX_DIR}/lib ENV GUACD_LOG_LEVEL=info -ARG RUNTIME_DEPENDENCIES=" \ - ca-certificates \ - netcat-openbsd" -ARG DEBIAN_FRONTEND=noninteractive -COPY --from=builder ${PREFIX_DIR} ${PREFIX_DIR} +# Bring runtime environment up to date and install runtime dependencies +ARG RUNTIME_DEPENDENCIES="\ + ca-certificates \ + libcairo2 \ + libwebp-dev \ + libjpeg62-turbo \ + netcat-openbsd" -RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,target=/var/lib/apt,sharing=locked \ - set -ex \ - && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ - && apt-get update \ +RUN apt-get update \ && apt-get install -y --no-install-recommends $RUNTIME_DEPENDENCIES \ - && apt-get install -y --no-install-recommends $(cat "${PREFIX_DIR}"/DEPENDENCIES) \ - && echo "no" | dpkg-reconfigure dash + && apt-get install -y --no-install-recommends $(cat "${PREFIX_DIR}"/DEPENDENCIES) +# Checks the operating status every 5 minutes with a timeout of 5 seconds HEALTHCHECK --interval=5m --timeout=5s CMD nc -z 127.0.0.1 4822 || exit 1 +# Create a new user guacd ARG UID=1000 ARG GID=1000 RUN groupadd --gid $GID guacd -RUN useradd --system --create-home --shell /usr/sbin/nologin --uid $UID --gid $GID guacd +RUN useradd --system --create-home --shell /sbin/nologin --uid $UID --gid $GID guacd +# Run with user guacd USER guacd +# Expose the default listener port EXPOSE 4822 -CMD /opt/guacamole/sbin/guacd -b 0.0.0.0 -L $GUACD_LOG_LEVEL -f \ No newline at end of file +# Start guacd, listening on port 0.0.0.0:4822 +# +# Note the path here MUST correspond to the value specified in the +# PREFIX_DIR build argument. +# +CMD [ "/opt/guacamole/entrypoint.sh" ] + diff --git a/debian/trixie/freerdp.patch b/debian/trixie/freerdp.patch new file mode 100644 index 0000000..2d6065f --- /dev/null +++ b/debian/trixie/freerdp.patch @@ -0,0 +1,68 @@ +diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c +index 9aaa6cf..f2fc98c 100644 +--- a/libfreerdp/core/info.c ++++ b/libfreerdp/core/info.c +@@ -85,7 +85,7 @@ static BOOL rdp_read_info_null_string(const char* what, UINT32 flags, wStream* s + + if (cbLen > 0) + { +- const WCHAR* domain = Stream_Pointer(s); ++ const WCHAR* domain = (const WCHAR*)Stream_Pointer(s); + + if (isNullTerminated && (max > 0)) + max -= nullSize; +diff --git a/libfreerdp/core/redirection.c b/libfreerdp/core/redirection.c +index 59c6dbc..5f442e5 100644 +--- a/libfreerdp/core/redirection.c ++++ b/libfreerdp/core/redirection.c +@@ -86,14 +86,14 @@ static void redirection_free_data(BYTE** str, UINT32* length) + *str = NULL; + } + +-static BOOL redirection_copy_data(char** dst, UINT32* plen, const char* str, UINT32 len) ++static BOOL redirection_copy_data(BYTE** dst, UINT32* plen, const BYTE* str, UINT32 len) + { + redirection_free_data(dst, plen); + + if (!str || (len == 0)) + return TRUE; + +- *dst = malloc(len); ++ *dst = (BYTE*)malloc(len); + if (!*dst) + return FALSE; + memcpy(*dst, str, len); +@@ -109,27 +109,27 @@ static BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, size_t id, c + switch (id) + { + case FreeRDP_TargetNetAddress: +- pdata = &settings->TargetNetAddress; ++ pdata = (BYTE**)&settings->TargetNetAddress; + plen = &settings->TargetNetAddressCount; + break; + case FreeRDP_LoadBalanceInfo: +- pdata = &settings->LoadBalanceInfo; ++ pdata = (BYTE**)&settings->LoadBalanceInfo; + plen = &settings->LoadBalanceInfoLength; + break; + case FreeRDP_RedirectionPassword: +- pdata = &settings->RedirectionPassword; ++ pdata = (BYTE**)&settings->RedirectionPassword; + plen = &settings->RedirectionPasswordLength; + break; + case FreeRDP_RedirectionTsvUrl: +- pdata = &settings->RedirectionTsvUrl; ++ pdata = (BYTE**)&settings->RedirectionTsvUrl; + plen = &settings->RedirectionTsvUrlLength; + break; + case FreeRDP_RedirectionGuid: +- pdata = &settings->RedirectionGuid; ++ pdata = (BYTE**)&settings->RedirectionGuid; + plen = &settings->RedirectionGuidLength; + break; + case FreeRDP_RedirectionTargetCertificate: +- pdata = &settings->RedirectionTargetCertificate; ++ pdata = (BYTE**)&settings->RedirectionTargetCertificate; + plen = &settings->RedirectionTargetCertificateLength; + break; + default: diff --git a/debian/trixie/list-dependencies_trixie.sh b/debian/trixie/list-dependencies_trixie.sh new file mode 100755 index 0000000..d9e1e35 --- /dev/null +++ b/debian/trixie/list-dependencies_trixie.sh @@ -0,0 +1,52 @@ +#!/bin/sh -e +# +# 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. +# + +## +## @fn list-dependencies.sh +## +## Lists the Debian/Ubuntu package names for all library dependencies of the +## given binaries. Each package is only listed once, even if multiple binaries +## provided by the same package are given. +## +## @param ... +## The full paths to all binaries being checked. +## + +while [ -n "$1" ]; do + + # For all non-Guacamole library dependencies + ldd "$1" | grep -v 'libguac' | awk '/=>/{print $(NF-1)}' \ + | while read LIBRARY; do + + # In some cases, the library that's linked against is a hard link + # to the file that's managed by the package, which dpkg doesn't understand. + # Searching by */basename ensures the package will be found in these cases. + LIBRARY_BASENAME=$(basename "$LIBRARY") + + # Determine the Debian package which is associated with that + # library, if any + dpkg-query -S "*/$LIBRARY_BASENAME" | grep -P '^[a-z0-9][a-z0-9\.\+-]*:' || true + + done + + # Next binary + shift + +done | cut -f1 -d: | sort -u \ No newline at end of file