diff --git a/e2e-tests/.ci/server.prepare.sh b/e2e-tests/.ci/server.prepare.sh index 4ce84778118..a985ec4dd1a 100755 --- a/e2e-tests/.ci/server.prepare.sh +++ b/e2e-tests/.ci/server.prepare.sh @@ -23,11 +23,14 @@ fi if [ "$TEST" = "cypress" ]; then mme2e_log "Prepare Cypress: install dependencies" - ${MME2E_DC_SERVER} exec -T -u 0 -- cypress bash -c "id $MME2E_UID || useradd -u $MME2E_UID -m nodeci" # Works around the node image's assumption that the app files are owned by user 1000 + # Create user in Cypress container and work around the node image's assumption that the app files are owned by user 1000 + mme2e_log "Creating user for Cypress container" + ${MME2E_DC_SERVER} exec -T -u 0 -- cypress bash -c "id $MME2E_UID || useradd -u $MME2E_UID -m nodeci" ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress npm i ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress cypress install mme2e_log "Prepare Cypress: populating fixtures" ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress tee tests/fixtures/keycloak.crt >/dev/null <../../server/build/docker/keycloak/keycloak.crt + # Download plugins using wget in the Cypress container for PLUGIN_URL in \ "https://github.com/mattermost/mattermost-plugin-gitlab/releases/download/v1.3.0/com.github.manland.mattermost-plugin-gitlab-1.3.0.tar.gz" \ "https://github.com/mattermost/mattermost-plugin-demo/releases/download/v0.9.0/com.mattermost.demo-plugin-0.9.0.tar.gz" \ @@ -35,12 +38,16 @@ if [ "$TEST" = "cypress" ]; then do PLUGIN_NAME="${PLUGIN_URL##*/}" PLUGIN_PATH="tests/fixtures/$PLUGIN_NAME" + + # Check if file exists if ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress test -f "$PLUGIN_PATH"; then mme2e_log "Skipping installation of plugin $PLUGIN_NAME: file exists" continue fi + + # Use wget in the Cypress container instead of curl in server (for distroless compatibility) mme2e_log "Downloading $PLUGIN_NAME to fixtures directory" - ${MME2E_DC_SERVER} exec -T -- server curl -L --silent "${PLUGIN_URL}" | ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress tee "$PLUGIN_PATH" >/dev/null + ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress wget -q -O "/cypress/$PLUGIN_PATH" "$PLUGIN_URL" done fi diff --git a/server/build/Dockerfile b/server/build/Dockerfile index 088dbc3b828..91b8ca70fc6 100644 --- a/server/build/Dockerfile +++ b/server/build/Dockerfile @@ -1,11 +1,8 @@ -FROM ubuntu:noble-20240605@sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30 - +# First stage - Ubuntu with document processing dependencies and curl for downloading +FROM ubuntu:noble-20250415.1@sha256:dc17125eaac86538c57da886e494a34489122fb6a3ebb6411153d742594c2ddc AS builder # Setting bash as our shell, and enabling pipefail option SHELL ["/bin/bash", "-o", "pipefail", "-c"] -# Some ENV variables -ENV PATH="/mattermost/bin:${PATH}" - # Build Arguments ARG PUID=2000 ARG PGID=2000 @@ -13,7 +10,7 @@ ARG PGID=2000 # i.e. https://releases.mattermost.com/9.7.1/mattermost-9.7.1-linux-amd64.tar.gz ARG MM_PACKAGE="https://latest.mattermost.com/mattermost-enterprise-linux" -# # Install needed packages and indirect dependencies +# Install needed packages and indirect dependencies RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ ca-certificates \ @@ -34,18 +31,48 @@ RUN mkdir -p /mattermost/data /mattermost/plugins /mattermost/client/plugins \ && curl -L $MM_PACKAGE | tar -xvz \ && chown -R mattermost:mattermost /mattermost /mattermost/data /mattermost/plugins /mattermost/client/plugins +# Final stage using distroless for minimal attack surface +FROM gcr.io/distroless/base-debian12 + +# Some ENV variables +ENV PATH="/mattermost/bin:${PATH}" +ENV MM_SERVICESETTINGS_ENABLELOCALMODE="true" + +# Copy over metadata files needed by runtime +COPY --from=builder /etc/mime.types /etc + +# Copy document processing utilities and necessary support files +COPY --from=builder /usr/bin/pdftotext /usr/bin/pdftotext +COPY --from=builder /usr/bin/wvText /usr/bin/wvText +COPY --from=builder /usr/bin/wvWare /usr/bin/wvWare +COPY --from=builder /usr/bin/unrtf /usr/bin/unrtf +COPY --from=builder /usr/bin/tidy /usr/bin/tidy +COPY --from=builder /usr/share/wv /usr/share/wv + +# Copy necessary libraries for document processing utilities +COPY --from=builder /usr/lib/libpoppler.so* /usr/lib/ +COPY --from=builder /usr/lib/libfreetype.so* /usr/lib/ +COPY --from=builder /usr/lib/libpng.so* /usr/lib/ +COPY --from=builder /usr/lib/libwv.so* /usr/lib/ +COPY --from=builder /usr/lib/libtidy.so* /usr/lib/ +COPY --from=builder /usr/lib/libfontconfig.so* /usr/lib/ + +# Copy mattermost from builder stage +COPY --from=builder --chown=2000:2000 /mattermost /mattermost + +# Copy passwd including mattermost user +COPY passwd /etc/passwd + # We should refrain from running as privileged user USER mattermost -# Healthcheck to make sure container is ready +# Healthcheck to make sure container is ready - using mmctl instead of curl for distroless compatibility HEALTHCHECK --interval=30s --timeout=10s \ - CMD curl -f http://localhost:8065/api/v4/system/ping || exit 1 + CMD ["/mattermost/bin/mmctl", "system", "status", "--local"] # Configure entrypoint and command with proper permissions -COPY --chown=mattermost:mattermost --chmod=765 entrypoint.sh / -ENTRYPOINT ["/entrypoint.sh"] WORKDIR /mattermost -CMD ["mattermost"] +CMD ["/mattermost/bin/mattermost"] EXPOSE 8065 8067 8074 8075 diff --git a/server/build/passwd b/server/build/passwd new file mode 100644 index 00000000000..4696ba5f8ed --- /dev/null +++ b/server/build/passwd @@ -0,0 +1,4 @@ +root:x:0:0:root:/root:/sbin/nologin +nobody:x:65534:65534:nobody:/nonexistent:/sbin/nologin +nonroot:x:65532:65532:nonroot:/home/nonroot:/sbin/nologin +mattermost:x:2000:2000:nonroot:/home/nonroot:/sbin/nologin