fix(docker): keep C toolchain headers out of the runtime image - #43182
fix(docker): keep C toolchain headers out of the runtime image#43182bikash-barnwal wants to merge 1 commit into
Conversation
The `python-common` stage, which every final image (`lean`, `dev`, `ci`,
`showtime`) is built from, installed `libsasl2-dev`, `libpq-dev`,
`libecpg-dev` and `libldap2-dev`. Those `-dev` packages exist only to
provide C headers and static archives for compiling native Python
extensions, and they transitively pull a full C toolchain into every
final image: `libc6-dev`, `libc-dev-bin`, `libcrypt-dev`, `linux-libc-dev`,
`libssl-dev` and `libldap-dev`. None of them are ever removed, so a
production `lean` image shipped ten development packages it cannot use.
Each `-dev` package is replaced with the runtime shared library it
depends on, so no library that anything actually links against is lost:
libsasl2-dev -> libsasl2-2 (Cyrus SASL runtime, also needed by
libsasl2-modules-gssapi-mit)
libpq-dev -> libpq5 (PostgreSQL C client library)
libecpg-dev -> libecpg6 (ECPG runtime library)
libldap2-dev -> libldap2 (OpenLDAP runtime libraries)
All four runtime packages were already present in the image as
dependencies of the `-dev` packages, so this change is a strict
subset removal.
Nothing in `requirements/base.txt` (the `lean` dependency set) links
against these libraries, and the `postgres` extra used by `ci` and
`showtime` is `psycopg2-binary`, which bundles its own libpq. The
headers are only needed to build `python-ldap` and `mysqlclient` from
`requirements/development.txt`, so `libsasl2-dev`, `libldap2-dev` and
`libpq-dev` move to the `dev` stage next to the existing
`default-libmysqlclient-dev`.
`--no-install-recommends` hygiene is unchanged: installs still go
through `docker/apt-install.sh`.
No change is warranted for the `devlop` and `preact-devtools` npm names
in the reported SBOM. `node_modules` is never copied into a final
image - only `superset/static/assets` and `superset/translations` come
from the node stage. `devlop` is a production transitive dependency of
`react-markdown`/`micromark` (22 dependents in `package-lock.json`, none
marked `dev`), and no `preact-devtools` package exists in the lock file
at all; `preact` itself is a production dependency of
`@deck.gl/widgets`. Removing either would break markdown rendering and
deck.gl widgets.
Verified by building the `lean`, `ci` and `dev` targets locally.
`dpkg -l` in the resulting `lean` image lists no `-dev` package and no
compiler, all runtime libraries above are still installed, `superset
version` runs, and `psycopg2`/`duckdb` (`ci`) and
`python-ldap`/`mysqlclient`/`psycopg2` (`dev`) still import.
Fixes apache#43002
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Code Review Agent Run #23a8b7Actionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
| libldap2-dev | ||
| libpq5 \ | ||
| libecpg6 \ | ||
| libldap2 |
There was a problem hiding this comment.
Suggestion: The Debian trixie runtime package is versioned libldap-2.6-0, not libldap2. Since apt-install.sh passes package names directly to apt-get install without fallback, this causes the python-common stage and every descendant image to fail during construction. Replace it with the runtime package name provided by the selected Debian release. [api mismatch]
Severity Level: Critical 🚨
- ❌ `python-common` cannot build on Debian trixie.
- ❌ Lean and development images cannot be produced.
- ❌ Docker-based deployment and CI builds fail.Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** Dockerfile
**Line:** 207:207
**Comment:**
*Api Mismatch: The Debian trixie runtime package is versioned `libldap-2.6-0`, not `libldap2`. Since `apt-install.sh` passes package names directly to `apt-get install` without fallback, this causes the `python-common` stage and every descendant image to fail during construction. Replace it with the runtime package name provided by the selected Debian release.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix|
The flagged issue is correct. The package To resolve this, update the I have checked the available PR comments, and there are no other comments to address. Would you like me to implement this fix for you? Dockerfile |
SUMMARY
The
leanruntime image shipped a full set of C development packages.python-common— the shared ancestor oflean,dev,ciandshowtime— installedlibsasl2-dev,libpq-dev,libldap2-devandlibecpg-dev;apt-mark showmanualinside the builtleanimage confirms those four are the only manually installed offenders, withlibc6-dev,libc-dev-bin,libcrypt-dev,linux-libc-dev,libssl-devandlibldap-devarriving as their auto-deps.pip-install.shalready purgesbuild-essential, but never touched these.Each
-devpackage is replaced with its runtime shared library inpython-common, and the headers move to thedevstage, which is where native extensions are actually compiled:libsasl2-devpython-ldap)libsasl2-2;-devmoved todevlibpq-devpostgresextra ispsycopg2-binary, which bundles libpq)libpq5;-devmoved todevlibldap2-devpython-ldap,development.txtonly)libldap2;-devmoved todevlibecpg-devlibecpg6; not re-addedlibc6-dev,libc-dev-bin,libcrypt-dev,linux-libc-dev,libssl-dev,libldap-devlibsasl2-modules-gssapi-mitcurlFour packages from the report —
libpython3.11-dev,python3.11-dev,zlib1g-dev,libexpat1-dev— are not present in a currentmasterleanbuild. The base image builds CPython from source, so Debian'spython3.11-devisn't in the tree at all; those entries most likely come from an older base image or a Chromium/Playwright-enabled build. No action taken rather than a speculative one.On the npm side:
devlopis a genuine production dependency (22 dependents inpackage-lock.json—react-markdown,micromark,mdast-util-*), andpreact-devtoolsdoes not exist in the lock file at all, almost certainly a scanner mis-attribution of thepreact/devtoolssubmodule path. Worth noting for the reporter:node_modulesis never copied into a final image —python-commontakes onlysuperset/static/assets,service-worker.jsandsuperset/translationsfrom the node stage — so those names can reach an SBOM through bundled JS, not as installed packages.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
--target lean, built locally on amd64:-dev/dev-binpackagesNo
gcc,cc,makeorldin either.libpq5,libldap2,libsasl2-2,libsasl2-modules-gssapi-mit,libecpg6,libssl3t64andzlib1gare all still installed.TESTING INSTRUCTIONS
Verified locally (Docker 29.6.1, builds used
--build-arg DEV_MODE=trueto skip webpack, which touches no apt layer):leanruntime:import superset, flask, sqlalchemyandimport ssl, zlib, sqlite3all fine;superset versionprints, exercising the full app import path.citarget builds;psycopg2 2.9.12andduckdb 1.5.5import, and a realduckdb:///:memory:SQLAlchemy query returns.devtarget builds;ldap 3.4.7,MySQLdb,psycopg2andsupersetall import — sopython-ldapandmysqlclientstill compile against the headers in their new location.Not verified:
linux/arm64(only the local amd64 platform was built); a fullDEV_MODE=falsefrontend build, so the emittedstatic/assetswere not scanned fordevlop/preactstrings — that conclusion rests on lock-file dependency flags and theCOPY --from=superset-nodescope. Theshowtimetarget wasn't built, but it islean+.[duckdb], a strict subset of thecitarget that was.One honest side effect: installing
libssl-devused to incidentally upgradelibssl3t64from the base image's3.5.4to3.5.6. Without it the image keeps the pinned base image's3.5.4. That is the ordinary consequence of not pulling in extra packages and resolves wheneverPY_VERis bumped, but a scanner diffing before/after will see that one version move backwards.ADDITIONAL INFORMATION
🤖 Generated with Claude Code