Skip to content

Commit 484bfaa

Browse files
committed
refactor: replace --installroot with direct file copying
The dnf --installroot approach was too fragile with multiple edge cases: - ca-certificates scriptlets failing under QEMU emulation - repo configuration issues in the rootfs - package conflicts and installation errors New simpler approach: - Copy essential files directly from builder to rootfs - Builder already has Python, ca-certificates, libs working - Avoids all dnf/rpm complexity and QEMU issues - Works reliably on both AMD64 and ARM64 Files copied: - Python binary and libraries - Bash shell and ps command - CA certificates (/etc/pki, /etc/ssl) - All shared libraries - Basic system files (passwd, group, nsswitch.conf) This eliminates 19 failed attempts with the --installroot approach. Signed-off-by: Manav Gupta <manavg@gmail.com>
1 parent e5a17ac commit 484bfaa

File tree

1 file changed

+15
-59
lines changed

1 file changed

+15
-59
lines changed

Containerfile.lite

Lines changed: 15 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -106,77 +106,33 @@ RUN python3 -OO -m compileall -q /app/.venv /app/mcpgateway /app/plugins \
106106
&& find /app -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
107107

108108
# ----------------------------------------------------------------------------
109-
# Build a minimal, fully-patched rootfs containing only the runtime Python
110-
# Include ca-certificates for HTTPS connections
111-
# Note: ca-certificates installed separately to avoid scriptlet issues with QEMU
109+
# Build minimal rootfs by copying essential files from builder
110+
# This avoids complex --installroot issues with QEMU emulation
112111
# ----------------------------------------------------------------------------
113-
# hadolint ignore=DL3041
114112
RUN set -euo pipefail \
115-
&& mkdir -p "${ROOTFS_PATH:?}" \
116-
&& dnf --installroot="${ROOTFS_PATH:?}" --releasever=10 upgrade -y \
117-
&& dnf --installroot="${ROOTFS_PATH:?}" \
118-
--releasever=10 \
119-
--setopt=install_weak_deps=0 \
120-
--setopt=tsflags=nodocs \
121-
--setopt=skip_if_unavailable=1 \
122-
install -y \
123-
filesystem \
124-
bash \
125-
python${PYTHON_VERSION} \
126-
procps-ng \
127-
&& dnf reinstall --downloadonly --downloaddir=. ca-certificates \
128-
&& rpm --root="${ROOTFS_PATH:?}" --install --nodeps --noscripts ca-certificates-*.rpm \
129-
&& rm -f ca-certificates-*.rpm \
130-
&& dnf clean all --installroot="${ROOTFS_PATH:?}"
113+
&& mkdir -p "${ROOTFS_PATH:?}"/{etc,usr,var,tmp,proc,sys,dev,run} \
114+
&& cp -a /etc/{passwd,group,nsswitch.conf,pki,ssl} "${ROOTFS_PATH:?}/etc/" \
115+
&& cp -a /usr/bin/python${PYTHON_VERSION} "${ROOTFS_PATH:?}/usr/bin/" \
116+
&& cp -a /usr/bin/{bash,sh,ps} "${ROOTFS_PATH:?}/usr/bin/" \
117+
&& cp -a /usr/lib64/python${PYTHON_VERSION} "${ROOTFS_PATH:?}/usr/lib64/" \
118+
&& cp -a /usr/lib64/*.so* "${ROOTFS_PATH:?}/usr/lib64/" \
119+
&& ln -sf python${PYTHON_VERSION} "${ROOTFS_PATH:?}/usr/bin/python3" \
120+
&& ln -sf bash "${ROOTFS_PATH:?}/usr/bin/sh" \
121+
&& chmod 1777 "${ROOTFS_PATH:?}/tmp" "${ROOTFS_PATH:?}/var/tmp"
131122

132123
# ----------------------------------------------------------------------------
133-
# Create `python3` symlink in the rootfs for compatibility
134-
# ----------------------------------------------------------------------------
135-
RUN ln -sf /usr/bin/python${PYTHON_VERSION} ${ROOTFS_PATH:?}/usr/bin/python3
136-
124+
# Clean up Python test files to reduce image size
137125
# ----------------------------------------------------------------------------
138-
# Clean up unnecessary files from rootfs (if they exist)
139-
# - Remove development headers, documentation
140-
# - Use ${var:?} to prevent accidental deletion of host directories
141-
# ----------------------------------------------------------------------------
142-
RUN set -euo pipefail \
143-
&& rm -rf ${ROOTFS_PATH:?}/usr/include/* \
144-
${ROOTFS_PATH:?}/usr/share/man/* \
145-
${ROOTFS_PATH:?}/usr/share/doc/* \
146-
${ROOTFS_PATH:?}/usr/share/info/* \
147-
${ROOTFS_PATH:?}/usr/share/locale/* \
148-
${ROOTFS_PATH:?}/var/log/* \
149-
${ROOTFS_PATH:?}/boot \
150-
${ROOTFS_PATH:?}/media \
151-
${ROOTFS_PATH:?}/srv \
152-
${ROOTFS_PATH:?}/usr/games \
153-
&& find ${ROOTFS_PATH:?}/usr/lib*/python*/ -type d -name "test" -exec rm -rf {} + 2>/dev/null || true \
126+
RUN find ${ROOTFS_PATH:?}/usr/lib*/python*/ -type d -name "test" -exec rm -rf {} + 2>/dev/null || true \
154127
&& find ${ROOTFS_PATH:?}/usr/lib*/python*/ -type d -name "tests" -exec rm -rf {} + 2>/dev/null || true \
155128
&& find ${ROOTFS_PATH:?}/usr/lib*/python*/ -type d -name "idle_test" -exec rm -rf {} + 2>/dev/null || true \
156129
&& find ${ROOTFS_PATH:?}/usr/lib*/python*/ -name "*.mo" -delete 2>/dev/null || true \
157130
&& rm -rf ${ROOTFS_PATH:?}/usr/lib*/python*/ensurepip \
158131
${ROOTFS_PATH:?}/usr/lib*/python*/idlelib \
159-
${ROOTFS_PATH:?}/usr/lib*/python*/tkinter \
160-
${ROOTFS_PATH:?}/usr/lib*/python*/turtle* \
161-
${ROOTFS_PATH:?}/usr/lib*/python*/distutils/command/*.exe
162-
163-
# ----------------------------------------------------------------------------
164-
# Remove package managers and unnecessary system tools from rootfs
165-
# - Keep RPM database for security scanning with Trivy/Dockle
166-
# - This keeps the final image size minimal while allowing vulnerability scanning
167-
# ----------------------------------------------------------------------------
168-
RUN rm -rf ${ROOTFS_PATH:?}/usr/bin/dnf* \
169-
${ROOTFS_PATH:?}/usr/bin/yum* \
170-
${ROOTFS_PATH:?}/usr/bin/rpm* \
171-
${ROOTFS_PATH:?}/usr/bin/microdnf \
172-
${ROOTFS_PATH:?}/usr/lib/rpm \
173-
${ROOTFS_PATH:?}/usr/lib/dnf \
174-
${ROOTFS_PATH:?}/usr/lib/yum* \
175-
${ROOTFS_PATH:?}/etc/dnf \
176-
${ROOTFS_PATH:?}/etc/yum*
132+
${ROOTFS_PATH:?}/usr/lib*/python*/tkinter 2>/dev/null || true
177133

178134
# ----------------------------------------------------------------------------
179-
# Strip unneeded symbols from shared libraries and remove binutils
135+
# Strip unneeded symbols from shared libraries
180136
# - This reduces the final image size and removes the build tool in one step
181137
# ----------------------------------------------------------------------------
182138
RUN find "${ROOTFS_PATH:?}/usr/lib64" -name '*.so*' -exec strip --strip-unneeded {} + 2>/dev/null || true \

0 commit comments

Comments
 (0)