feat: build non-root image variants (#310)
authorThomas B. <redacted>
Tue, 15 Apr 2025 19:46:17 +0000 (21:46 +0200)
committerGitHub <redacted>
Tue, 15 Apr 2025 19:46:17 +0000 (21:46 +0200)
Adds an additional stage to the Dockerfile to create images with default user www-data.
The apache webserver listens on unprivileged port 8000 instead of 80.
Publish all variants with an additional tag ending in `-nonroot` for distinction.

Refs: #306

14 files changed:
.github/workflows/build.yml
.github/workflows/test.yml
apache/Dockerfile
apache/docker-entrypoint.sh
apache/nonroot-add.txt [new file with mode: 0644]
fpm-alpine/Dockerfile
fpm-alpine/docker-entrypoint.sh
fpm/Dockerfile
fpm/docker-entrypoint.sh
templates/Dockerfile-alpine.templ
templates/Dockerfile-debian.templ
templates/docker-entrypoint.sh
tests/docker-compose.test-apache-postgres.yml
update.sh

index 542dcd961c04f4b04b60b6c6fb27cbd6874aad29..07357b6fcc4611e2b3094f78043767a563e496ae 100644 (file)
@@ -30,14 +30,32 @@ jobs:
             test-files: 'apache-postgres'
             docker-tag: roundcube/roundcubemail:1.6.x-apache,roundcube/roundcubemail:1.6.10-apache,roundcube/roundcubemail:latest-apache,roundcube/roundcubemail:latest
             test-tag: roundcube/roundcubemail:latest-apache
+            target: 'root'
           - variant: 'fpm'
             test-files: 'fpm-postgres'
             docker-tag: roundcube/roundcubemail:1.6.x-fpm,roundcube/roundcubemail:1.6.10-fpm,roundcube/roundcubemail:latest-fpm
             test-tag: roundcube/roundcubemail:latest-fpm
+            target: 'root'
           - variant: 'fpm-alpine'
             test-files: 'fpm-postgres'
             docker-tag: roundcube/roundcubemail:1.6.x-fpm-alpine,roundcube/roundcubemail:1.6.10-fpm-alpine,roundcube/roundcubemail:latest-fpm-alpine
             test-tag: roundcube/roundcubemail:latest-fpm-alpine
+            target: 'root'
+          - variant: 'apache'
+            test-files: 'apache-postgres'
+            docker-tag: roundcube/roundcubemail:1.6.x-apache-nonroot,roundcube/roundcubemail:1.6.9-apache-nonroot,roundcube/roundcubemail:latest-apache-nonroot,roundcube/roundcubemail:latest-nonroot
+            test-tag: roundcube/roundcubemail:latest-apache-nonroot
+            target: 'nonroot'
+          - variant: 'fpm'
+            test-files: 'apache-postgres'
+            docker-tag: roundcube/roundcubemail:1.6.x-fpm-nonroot,roundcube/roundcubemail:1.6.9-fpm-nonroot,roundcube/roundcubemail:latest-fpm-nonroot
+            test-tag: roundcube/roundcubemail:latest-fpm-nonroot
+            target: 'nonroot'
+          - variant: 'fpm-alpine'
+            test-files: 'apache-postgres'
+            docker-tag: roundcube/roundcubemail:1.6.x-fpm-alpine-nonroot,roundcube/roundcubemail:1.6.9-fpm-alpine-nonroot,roundcube/roundcubemail:latest-fpm-alpine-nonroot
+            test-tag: roundcube/roundcubemail:latest-fpm-alpine-nonroot
+            target: 'nonroot'
     steps:
       - name: Checkout repository
         uses: actions/checkout@v4
@@ -65,6 +83,7 @@ jobs:
           platforms: "linux/arm64,linux/arm/v6,linux/arm/v7,linux/386,linux/amd64,"
           push: true
           tags: ${{ matrix.docker-tag }}
+          target: ${{ matrix.target }}
           # does not work linux/arm/v5 AND linux/mips64le - composer does not support  mips64le or armv5 nor does the php image support them on the alpine variant
 
       - name: Run tests
index 50577d70a514da7b616ce04a2982a52b928a0d77..baa06e986970ce740f41db884ed733d2742d7bd2 100644 (file)
@@ -20,12 +20,28 @@ jobs:
           - variant: 'apache'
             test-files: 'apache-postgres'
             docker-tag: roundcube/roundcubemail:test-apache
+            target: 'root'
           - variant: 'fpm'
             test-files: 'fpm-postgres'
             docker-tag: roundcube/roundcubemail:test-fpm
+            target: 'root'
           - variant: 'fpm-alpine'
             test-files: 'fpm-postgres'
             docker-tag: roundcube/roundcubemail:test-fpm-alpine
+            target: 'root'
+          - variant: 'apache'
+            test-files: 'apache-postgres'
+            docker-tag: roundcube/roundcubemail:test-apache-nonroot
+            target: 'nonroot'
+            http-port: '8000'
+          - variant: 'fpm'
+            test-files: 'fpm-postgres'
+            docker-tag: roundcube/roundcubemail:test-fpm-nonroot
+            target: 'nonroot'
+          - variant: 'fpm-alpine'
+            test-files: 'fpm-postgres'
+            docker-tag: roundcube/roundcubemail:test-fpm-alpine-nonroot
+            target: 'nonroot'
     steps:
       - name: Checkout repository
         uses: actions/checkout@v4
@@ -39,11 +55,12 @@ jobs:
           username: ${{ secrets.DOCKER_PULL_USERNAME }}
           password: ${{ secrets.DOCKER_PULL_PASSWORD }}
 
-      - name: Build image for "${{ matrix.variant }}"
-        run: cd ${{ matrix.variant }} && docker buildx build ./ -t ${{ matrix.docker-tag }}
+      - name: Build image for "${{ matrix.variant }} / ${{ matrix.target }}"
+        run: cd ${{ matrix.variant }} && docker buildx build ./ -t ${{ matrix.docker-tag }} --target ${{ matrix.target }}
       - name: Run tests
         env:
           ROUNDCUBEMAIL_TEST_IMAGE: ${{ matrix.docker-tag }}
+          HTTP_PORT: ${{ matrix.http-port || '80' }}
         run: |
           set -exu;
           for testFile in ${{ join(matrix.test-files, ' ') }};
index 1b1bec3d72659a791d52e53f0424d8927c93d6c1..c27ad148dec653966ca9f80679adc77a6a05c5a2 100644 (file)
@@ -1,4 +1,4 @@
-FROM php:8.1-apache
+FROM php:8.1-apache as root
 LABEL maintainer="Thomas Bruederli <thomas@roundcube.net>"
 LABEL org.opencontainers.image.source="https://github.com/roundcube/roundcubemail-docker"
 
@@ -122,7 +122,24 @@ RUN set -ex; \
        rm -rf /usr/src/roundcubemail/installer; \
        chown -R www-data:www-data /usr/src/roundcubemail/logs; \
 # Create the config dir
-       mkdir -p /var/roundcube/config /var/roundcube/enigma
+       mkdir -p /var/roundcube/config /var/roundcube/enigma; \
+       chown -R www-data:www-data /var/roundcube; \
+       chmod +t /var/roundcube
 
 ENTRYPOINT ["/docker-entrypoint.sh"]
 CMD ["apache2-foreground"]
+
+
+#### non-root stage
+
+FROM root as nonroot
+
+# Prepare locale config for locale-gen
+RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen; \
+       /usr/sbin/locale-gen
+
+RUN sed -i 's/^Listen 80$/Listen 8000/' /etc/apache2/ports.conf
+
+EXPOSE 8000
+
+USER 33:33
\ No newline at end of file
index e493b51f3ca2d0f07dae80ec87e4f7c7c9a400da..95174b47f4f63570c91006b918dbaaa3acf6763e 100755 (executable)
@@ -189,9 +189,8 @@ if  [[ "$1" == apache2* || "$1" == php-fpm || "$1" == bin* ]]; then
 
   : "${ROUNDCUBEMAIL_LOCALE:=en_US.UTF-8 UTF-8}"
 
-  if [ -e /usr/sbin/locale-gen ] && [ ! -z "${ROUNDCUBEMAIL_LOCALE}" ]; then
-    echo "${ROUNDCUBEMAIL_LOCALE}" > /etc/locale.gen
-    /usr/sbin/locale-gen
+  if [ -e /usr/sbin/locale-gen ] && [ ! -f /etc/locale.gen ] && [ ! -z "${ROUNDCUBEMAIL_LOCALE}" ]; then
+    echo "${ROUNDCUBEMAIL_LOCALE}" > /etc/locale.gen && /usr/sbin/locale-gen
   fi
 
   if [ ! -z "${ROUNDCUBEMAIL_ASPELL_DICTS}" ]; then
diff --git a/apache/nonroot-add.txt b/apache/nonroot-add.txt
new file mode 100644 (file)
index 0000000..1e02d1f
--- /dev/null
@@ -0,0 +1,3 @@
+RUN sed -i 's/^Listen 80$/Listen 8000/' /etc/apache2/ports.conf
+
+EXPOSE 8000
index 689b4b0aeb2fcae87be0e1660b9457ded97ec0ea..0e6fba8fe130215bcaba0d0ed0b53a6db841d9c7 100644 (file)
@@ -1,4 +1,4 @@
-FROM php:8.1-fpm-alpine
+FROM php:8.1-fpm-alpine as root
 LABEL maintainer="Thomas Bruederli <thomas@roundcube.net>"
 LABEL org.opencontainers.image.source="https://github.com/roundcube/roundcubemail-docker"
 
@@ -110,7 +110,16 @@ RUN set -ex; \
        rm -rf /usr/src/roundcubemail/installer; \
        chown -R www-data:www-data /usr/src/roundcubemail/logs; \
 # Create the config dir
-       mkdir -p /var/roundcube/config /var/roundcube/enigma
+       mkdir -p /var/roundcube/config /var/roundcube/enigma; \
+       chown -R www-data:www-data /var/roundcube; \
+       chmod +t /var/roundcube
 
 ENTRYPOINT ["/docker-entrypoint.sh"]
 CMD ["php-fpm"]
+
+
+#### non-root stage
+
+FROM root as nonroot
+
+USER 82:82
\ No newline at end of file
index e493b51f3ca2d0f07dae80ec87e4f7c7c9a400da..95174b47f4f63570c91006b918dbaaa3acf6763e 100755 (executable)
@@ -189,9 +189,8 @@ if  [[ "$1" == apache2* || "$1" == php-fpm || "$1" == bin* ]]; then
 
   : "${ROUNDCUBEMAIL_LOCALE:=en_US.UTF-8 UTF-8}"
 
-  if [ -e /usr/sbin/locale-gen ] && [ ! -z "${ROUNDCUBEMAIL_LOCALE}" ]; then
-    echo "${ROUNDCUBEMAIL_LOCALE}" > /etc/locale.gen
-    /usr/sbin/locale-gen
+  if [ -e /usr/sbin/locale-gen ] && [ ! -f /etc/locale.gen ] && [ ! -z "${ROUNDCUBEMAIL_LOCALE}" ]; then
+    echo "${ROUNDCUBEMAIL_LOCALE}" > /etc/locale.gen && /usr/sbin/locale-gen
   fi
 
   if [ ! -z "${ROUNDCUBEMAIL_ASPELL_DICTS}" ]; then
index bb2f4259db714fbe227e0132c9fb73e1564667a2..1b20af5ca4d9ccdd0b97a7ad43bcd0eb4b2e952b 100644 (file)
@@ -1,4 +1,4 @@
-FROM php:8.1-fpm
+FROM php:8.1-fpm as root
 LABEL maintainer="Thomas Bruederli <thomas@roundcube.net>"
 LABEL org.opencontainers.image.source="https://github.com/roundcube/roundcubemail-docker"
 
@@ -122,7 +122,20 @@ RUN set -ex; \
        rm -rf /usr/src/roundcubemail/installer; \
        chown -R www-data:www-data /usr/src/roundcubemail/logs; \
 # Create the config dir
-       mkdir -p /var/roundcube/config /var/roundcube/enigma
+       mkdir -p /var/roundcube/config /var/roundcube/enigma; \
+       chown -R www-data:www-data /var/roundcube; \
+       chmod +t /var/roundcube
 
 ENTRYPOINT ["/docker-entrypoint.sh"]
 CMD ["php-fpm"]
+
+
+#### non-root stage
+
+FROM root as nonroot
+
+# Prepare locale config for locale-gen
+RUN    echo "en_US.UTF-8 UTF-8" > /etc/locale.gen; \
+       /usr/sbin/locale-gen
+
+USER 33:33
\ No newline at end of file
index e493b51f3ca2d0f07dae80ec87e4f7c7c9a400da..95174b47f4f63570c91006b918dbaaa3acf6763e 100755 (executable)
@@ -189,9 +189,8 @@ if  [[ "$1" == apache2* || "$1" == php-fpm || "$1" == bin* ]]; then
 
   : "${ROUNDCUBEMAIL_LOCALE:=en_US.UTF-8 UTF-8}"
 
-  if [ -e /usr/sbin/locale-gen ] && [ ! -z "${ROUNDCUBEMAIL_LOCALE}" ]; then
-    echo "${ROUNDCUBEMAIL_LOCALE}" > /etc/locale.gen
-    /usr/sbin/locale-gen
+  if [ -e /usr/sbin/locale-gen ] && [ ! -f /etc/locale.gen ] && [ ! -z "${ROUNDCUBEMAIL_LOCALE}" ]; then
+    echo "${ROUNDCUBEMAIL_LOCALE}" > /etc/locale.gen && /usr/sbin/locale-gen
   fi
 
   if [ ! -z "${ROUNDCUBEMAIL_ASPELL_DICTS}" ]; then
index 310ca841ce39d26f384b8a1c152556ed852c32da..a68c349f96ddea56b2e51a73e8f4204251fc7604 100644 (file)
@@ -1,4 +1,4 @@
-FROM php:8.1-%%VARIANT%%
+FROM php:8.1-%%VARIANT%% as root
 LABEL maintainer="Thomas Bruederli <thomas@roundcube.net>"
 LABEL org.opencontainers.image.source="https://github.com/roundcube/roundcubemail-docker"
 
@@ -110,7 +110,16 @@ RUN set -ex; \
        rm -rf /usr/src/roundcubemail/installer; \
        chown -R www-data:www-data /usr/src/roundcubemail/logs; \
 # Create the config dir
-       mkdir -p /var/roundcube/config /var/roundcube/enigma
+       mkdir -p /var/roundcube/config /var/roundcube/enigma; \
+       chown -R www-data:www-data /var/roundcube; \
+       chmod +t /var/roundcube
 
 ENTRYPOINT ["/docker-entrypoint.sh"]
 CMD ["%%CMD%%"]
+
+
+#### non-root stage
+
+FROM root as nonroot
+
+USER 82:82
\ No newline at end of file
index 57a96ecb2814720934ebcb46d8b4b2291b3b1b62..06ee4fcd2fdc6cad720693a7eadecebf2b4ee75f 100644 (file)
@@ -1,4 +1,4 @@
-FROM php:8.1-%%VARIANT%%
+FROM php:8.1-%%VARIANT%% as root
 LABEL maintainer="Thomas Bruederli <thomas@roundcube.net>"
 LABEL org.opencontainers.image.source="https://github.com/roundcube/roundcubemail-docker"
 
@@ -122,7 +122,22 @@ RUN set -ex; \
        rm -rf /usr/src/roundcubemail/installer; \
        chown -R www-data:www-data /usr/src/roundcubemail/logs; \
 # Create the config dir
-       mkdir -p /var/roundcube/config /var/roundcube/enigma
+       mkdir -p /var/roundcube/config /var/roundcube/enigma; \
+       chown -R www-data:www-data /var/roundcube; \
+       chmod +t /var/roundcube
 
 ENTRYPOINT ["/docker-entrypoint.sh"]
 CMD ["%%CMD%%"]
+
+
+#### non-root stage
+
+FROM root as nonroot
+
+# Prepare locale config for locale-gen
+RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen; \
+       /usr/sbin/locale-gen
+
+%%NONROOT_ADD%%
+
+USER 33:33
\ No newline at end of file
index e493b51f3ca2d0f07dae80ec87e4f7c7c9a400da..95174b47f4f63570c91006b918dbaaa3acf6763e 100644 (file)
@@ -189,9 +189,8 @@ if  [[ "$1" == apache2* || "$1" == php-fpm || "$1" == bin* ]]; then
 
   : "${ROUNDCUBEMAIL_LOCALE:=en_US.UTF-8 UTF-8}"
 
-  if [ -e /usr/sbin/locale-gen ] && [ ! -z "${ROUNDCUBEMAIL_LOCALE}" ]; then
-    echo "${ROUNDCUBEMAIL_LOCALE}" > /etc/locale.gen
-    /usr/sbin/locale-gen
+  if [ -e /usr/sbin/locale-gen ] && [ ! -f /etc/locale.gen ] && [ ! -z "${ROUNDCUBEMAIL_LOCALE}" ]; then
+    echo "${ROUNDCUBEMAIL_LOCALE}" > /etc/locale.gen && /usr/sbin/locale-gen
   fi
 
   if [ ! -z "${ROUNDCUBEMAIL_ASPELL_DICTS}" ]; then
index 578d931ea74584b752fbcf09516dffc88acfa4f6..0967a0aa669d2631627b15c33f4ab2b01847ab94 100644 (file)
@@ -3,9 +3,11 @@ version: "2"
 services:
   roundcubemail:
     image: ${ROUNDCUBEMAIL_TEST_IMAGE:-roundcube/roundcubemail:latest-apache}
+    ports:
+      - 80:${HTTP_PORT:-80}
     healthcheck:
       # To make it obvious in logs "ping=ping" is added
-      test: ["CMD", "curl", "--fail", "http://localhost/?ping=ping"]
+      test: ["CMD", "curl", "--fail", "http://localhost:${HTTP_PORT:-80}/?ping=ping"]
       interval: 2s
       timeout: 3s
       retries: 30
@@ -55,6 +57,8 @@ services:
       roundcubedb:
         condition: service_healthy
     command: /tests/run.sh
+    environment:
+      - ROUNDCUBE_URL=http://roundcubemail:${HTTP_PORT:-80}/
     volumes:
       - ./run.sh:/tests/run.sh:ro
     working_dir: /tests
index 1887cbb78b91fbf6538d9665a968775faeda749b..e0ee96fc8609a5acb019446797e29eb2a8988590 100755 (executable)
--- a/update.sh
+++ b/update.sh
@@ -31,6 +31,12 @@ for variant in apache fpm fpm-alpine; do
                s/%%CMD%%/'"${CMD[$variant]}"'/;
        ' $template | tr '¬' '\n' > "$dir/Dockerfile"
 
+       if [[ -f "$dir/nonroot-add.txt" ]]; then
+               sed -i -e '/%%NONROOT_ADD%%/ {' -e 'r '"$dir/nonroot-add.txt" -e 'd' -e '}' $dir/Dockerfile
+       else
+               sed -i 's/%%NONROOT_ADD%%//' $dir/Dockerfile
+       fi
+
        echo "✓ Wrote $dir/Dockerfile"
 done
 
git clone https://git.99rst.org/PROJECT