From b66d4ade4160b0f13efa4fb48a6c27884ad81804 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Fri, 12 Dec 2025 22:07:19 +0100 Subject: [PATCH] Improve Docker + compatibility Arch (#8299) * Better comments in our Docker images * Make `cli/access-permissions.sh` compatible with other Apache groups such as `http` for Linux Arch * Better `/Docker/entrypoint.sh` supporting various Apache configuration paths (and slightly faster). * Add test image for Linux Arch (not sure we will keep it) See * https://github.com/FreshRSS/FreshRSS/pull/8279#issuecomment-3620674818 --- .devcontainer/Dockerfile | 9 +++-- Docker/Dockerfile | 20 +++++++----- Docker/Dockerfile-Alpine | 14 +++++--- Docker/Dockerfile-Arch | 69 +++++++++++++++++++++++++++++++++++++++ Docker/Dockerfile-Newest | 15 ++++++--- Docker/Dockerfile-Oldest | 15 ++++++--- Docker/entrypoint.sh | 27 ++++++++++++--- cli/access-permissions.sh | 13 +++++++- 8 files changed, 151 insertions(+), 31 deletions(-) create mode 100644 Docker/Dockerfile-Arch diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3db323983..31abb1c5a 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -11,13 +11,16 @@ RUN apk add --no-cache \ php-pdo_sqlite php-pdo_mysql php-pdo_pgsql \ bash composer curl docker-cli-buildx git gpg make nodejs npm shellcheck shfmt sudo -RUN rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ +RUN \ + # Disable unwanted Apache modules and configurations + rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ /etc/apache2/conf.d/status.conf /etc/apache2/conf.d/userdir.conf && \ sed -r -i "/^\s*LoadModule .*mod_(alias|autoindex|negotiation|status).so$/s/^/#/" \ /etc/apache2/httpd.conf && \ - sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" \ - /etc/apache2/httpd.conf && \ sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" \ + /etc/apache2/httpd.conf && \ + # Enable required Apache modules + sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" \ /etc/apache2/httpd.conf RUN adduser --ingroup www-data --disabled-password developer && \ diff --git a/Docker/Dockerfile b/Docker/Dockerfile index 5da0e021a..9e9ae54a0 100644 --- a/Docker/Dockerfile +++ b/Docker/Dockerfile @@ -23,7 +23,6 @@ ARG FRESHRSS_VERSION ARG SOURCE_COMMIT LABEL \ - org.opencontainers.image.authors="Alkarex" \ org.opencontainers.image.description="A self-hosted RSS feed aggregator" \ org.opencontainers.image.documentation="https://freshrss.github.io/FreshRSS/" \ org.opencontainers.image.licenses="AGPL-3.0" \ @@ -34,18 +33,23 @@ LABEL \ org.opencontainers.image.vendor="FreshRSS" \ org.opencontainers.image.version="$FRESHRSS_VERSION" -RUN a2dismod -q -f alias autoindex negotiation status && \ +RUN \ + # Disable unwanted Apache modules and configurations + a2dismod -q -f alias autoindex negotiation status && \ a2dismod -q auth_openidc && \ - phpdismod calendar exif ffi ftp gettext mysqli posix readline shmop sockets sysvmsg sysvsem sysvshm xsl && \ - a2enmod -q deflate expires filter headers mime remoteip setenvif && \ a2disconf -q '*' && \ a2dissite -q '*' && \ - a2ensite -q 'FreshRSS*' - -RUN sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" /etc/apache2/apache2.conf && \ + sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" /etc/apache2/apache2.conf && \ sed -r -i "/^\s*Listen /s/^/#/" /etc/apache2/ports.conf && \ - # Disable built-in updates when using Docker, as the full image is supposed to be updated instead. + # Enable required Apache modules + a2enmod -q deflate expires filter headers mime remoteip setenvif && \ + # Enable FreshRSS configuration for Apache + a2ensite -q 'FreshRSS*' && \ + # Disable unwanted PHP modules + phpdismod calendar exif ffi ftp gettext mysqli posix readline shmop sockets sysvmsg sysvsem sysvshm xsl && \ + # Disable built-in FreshRSS updates when using Docker, as the full image is supposed to be updated instead sed -r -i "\\#disable_update#s#^.*#\t'disable_update' => true,#" ./config.default.php && \ + # Configure cron job touch /var/www/FreshRSS/Docker/env.txt && \ echo "7,37 * * * * . /var/www/FreshRSS/Docker/env.txt; \ su www-data -s /bin/sh -c 'php /var/www/FreshRSS/app/actualize_script.php' \ diff --git a/Docker/Dockerfile-Alpine b/Docker/Dockerfile-Alpine index 0307d580e..1c688742f 100644 --- a/Docker/Dockerfile-Alpine +++ b/Docker/Dockerfile-Alpine @@ -20,7 +20,6 @@ ARG FRESHRSS_VERSION ARG SOURCE_COMMIT LABEL \ - org.opencontainers.image.authors="Alkarex" \ org.opencontainers.image.description="A self-hosted RSS feed aggregator" \ org.opencontainers.image.documentation="https://freshrss.github.io/FreshRSS/" \ org.opencontainers.image.licenses="AGPL-3.0" \ @@ -31,17 +30,22 @@ LABEL \ org.opencontainers.image.vendor="FreshRSS" \ org.opencontainers.image.version="$FRESHRSS_VERSION" -RUN rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ +RUN \ + # Disable unwanted Apache modules and configurations + rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ /etc/apache2/conf.d/status.conf /etc/apache2/conf.d/userdir.conf && \ sed -r -i "/^\s*LoadModule .*mod_(alias|autoindex|negotiation|status).so$/s/^/#/" \ /etc/apache2/httpd.conf && \ - sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" \ - /etc/apache2/httpd.conf && \ sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" \ /etc/apache2/httpd.conf && \ + # Enable required Apache modules + sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" \ + /etc/apache2/httpd.conf && \ + # PHP configuration if [ ! -f /usr/bin/php ]; then ln -s /usr/bin/php84 /usr/bin/php; else true; fi && \ - # Disable built-in updates when using Docker, as the full image is supposed to be updated instead. + # Disable built-in FreshRSS updates when using Docker, as the full image is supposed to be updated instead sed -r -i "\\#disable_update#s#^.*#\t'disable_update' => true,#" ./config.default.php && \ + # Configure cron job touch /var/www/FreshRSS/Docker/env.txt && \ echo "27,57 * * * * . /var/www/FreshRSS/Docker/env.txt; \ su apache -s /bin/sh -c 'php /var/www/FreshRSS/app/actualize_script.php' \ diff --git a/Docker/Dockerfile-Arch b/Docker/Dockerfile-Arch new file mode 100644 index 000000000..44860826f --- /dev/null +++ b/Docker/Dockerfile-Arch @@ -0,0 +1,69 @@ +# Test image for development +# hadolint ignore=DL3006 +FROM archlinux + +ENV TZ=UTC +SHELL ["/bin/bash", "-eo", "pipefail", "-c"] + +RUN pacman -Syu --noconfirm && pacman -S --noconfirm \ + cronie \ + apache php-apache \ + php \ + php-sqlite php-pgsql \ + && pacman -Scc --noconfirm + +RUN mkdir -p /var/www/FreshRSS /run/httpd/ +WORKDIR /var/www/FreshRSS + +COPY --chown=root:http . /var/www/FreshRSS +COPY ./Docker/*.Apache.conf /etc/httpd/conf/conf.d/ + +ARG FRESHRSS_VERSION +ARG SOURCE_COMMIT + +LABEL \ + org.opencontainers.image.description="A self-hosted RSS feed aggregator" \ + org.opencontainers.image.documentation="https://freshrss.github.io/FreshRSS/" \ + org.opencontainers.image.licenses="AGPL-3.0" \ + org.opencontainers.image.revision="${SOURCE_COMMIT}" \ + org.opencontainers.image.source="https://github.com/FreshRSS/FreshRSS" \ + org.opencontainers.image.title="FreshRSS" \ + org.opencontainers.image.url="https://freshrss.org/" \ + org.opencontainers.image.vendor="FreshRSS" \ + org.opencontainers.image.version="$FRESHRSS_VERSION" + +RUN \ + # Disable unwanted Apache modules and configurations + sed -r -i "/^\s*LoadModule .*mod_(alias|autoindex|negotiation|status).so$/s/^/#/" /etc/httpd/conf/httpd.conf && \ + sed -r -i "/^\s*Include .*\/(httpd-autoindex|httpd-languages|httpd-multilang-errordoc|httpd-userdir|proxy-html).conf$/s/^/#/" /etc/httpd/conf/httpd.conf && \ + sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" /etc/httpd/conf/httpd.conf && \ + # Enable required Apache modules + sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" /etc/httpd/conf/httpd.conf && \ + # Configure PHP for Apache + sed -r -i 's|^#?LoadModule mpm_event_module|#LoadModule mpm_event_module|' /etc/httpd/conf/httpd.conf && \ + sed -r -i 's|^#?LoadModule mpm_prefork_module|LoadModule mpm_prefork_module|' /etc/httpd/conf/httpd.conf && \ + sed -r -i '/LoadModule mpm_prefork_module.*/a LoadModule php_module modules/libphp.so\nAddHandler php-script .php' /etc/httpd/conf/httpd.conf && \ + # Enable required PHP extensions + sed -r -i "/;extension=(curl|gmp|iconv|intl|pdo_mysql|pdo_pgsql|pdo_sqlite|zip)$/s/^;//" /etc/php/php.ini && \ + # Disable built-in FreshRSS updates when using Docker, as the full image is supposed to be updated instead + sed -r -i "\\#disable_update#s#^.*#\t'disable_update' => true,#" ./config.default.php && \ + touch /var/www/FreshRSS/Docker/env.txt && \ + echo "17,47 * * * * . /var/www/FreshRSS/Docker/env.txt; \ + su http -s /bin/sh -c 'php /var/www/FreshRSS/app/actualize_script.php' \ + 2>> /proc/1/fd/2 > /tmp/FreshRSS.log" > /etc/crontab.freshrss.default + +ENV COPY_LOG_TO_SYSLOG=On +ENV COPY_SYSLOG_TO_STDERR=On +ENV CRON_MIN='' +ENV DATA_PATH='' +ENV FRESHRSS_ENV='' +ENV LISTEN='' +ENV OIDC_ENABLED='' +ENV TRUSTED_PROXY='' + +ENTRYPOINT ["./Docker/entrypoint.sh"] + +EXPOSE 80 +# hadolint ignore=DL3025 +CMD ([ -z "$CRON_MIN" ] || crond) && \ + exec httpd -D FOREGROUND diff --git a/Docker/Dockerfile-Newest b/Docker/Dockerfile-Newest index cb959cf5b..a7c2c8265 100644 --- a/Docker/Dockerfile-Newest +++ b/Docker/Dockerfile-Newest @@ -1,3 +1,4 @@ +# Test image for development FROM alpine:edge ENV TZ=UTC @@ -21,7 +22,6 @@ ARG FRESHRSS_VERSION ARG SOURCE_COMMIT LABEL \ - org.opencontainers.image.authors="Alkarex" \ org.opencontainers.image.description="A self-hosted RSS feed aggregator" \ org.opencontainers.image.documentation="https://freshrss.github.io/FreshRSS/" \ org.opencontainers.image.licenses="AGPL-3.0" \ @@ -32,19 +32,24 @@ LABEL \ org.opencontainers.image.vendor="FreshRSS" \ org.opencontainers.image.version="$FRESHRSS_VERSION" -RUN rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ +RUN \ + # Disable unwanted Apache modules and configurations + rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ /etc/apache2/conf.d/status.conf /etc/apache2/conf.d/userdir.conf && \ sed -r -i "/^\s*LoadModule .*mod_(alias|autoindex|negotiation|status).so$/s/^/#/" \ /etc/apache2/httpd.conf && \ - sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" \ - /etc/apache2/httpd.conf && \ sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" \ /etc/apache2/httpd.conf && \ mv /etc/apache2/conf.d/mod-auth-openidc.conf /etc/apache2/conf.d/mod-auth-openidc.conf.bak && \ + # Enable required Apache modules + sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" \ + /etc/apache2/httpd.conf && \ + # PHP configuration if [ ! -f /usr/bin/php ]; then ln -s /usr/bin/php85 /usr/bin/php; else true; fi && \ echo 'memory_limit = 256M' > /etc/php85/conf.d/10_memory.ini && \ - # Disable built-in updates when using Docker, as the full image is supposed to be updated instead. + # Disable built-in FreshRSS updates when using Docker, as the full image is supposed to be updated instead. sed -r -i "\\#disable_update#s#^.*#\t'disable_update' => true,#" ./config.default.php && \ + # Configure cron job touch /var/www/FreshRSS/Docker/env.txt && \ echo "27,57 * * * * . /var/www/FreshRSS/Docker/env.txt; \ su apache -s /bin/sh -c 'php /var/www/FreshRSS/app/actualize_script.php' \ diff --git a/Docker/Dockerfile-Oldest b/Docker/Dockerfile-Oldest index f827adcaf..c76f896dd 100644 --- a/Docker/Dockerfile-Oldest +++ b/Docker/Dockerfile-Oldest @@ -1,3 +1,4 @@ +# Test image for development FROM alpine:3.16 ENV TZ=UTC @@ -20,7 +21,6 @@ ARG FRESHRSS_VERSION ARG SOURCE_COMMIT LABEL \ - org.opencontainers.image.authors="Alkarex" \ org.opencontainers.image.description="A self-hosted RSS feed aggregator" \ org.opencontainers.image.documentation="https://freshrss.github.io/FreshRSS/" \ org.opencontainers.image.licenses="AGPL-3.0" \ @@ -31,18 +31,23 @@ LABEL \ org.opencontainers.image.vendor="FreshRSS" \ org.opencontainers.image.version="$FRESHRSS_VERSION" -RUN rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ +RUN \ + # Disable unwanted Apache modules and configurations + rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ /etc/apache2/conf.d/status.conf /etc/apache2/conf.d/userdir.conf && \ sed -r -i "/^\s*LoadModule .*mod_(alias|autoindex|negotiation|status).so$/s/^/#/" \ /etc/apache2/httpd.conf && \ - sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" \ - /etc/apache2/httpd.conf && \ sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" \ /etc/apache2/httpd.conf && \ + # Enable required Apache modules + sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|filter|headers|mime|remoteip|setenvif).so$/s/^\s*#//" \ + /etc/apache2/httpd.conf && \ + # PHP configuration if [ ! -f /usr/bin/php ]; then ln -s /usr/bin/php81 /usr/bin/php; else true; fi && \ echo 'memory_limit = 256M' > /etc/php81/conf.d/10_memory.ini && \ - # Disable built-in updates when using Docker, as the full image is supposed to be updated instead. + # Disable built-in FreshRSS updates when using Docker, as the full image is supposed to be updated instead. sed -r -i "\\#disable_update#s#^.*#\t'disable_update' => true,#" ./config.default.php && \ + # Configure cron job touch /var/www/FreshRSS/Docker/env.txt && \ echo "27,57 * * * * . /var/www/FreshRSS/Docker/env.txt; \ su apache -s /bin/sh -c 'php /var/www/FreshRSS/app/actualize_script.php' \ diff --git a/Docker/entrypoint.sh b/Docker/entrypoint.sh index 88e00bbce..b7c06c672 100755 --- a/Docker/entrypoint.sh +++ b/Docker/entrypoint.sh @@ -8,17 +8,33 @@ find /etc/php*/ -type f -name php.ini -exec sed -i -E \ -e "\\#^;?post_max_size#s#^.*#post_max_size = 32M#" \ -e "\\#^;?upload_max_filesize#s#^.*#upload_max_filesize = 32M#" {} \; +while read -r config_path _; do + if [ -f "$config_path" ]; then + APACHE_CONFIG="$config_path" + break + fi +done </dev/null && a2enmod -q auth_openidc) || # Alpine - (mv /etc/apache2/conf.d/mod-auth-openidc.conf.bak /etc/apache2/conf.d/mod-auth-openidc.conf && echo 'Enabling module auth_openidc.') + (mv /etc/apache2/conf.d/mod-auth-openidc.conf.bak /etc/apache2/conf.d/mod-auth-openidc.conf && echo 'Enabling module auth_openidc.') || + # Misc. + (echo '❌ Failed to enable auth_openidc module!' && exit 12) + if [ -n "$OIDC_SCOPES" ]; then # Compatibility with : as separator instead of space OIDC_SCOPES=$(echo "$OIDC_SCOPES" | tr ':' ' ') diff --git a/cli/access-permissions.sh b/cli/access-permissions.sh index 1286d34aa..73ae54f35 100755 --- a/cli/access-permissions.sh +++ b/cli/access-permissions.sh @@ -22,8 +22,19 @@ fi mkdir -p "${data_path}/users/_/" +if getent group www-data >/dev/null; then + www_group="www-data" # Debian, Alpine +elif getent group apache >/dev/null; then + www_group="apache" # Alpine +elif getent group http >/dev/null; then + www_group="http" # Arch Linux +else + echo >&2 '⛔ No Apache group {www-data, apache, http} found!' + exit 4 +fi + # Based on group access -chown -R :www-data "$data_path" "$to_update" +chown -R :$www_group "$data_path" "$to_update" # Read files, and directory traversal chmod -R g+rX "$data_path" "$to_update"