GUACAMOLE-407: Dynamically derive runtime dependencies.
authorMichael Jumper <mjumper@apache.org>
Fri, 9 Feb 2018 00:29:07 +0000 (16:29 -0800)
committerMichael Jumper <mjumper@apache.org>
Mon, 2 Apr 2018 04:16:38 +0000 (21:16 -0700)
Dockerfile
src/guacd-docker/bin/link-freerdp-plugins.sh [new file with mode: 0755]
src/guacd-docker/bin/list-dependencies.sh [new file with mode: 0755]

index e2e632d..79c884f 100644 (file)
@@ -61,13 +61,20 @@ RUN apt-get update                         && \
     rm -rf /var/lib/apt/lists/*
 
 # Add configuration scripts
-COPY src/guacd-docker/bin /opt/guacd/bin/
+COPY src/guacd-docker/bin "${PREFIX_DIR}/bin/"
 
 # Copy source to container for sake of build
 COPY . "$BUILD_DIR"
 
 # Build guacamole-server from local source
-RUN /opt/guacd/bin/build-guacd.sh "$BUILD_DIR" "$PREFIX_DIR"
+RUN ${PREFIX_DIR}/bin/build-guacd.sh "$BUILD_DIR" "$PREFIX_DIR"
+
+# Record the packages of all runtime library dependencies
+RUN ${PREFIX_DIR}/bin/list-dependencies.sh    \
+        ${PREFIX_DIR}/sbin/guacd              \
+        ${PREFIX_DIR}/lib/libguac-client-*.so \
+        ${PREFIX_DIR}/lib/freerdp/guac*.so    \
+        > ${PREFIX_DIR}/DEPENDENCIES
 
 # Use same Ubuntu as the base for the runtime image
 FROM ubuntu:${UBUNTU_VERSION}
@@ -85,62 +92,23 @@ ENV GUACD_LOG_LEVEL=info
 
 ARG RUNTIME_DEPENDENCIES="            \
         ghostscript                   \
-        libcairo2                     \
+        libfreerdp-plugins-standard   \
         fonts-liberation              \
         fonts-dejavu                  \
-        libfreerdp-cache1.1           \
-        libfreerdp-client1.1          \
-        libfreerdp-codec1.1           \
-        libfreerdp-common1.1.0        \
-        libfreerdp-core1.1            \
-        libfreerdp-crypto1.1          \
-        libfreerdp-locale1.1          \
-        libfreerdp-primitives1.1      \
-        libfreerdp-plugins-standard   \
-        libfreerdp-utils1.1           \
-        libjpeg-turbo8                \
-        libossp-uuid16                \
-        libpango1.0                   \
-        libpulse0                     \
-        libssh2-1                     \
-        libssl1.0.0                   \
-        libtelnet2                    \
-        libvncclient1                 \
-        libwebp5                      \
-        libwinpr-crt0.1               \
-        libwinpr-dsparse0.1           \
-        libwinpr-environment0.1       \
-        libwinpr-file0.1              \
-        libwinpr-handle0.1            \
-        libwinpr-heap0.1              \
-        libwinpr-input0.1             \
-        libwinpr-interlocked0.1       \
-        libwinpr-library0.1           \
-        libwinpr-path0.1              \
-        libwinpr-pool0.1              \
-        libwinpr-registry0.1          \
-        libwinpr-rpc0.1               \
-        libwinpr-sspi0.1              \
-        libwinpr-synch0.1             \
-        libwinpr-sysinfo0.1           \
-        libwinpr-thread0.1            \
-        libwinpr-utils0.1             \
         xfonts-terminus"
 
-# Bring runtime environment up to date and install runtime dependencies
-RUN apt-get update                           && \
-    apt-get install -y $RUNTIME_DEPENDENCIES && \
-    rm -rf /var/lib/apt/lists/*
-
 # Copy build artifacts into this stage
 COPY --from=builder ${PREFIX_DIR} ${PREFIX_DIR}
 
+# Bring runtime environment up to date and install runtime dependencies
+RUN apt-get update                                          && \
+    apt-get install -y $RUNTIME_DEPENDENCIES                && \
+    apt-get install -y $(cat "${PREFIX_DIR}"/DEPENDENCIES)  && \
+    rm -rf /var/lib/apt/lists/*
+
 # Link FreeRDP plugins into proper path
-RUN FREERDP_DIR=$(dirname \
-        $(dpkg-query -L libfreerdp-client1.1 | grep 'libfreerdp.*\.so' | head -n1)) && \
-    FREERDP_PLUGIN_DIR="${FREERDP_DIR}/freerdp" && \
-    mkdir -p "$FREERDP_PLUGIN_DIR" && \
-    ln -s "$PREFIX_DIR"/lib/freerdp/*.so "$FREERDP_PLUGIN_DIR"
+RUN ${PREFIX_DIR}/bin/link-freerdp-plugins.sh \
+        ${PREFIX_DIR}/lib/freerdp/guac*.so
 
 # Expose the default listener port
 EXPOSE 4822
diff --git a/src/guacd-docker/bin/link-freerdp-plugins.sh b/src/guacd-docker/bin/link-freerdp-plugins.sh
new file mode 100755 (executable)
index 0000000..332d4c0
--- /dev/null
@@ -0,0 +1,86 @@
+#!/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 link-freerdp-plugins.sh
+##
+## Automatically creates any required symbolic links for the proper loading of
+## the given FreeRDP plugins. If a given plugin is already in the correct
+## directory, no link is created for that plugin.
+##
+## @param ...
+##     The FreeRDP plugins to add links for.
+##
+
+##
+## Given the full path to a FreeRDP plugin, locates the base directory of the
+## associated FreeRDP installation (where the FreeRDP library .so files are
+## located), printing the result to STDOUT. If the directory cannot be
+## determined, an error is printed.
+##
+## @param PLUGIN_FILE
+##     The full path to the FreeRDP plugin to check.
+##
+where_is_freerdp() {
+
+    PLUGIN_FILE="$1"
+
+    # Determine the location of all libfreerdp* libraries explicitly linked
+    # to given file
+    PATHS="$(ldd "$PLUGIN_FILE"              \
+                 | awk '/=>/{print $(NF-1)}' \
+                 | grep 'libfreerdp'         \
+                 | xargs -r dirname          \
+                 | xargs -r realpath         \
+                 | sort -u)"
+
+    # Verify that exactly one location was found
+    if [ "$(echo "$PATHS" | wc -l)" != 1 ]; then
+        echo "$1: Unable to locate FreeRDP install location." >&2
+        return 1
+    fi
+
+    echo "$PATHS"
+
+}
+
+#
+# Create symbolic links as necessary to include all given plugins within the
+# search path of FreeRDP
+#
+
+while [ -n "$1" ]; do
+
+    # Determine correct install location for FreeRDP plugins
+    FREERDP_DIR="$(where_is_freerdp "$1")"
+    FREERDP_PLUGIN_DIR="${FREERDP_DIR}/freerdp"
+
+    # Add symbolic link if necessary
+    if [ ! -e "$FREERDP_PLUGIN_DIR/$(basename "$1")" ]; then
+        mkdir -p "$FREERDP_PLUGIN_DIR"
+        ln -s "$1" "$FREERDP_PLUGIN_DIR"
+    else
+        echo "$1: Already in correct directory." >&2
+    fi
+
+    shift
+
+done
+
diff --git a/src/guacd-docker/bin/list-dependencies.sh b/src/guacd-docker/bin/list-dependencies.sh
new file mode 100755 (executable)
index 0000000..090185e
--- /dev/null
@@ -0,0 +1,48 @@
+#!/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
+
+        # Determine the Debian package which is associated with that
+        # library, if any
+        dpkg-query -S "$LIBRARY" 2> /dev/null || true
+
+    done
+
+    # Next binary
+    shift
+
+done | cut -f1 -d: | sort -u
+