Reduce Docker image size using multi-stage builds#1161
Reduce Docker image size using multi-stage builds#1161mrz948 wants to merge 2 commits intoAudionut:masterfrom
Conversation
📝 WalkthroughWalkthroughIntroduces a new multi-stage Dockerfile.alpine for a Python application. The build uses separate stages for virtual environment preparation and application assembly, installs system dependencies, Python requirements, and additional binaries (mkbrr and DVD MediaInfo). The final image is optimized with proper file permissions, writable temporary directory configuration, and application entrypoint. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Thanks for the PR. I don't use docker, and everytime I push a PR for docker, it seems to cause issues for users, somewhere, somehow. I'll focus on this after I get an overdue release pushed. Thanks. |
|
Nice, no pressure, if there are any issues that come up afterwards feel free to tag me in them, so I can help. |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Dockerfile (1)
65-92:⚠️ Potential issue | 🟠 MajorRun the container as a non‑root user.
The final image defaults to root; this is a common security risk and flagged by Trivy. Create a dedicated user and switch to it after setting ownership.
✅ Suggested fix
# Create tmp directory with appropriate permissions RUN mkdir -p /Upload-Assistant/tmp && chmod 777 /Upload-Assistant/tmp ENV TMPDIR=/Upload-Assistant/tmp +# Create non-root user and switch +RUN useradd -u 1000 -m app && \ + chown -R app:app /Upload-Assistant /venv +USER app + # Set the entry point for the container ENTRYPOINT ["python", "/Upload-Assistant/upload.py"]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Dockerfile` around lines 65 - 92, The image currently runs as root; update the Dockerfile to create a dedicated non-root user (e.g., add a user/group like appuser with a fixed UID/GID), chown the application directories to that UID/GID (you already call chown on /Upload-Assistant/bin/mkbrr and /Upload-Assistant/bin/MI — extend ownership to /Upload-Assistant and /Upload-Assistant/tmp), and add a USER instruction before the ENTRYPOINT so the container runs as that non-root user; ensure the TMPDIR and PATH usage (ENV PATH="/venv/bin:$PATH" and ENV TMPDIR) remain valid for the new user and that any files the app needs are writable by the new user.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Dockerfile.alpine`:
- Around line 67-95: The image currently runs as root; create a non-root user
and drop privileges before the final ENTRYPOINT: add a dedicated user/group
(e.g., uid 1000 and a name like uploadassistant) after copying files, chown the
application directories to that user (update references to /Upload-Assistant for
bin/mkbrr, bin/MI and tmp ownership), then use USER <username> (or USER 1000)
before the ENTRYPOINT so the container runs unprivileged; ensure TMPDIR and PATH
remain accessible to that user and that any files the app changes at runtime are
owned or world-writable as needed.
---
Outside diff comments:
In `@Dockerfile`:
- Around line 65-92: The image currently runs as root; update the Dockerfile to
create a dedicated non-root user (e.g., add a user/group like appuser with a
fixed UID/GID), chown the application directories to that UID/GID (you already
call chown on /Upload-Assistant/bin/mkbrr and /Upload-Assistant/bin/MI — extend
ownership to /Upload-Assistant and /Upload-Assistant/tmp), and add a USER
instruction before the ENTRYPOINT so the container runs as that non-root user;
ensure the TMPDIR and PATH usage (ENV PATH="/venv/bin:$PATH" and ENV TMPDIR)
remain valid for the new user and that any files the app needs are writable by
the new user.
| # START BUILDING SLIM IMAGE | ||
| FROM base | ||
|
|
||
| # Copy venv | ||
| COPY --from=builder-venv /venv /venv | ||
| ENV PATH="/venv/bin:$PATH" | ||
|
|
||
| # Copy application | ||
| COPY --from=builder-app /Upload-Assistant /Upload-Assistant | ||
|
|
||
| # Set workdir | ||
| WORKDIR /Upload-Assistant | ||
|
|
||
| # Ensure mkbrr is executable | ||
| RUN find bin/mkbrr -name "mkbrr" -exec chmod +x {} \; && \ | ||
| find bin/bdinfo -name "bdinfo" -exec chmod +x {} \; | ||
|
|
||
| # Enable non-root access while still letting Upload-Assistant tighten mkbrr permissions at runtime | ||
| RUN chown -R 1000:1000 /Upload-Assistant/bin/mkbrr | ||
|
|
||
| # Enable non-root access for DVD MediaInfo binary | ||
| RUN chown -R 1000:1000 /Upload-Assistant/bin/MI | ||
|
|
||
| # Create tmp directory with appropriate permissions | ||
| RUN mkdir -p /Upload-Assistant/tmp && chmod 777 /Upload-Assistant/tmp | ||
| ENV TMPDIR=/Upload-Assistant/tmp | ||
|
|
||
| # Set the entry point for the container | ||
| ENTRYPOINT ["python", "/Upload-Assistant/upload.py"] |
There was a problem hiding this comment.
Run the container as a non‑root user.
The final image defaults to root; this is a common security risk and flagged by Trivy. Create a dedicated user and switch to it after setting ownership.
✅ Suggested fix
# Create tmp directory with appropriate permissions
RUN mkdir -p /Upload-Assistant/tmp && chmod 777 /Upload-Assistant/tmp
ENV TMPDIR=/Upload-Assistant/tmp
+# Create non-root user and switch
+RUN addgroup -S app && adduser -S -G app -u 1000 app && \
+ chown -R app:app /Upload-Assistant /venv
+USER app
+
# Set the entry point for the container
ENTRYPOINT ["python", "/Upload-Assistant/upload.py"]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Dockerfile.alpine` around lines 67 - 95, The image currently runs as root;
create a non-root user and drop privileges before the final ENTRYPOINT: add a
dedicated user/group (e.g., uid 1000 and a name like uploadassistant) after
copying files, chown the application directories to that user (update references
to /Upload-Assistant for bin/mkbrr, bin/MI and tmp ownership), then use USER
<username> (or USER 1000) before the ENTRYPOINT so the container runs
unprivileged; ensure TMPDIR and PATH remain accessible to that user and that any
files the app changes at runtime are owned or world-writable as needed.
|
I closed this by accident, but since this is not a critical bugfix, I'll leave it as is. |
smaller image from docker-image-optimization branch, no web ui, docker-entrypoint script etc.
integrate most of upstream's changes
|
On second thought maybe this is useful for someone. Current alpine image size: 770MB |
There was a problem hiding this comment.
♻️ Duplicate comments (1)
Dockerfile.alpine (1)
80-100:⚠️ Potential issue | 🟠 MajorFinal image still runs as root (missing
USER).There is no privilege drop in the final stage, so the process runs as root. This issue was already raised earlier and still applies.
✅ Suggested hardening patch
FROM base # Copy venv COPY --from=builder-venv /venv /venv ENV PATH="/venv/bin:$PATH" # Copy application COPY --from=builder-app /Upload-Assistant /Upload-Assistant WORKDIR /Upload-Assistant + +# Drop privileges in runtime image +RUN addgroup -S uploadassistant && adduser -S -G uploadassistant -u 1000 uploadassistant && \ + chown -R uploadassistant:uploadassistant /Upload-Assistant /venv +USER uploadassistant EXPOSE 5000🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Dockerfile.alpine` around lines 80 - 100, The final image's container process still runs as root because the final stage (FROM base) lacks a USER directive; modify the final stage to switch to a non-root user (e.g., create or reuse a low‑privilege user) and add a USER instruction before ENTRYPOINT, ensuring ownership and permissions are correct for /venv and /Upload-Assistant (use chown/chmod during the build or copy steps) so python /Upload-Assistant/upload.py runs unprivileged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@Dockerfile.alpine`:
- Around line 80-100: The final image's container process still runs as root
because the final stage (FROM base) lacks a USER directive; modify the final
stage to switch to a non-root user (e.g., create or reuse a low‑privilege user)
and add a USER instruction before ENTRYPOINT, ensuring ownership and permissions
are correct for /venv and /Upload-Assistant (use chown/chmod during the build or
copy steps) so python /Upload-Assistant/upload.py runs unprivileged.
This PR introduces multi-stage Docker builds to reduce the final image size by excluding build-time dependencies from the runtime image.
Results
2.86 GB(-1.23 GB)1.63 GBEDIT: New results:
1.27 GB0.85 GBChanges
1.2GB0.85 GB)I tested each final image by processing a full disc and movie.
Summary by CodeRabbit