-
-
Notifications
You must be signed in to change notification settings - Fork 338
Refactor Dockerfile.debian for multi-stage build and hardening #1442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Refactor Dockerfile to improve structure and security.
📝 WalkthroughWalkthroughReplaces a single-stage Debian image with a multi-stage Dockerfile (builder, runner, hardened), adding build/runtime scaffolding, explicit read-only/read-write folder delineation, environment variables for NetAlertX paths, lifecycle bootstrap scripts, and a healthcheck; applies permission hardening and runtime pruning. Changes
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@Dockerfile.debian`:
- Around line 42-49: There is a duplicate environment variable declaration for
NETALERTX_BACK; remove the redundant ENV NETALERTX_BACK line so the variable is
only defined once (keep the original intended definition and delete the
duplicate), and verify NETALERTX_BACK is referenced consistently with
NETALERTX_APP elsewhere (no other ENV entries rely on the removed line).
- Line 235: Replace the dummy sudo script content written by the current printf
invocation that creates /usr/bin/sudo so it uses exec and correct argument
quoting; instead of writing '#!/bin/sh\n"$@"\n' produce a script that starts
with the shebang and calls exec "$@" to forward and execute the original argv
list (then keep the chmod +x). Locate the printf that writes /usr/bin/sudo and
change the string it writes to include exec "$@" with proper quoting.
🧹 Nitpick comments (5)
Dockerfile.debian (5)
94-94: Hardcoded Python version in PYTHONPATH.The path
python3.11is hardcoded. While Debian bookworm ships with Python 3.11, consider making this dynamic for maintainability:Alternative approach
-ENV PYTHONPATH=${NETALERTX_APP}:${NETALERTX_SERVER}:${NETALERTX_PLUGINS}:${VIRTUAL_ENV}/lib/python3.11/site-packages +ENV PYTHONPATH=${NETALERTX_APP}:${NETALERTX_SERVER}:${NETALERTX_PLUGINS}The virtual environment's
site-packagesis typically already on the path when the venv is activated viaPATH.
138-139: Consider verifying the GPG key fingerprint for the PHP repository.The GPG key is downloaded over HTTPS but not verified against a known fingerprint. For supply-chain security, consider adding fingerprint verification:
Proposed fix
- && wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg \ + && wget -qO /tmp/php.gpg https://packages.sury.org/php/apt.gpg \ + && gpg --dearmor -o /etc/apt/trusted.gpg.d/php.gpg /tmp/php.gpg \ + && rm /tmp/php.gpg \Alternatively, document the expected fingerprint in a comment for auditability.
191-196: Commented-out code should be addressed or removed.There are several commented-out lines:
- Lines 191-192: Python setcap (with a note about dynamic path)
- Lines 195-196: Cron init (with a note about Debian differences)
If these are intentionally disabled, consider adding TODO/FIXME comments with issue references, or remove if not needed.
110-110:tiniis installed but not used in ENTRYPOINT.
tiniis installed as an init system to handle zombie processes and signal forwarding, but the entrypoints use/bin/bashand/root-entrypoint.shdirectly without tini.Consider using tini in entrypoint
-ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] +ENTRYPOINT ["/usr/bin/tini", "--", "/bin/bash", "/entrypoint.sh"]And for the hardened stage:
-ENTRYPOINT ["/root-entrypoint.sh"] +ENTRYPOINT ["/usr/bin/tini", "--", "/root-entrypoint.sh"]
237-238: Add a clarifying comment about the permission-priming rationale for running as root initially.The
/root-entrypoint.shscript does properly drop privileges to thenetalertxuser (UID 20211 by default) viasu-execafter performing permission-priming operations on mounted volumes. This is intentional for handling host volume ownership issues on appliances like Synology where Docker volume copy-up is limited. However, this design is not obvious from the Dockerfile alone and would benefit from a brief inline comment beforeUSER 0:# Run as root initially for best-effort permission priming on host mounts # (privileges are dropped by root-entrypoint.sh via su-exec after initialization) USER 0 ENTRYPOINT ["/root-entrypoint.sh"]The hardening efforts remain effective since the application runs as the unprivileged
netalertxuser after the entrypoint completes.
Co-authored-by: Jokob @netalertx <96159884+jokob-sk@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@Dockerfile.debian`:
- Around line 106-149: The Dockerfile RUN installation block is missing
libcap2-bin, causing subsequent setcap calls (used to grant raw socket
capabilities to nmap, arp-scan, nbtscan, traceroute) to fail; update the apt-get
install list inside the RUN that installs system packages (the multi-line RUN
where packages like nmap, arp-scan, nbtscan, traceroute, php8.3-*, gosu are
installed) to include libcap2-bin so setcap is available during the build and
the later setcap invocations succeed.
♻️ Duplicate comments (1)
Dockerfile.debian (1)
216-234: Dummy sudo script doesn’t exec argv correctly.
"$@"alone doesn’t execute the command and collapses args. This was raised previously and still appears unchanged.🐛 Proposed fix
- printf '#!/bin/sh\n"$@"\n' > /usr/bin/sudo && chmod +x /usr/bin/sudo + printf '#!/bin/sh\nexec "$@"\n' > /usr/bin/sudo && chmod +x /usr/bin/sudo
🧹 Nitpick comments (1)
Dockerfile.debian (1)
90-104: Avoid hard-coding the Python minor version inPYTHONPATH.
python3.11can drift if the base image changes; the venv already injects site-packages. Consider only app paths here (or derive dynamically).♻️ Proposed adjustment
-ENV PYTHONPATH=${NETALERTX_APP}:${NETALERTX_SERVER}:${NETALERTX_PLUGINS}:${VIRTUAL_ENV}/lib/python3.11/site-packages +ENV PYTHONPATH=${NETALERTX_APP}:${NETALERTX_SERVER}:${NETALERTX_PLUGINS}
| # Install dependencies | ||
| # Using sury.org for PHP 8.3 to match Alpine version | ||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||
| tini snmp ca-certificates curl libwww-perl arp-scan sudo gettext-base \ | ||
| nginx-light php php-cgi php-fpm php-sqlite3 php-curl sqlite3 dnsutils net-tools \ | ||
| python3 python3-dev iproute2 nmap fping python3-pip zip git systemctl usbutils traceroute nbtscan openrc \ | ||
| busybox nginx nginx-core mtr python3-venv && \ | ||
| rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # While php8.3 is in debian bookworm repos, php-fpm is not included so we need to add sury.org repo | ||
| # (Ondřej Surý maintains php packages for debian. This is temp until debian includes php-fpm in their | ||
| # repos. Likely it will be in Debian Trixie.). This keeps the image up-to-date with the alpine version. | ||
| # hadolint ignore=DL3008 | ||
| RUN apt-get install -y --no-install-recommends \ | ||
| apt-transport-https \ | ||
| tini \ | ||
| snmp \ | ||
| ca-certificates \ | ||
| curl \ | ||
| libwww-perl \ | ||
| arp-scan \ | ||
| sudo \ | ||
| gettext-base \ | ||
| nginx-light \ | ||
| sqlite3 \ | ||
| dnsutils \ | ||
| net-tools \ | ||
| python3 \ | ||
| iproute2 \ | ||
| nmap \ | ||
| fping \ | ||
| zip \ | ||
| git \ | ||
| usbutils \ | ||
| traceroute \ | ||
| nbtscan \ | ||
| lsb-release \ | ||
| wget && \ | ||
| wget -q -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg && \ | ||
| echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list && \ | ||
| apt-get update && \ | ||
| apt-get install -y --no-install-recommends php8.3-fpm php8.3-cli php8.3-sqlite3 php8.3-common php8.3-curl php8.3-cgi && \ | ||
| ln -s /usr/sbin/php-fpm8.3 /usr/sbin/php-fpm83 && \ | ||
| rm -rf /var/lib/apt/lists/* # make it compatible with alpine version | ||
|
|
||
| # Setup virtual python environment and use pip3 to install packages | ||
| RUN python3 -m venv ${VIRTUAL_ENV} && \ | ||
| /bin/bash -c "source ${VIRTUAL_ENV_BIN}/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install -r ${INSTALL_DIR}/requirements.txt" | ||
|
|
||
| # Configure php-fpm | ||
| RUN chmod -R 755 /services && \ | ||
| chown -R ${USER}:${USER_GID} /services && \ | ||
| sed -i 's/^;listen.mode = .*/listen.mode = 0666/' ${SYSTEM_SERVICES_PHP_FPM_D}/www.conf && \ | ||
| printf "user = %s\ngroup = %s\n" "${USER}" "${USER_GID}" >> /services/config/php/php-fpm.d/www.conf | ||
|
|
||
|
|
||
|
|
||
| # Create a buildtimestamp.txt to later check if a new version was released | ||
| RUN date +%s > ${INSTALL_DIR}/front/buildtimestamp.txt | ||
| USER netalertx:netalertx | ||
| ENTRYPOINT ["/bin/bash","/entrypoint.sh"] | ||
|
|
||
|
|
||
| wget \ | ||
| apt-transport-https \ | ||
| gnupg2 \ | ||
| mtr \ | ||
| procps \ | ||
| gosu \ | ||
| && wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg \ | ||
| && echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list \ | ||
| && apt-get update \ | ||
| && apt-get install -y --no-install-recommends \ | ||
| php8.3-fpm \ | ||
| php8.3-cli \ | ||
| php8.3-sqlite3 \ | ||
| php8.3-common \ | ||
| php8.3-curl \ | ||
| && ln -s /usr/sbin/php-fpm8.3 /usr/sbin/php-fpm \ | ||
| && ln -s /usr/sbin/php-fpm8.3 /usr/sbin/php-fpm83 \ | ||
| && ln -s /usr/sbin/gosu /usr/sbin/su-exec \ | ||
| && rm -rf /var/lib/apt/lists/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Search for setcap usage in Dockerfile.debian
rg "setcap" Dockerfile.debianRepository: netalertx/NetAlertX
Length of output: 429
🏁 Script executed:
# Also check the full context of the Dockerfile
wc -l Dockerfile.debianRepository: netalertx/NetAlertX
Length of output: 84
🏁 Script executed:
# Get the full Dockerfile to understand the context
cat Dockerfile.debianRepository: netalertx/NetAlertX
Length of output: 9102
Install libcap2-bin for setcap usage.
setcap is invoked later in the RUN block to set capabilities for raw socket access on nmap, arp-scan, nbtscan, and traceroute; without libcap2-bin the build will fail.
Proposed fix
mtr \
procps \
+ libcap2-bin \
gosu \📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Install dependencies | |
| # Using sury.org for PHP 8.3 to match Alpine version | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| tini snmp ca-certificates curl libwww-perl arp-scan sudo gettext-base \ | |
| nginx-light php php-cgi php-fpm php-sqlite3 php-curl sqlite3 dnsutils net-tools \ | |
| python3 python3-dev iproute2 nmap fping python3-pip zip git systemctl usbutils traceroute nbtscan openrc \ | |
| busybox nginx nginx-core mtr python3-venv && \ | |
| rm -rf /var/lib/apt/lists/* | |
| # While php8.3 is in debian bookworm repos, php-fpm is not included so we need to add sury.org repo | |
| # (Ondřej Surý maintains php packages for debian. This is temp until debian includes php-fpm in their | |
| # repos. Likely it will be in Debian Trixie.). This keeps the image up-to-date with the alpine version. | |
| # hadolint ignore=DL3008 | |
| RUN apt-get install -y --no-install-recommends \ | |
| apt-transport-https \ | |
| tini \ | |
| snmp \ | |
| ca-certificates \ | |
| curl \ | |
| libwww-perl \ | |
| arp-scan \ | |
| sudo \ | |
| gettext-base \ | |
| nginx-light \ | |
| sqlite3 \ | |
| dnsutils \ | |
| net-tools \ | |
| python3 \ | |
| iproute2 \ | |
| nmap \ | |
| fping \ | |
| zip \ | |
| git \ | |
| usbutils \ | |
| traceroute \ | |
| nbtscan \ | |
| lsb-release \ | |
| wget && \ | |
| wget -q -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg && \ | |
| echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list && \ | |
| apt-get update && \ | |
| apt-get install -y --no-install-recommends php8.3-fpm php8.3-cli php8.3-sqlite3 php8.3-common php8.3-curl php8.3-cgi && \ | |
| ln -s /usr/sbin/php-fpm8.3 /usr/sbin/php-fpm83 && \ | |
| rm -rf /var/lib/apt/lists/* # make it compatible with alpine version | |
| # Setup virtual python environment and use pip3 to install packages | |
| RUN python3 -m venv ${VIRTUAL_ENV} && \ | |
| /bin/bash -c "source ${VIRTUAL_ENV_BIN}/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install -r ${INSTALL_DIR}/requirements.txt" | |
| # Configure php-fpm | |
| RUN chmod -R 755 /services && \ | |
| chown -R ${USER}:${USER_GID} /services && \ | |
| sed -i 's/^;listen.mode = .*/listen.mode = 0666/' ${SYSTEM_SERVICES_PHP_FPM_D}/www.conf && \ | |
| printf "user = %s\ngroup = %s\n" "${USER}" "${USER_GID}" >> /services/config/php/php-fpm.d/www.conf | |
| # Create a buildtimestamp.txt to later check if a new version was released | |
| RUN date +%s > ${INSTALL_DIR}/front/buildtimestamp.txt | |
| USER netalertx:netalertx | |
| ENTRYPOINT ["/bin/bash","/entrypoint.sh"] | |
| wget \ | |
| apt-transport-https \ | |
| gnupg2 \ | |
| mtr \ | |
| procps \ | |
| gosu \ | |
| && wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg \ | |
| && echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list \ | |
| && apt-get update \ | |
| && apt-get install -y --no-install-recommends \ | |
| php8.3-fpm \ | |
| php8.3-cli \ | |
| php8.3-sqlite3 \ | |
| php8.3-common \ | |
| php8.3-curl \ | |
| && ln -s /usr/sbin/php-fpm8.3 /usr/sbin/php-fpm \ | |
| && ln -s /usr/sbin/php-fpm8.3 /usr/sbin/php-fpm83 \ | |
| && ln -s /usr/sbin/gosu /usr/sbin/su-exec \ | |
| && rm -rf /var/lib/apt/lists/* | |
| # Install dependencies | |
| # Using sury.org for PHP 8.3 to match Alpine version | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| tini \ | |
| snmp \ | |
| ca-certificates \ | |
| curl \ | |
| libwww-perl \ | |
| arp-scan \ | |
| sudo \ | |
| gettext-base \ | |
| nginx-light \ | |
| sqlite3 \ | |
| dnsutils \ | |
| net-tools \ | |
| python3 \ | |
| iproute2 \ | |
| nmap \ | |
| fping \ | |
| zip \ | |
| git \ | |
| usbutils \ | |
| traceroute \ | |
| nbtscan \ | |
| lsb-release \ | |
| wget \ | |
| apt-transport-https \ | |
| gnupg2 \ | |
| mtr \ | |
| procps \ | |
| libcap2-bin \ | |
| gosu \ | |
| && wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg \ | |
| && echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list \ | |
| && apt-get update \ | |
| && apt-get install -y --no-install-recommends \ | |
| php8.3-fpm \ | |
| php8.3-cli \ | |
| php8.3-sqlite3 \ | |
| php8.3-common \ | |
| php8.3-curl \ | |
| && ln -s /usr/sbin/php-fpm8.3 /usr/sbin/php-fpm \ | |
| && ln -s /usr/sbin/php-fpm8.3 /usr/sbin/php-fpm83 \ | |
| && ln -s /usr/sbin/gosu /usr/sbin/su-exec \ | |
| && rm -rf /var/lib/apt/lists/* |
🤖 Prompt for AI Agents
In `@Dockerfile.debian` around lines 106 - 149, The Dockerfile RUN installation
block is missing libcap2-bin, causing subsequent setcap calls (used to grant raw
socket capabilities to nmap, arp-scan, nbtscan, traceroute) to fail; update the
apt-get install list inside the RUN that installs system packages (the
multi-line RUN where packages like nmap, arp-scan, nbtscan, traceroute,
php8.3-*, gosu are installed) to include libcap2-bin so setcap is available
during the build and the later setcap invocations succeed.
Refactor Dockerfile.debian to match alpine security, structure, compatibility, and startup.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.