Skip to content

build: optimize Dockerfile for production deployment#157

Open
suncle1993 wants to merge 1 commit intoEverMind-AI:mainfrom
suncle1993:fix/dockerfile-prod-optimization
Open

build: optimize Dockerfile for production deployment#157
suncle1993 wants to merge 1 commit intoEverMind-AI:mainfrom
suncle1993:fix/dockerfile-prod-optimization

Conversation

@suncle1993
Copy link
Copy Markdown

Description

  • Multi-stage build: separate build (g++, build-essential) from runtime, reducing final image size by ~270MB (1.96GB -> 1.69GB)
  • Layer caching: copy pyproject.toml + uv.lock before source code so dependency layer is cached across source code changes
  • Remove unnecessary packages: ffmpeg, vim, wget, zip/unzip, libgl1, libglib2.0-0 are not used at runtime
  • Non-root user: run as appuser instead of root for security compliance
  • Clean apt cache: rm /var/lib/apt/lists/* in both stages
  • Exclude tests/, docs/, demo/, examples/ etc. from image via .dockerignore

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Test improvements
  • Build/CI/CD changes

Related Issues

N/A

Changes Made

  • Dockerfile: Rewritten with multi-stage build (builder + runtime), non-root user, minimal apt packages, dependency-first COPY for layer caching
  • .dockerignore: Added tests/, docs/, demo/, examples/, docker/, .claude/, .github/, *.md, Makefile, LICENSE to reduce build context

Testing

  • Tested locally with manual verification
  • Added/updated unit tests
  • Added/updated integration tests
  • All existing tests pass

Test Configuration:

  • OS: macOS
  • Python version: 3.12.10

Test Results:

Metric Before After Delta
Image size 1.96 GB 1.69 GB -270 MB (-14%)
apt layer 869 MB (g++, build-essential, ffmpeg, vim...) 6.56 MB (libgomp1, curl, procps only) -862 MB
Security runs as root runs as appuser (non-root)

The apt layer dropped from 869 MB to 6.5 MB, but the total image only shrunk by 270 MB because the uv sync virtualenv (~740 MB) dominates and is incompressible.

Build time is similar (both dominated by uv sync), but the new Dockerfile benefits from layer caching — source code changes no longer invalidate the dependency layer, making rebuilds significantly faster.

Checklist

  • My code follows the project's code style guidelines
  • I have performed a self-review of my code
  • I have commented my code where necessary, particularly in complex areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings or errors
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have used Gitmoji in my commit messages
  • Any dependent changes have been merged and published

Screenshots (if applicable)

N/A

Additional Notes

  • curl is kept in the runtime image for debugging purposes (e.g., exec into container to test endpoints)
  • procps is kept for ps command availability in production debugging
  • libgomp1 is required at runtime by numpy/scikit-learn (OpenMP)

Breaking Changes

None. The application behavior is unchanged; only the build process and image composition are optimized.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

- Multi-stage build: separate build (g++, build-essential) from runtime,
  reducing final image size by ~270MB (1.96GB -> 1.69GB)
- Layer caching: copy pyproject.toml + uv.lock before source code so
  dependency layer is cached across source code changes
- Remove unnecessary packages: ffmpeg, vim, wget, zip/unzip, libgl1,
  libglib2.0-0 are not used at runtime
- Non-root user: run as appuser instead of root for security compliance
- Clean apt cache: rm /var/lib/apt/lists/* in both stages
- Exclude tests/, docs/, demo/, examples/ etc. from image
  via .dockerignore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant