Optimize Docker image and reduce size

- Replace build-essential with specific packages (gcc, g++, make)
- Remove curl from both builder and runtime stages
- Remove Docker healthcheck (Kubernetes handles this)
- Consolidate file copying to reduce layers
- Remove redundant mkdir and chown commands
- Add comprehensive .dockerignore file

These changes reduce image size and build time significantly.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Graham McIntire 2025-07-26 16:07:37 -05:00
parent 4f5f26287a
commit 27ee859d3b
No known key found for this signature in database
2 changed files with 65 additions and 58 deletions

View file

@ -1,45 +1,57 @@
# This file excludes paths from the Docker build context. # Version control
# .git/
# By default, Docker's build context includes all files (and folders) in the .github/
# current directory. Even if a file isn't copied into the container it is still sent to .gitignore
# the Docker daemon.
#
# There are multiple reasons to exclude files from the build context:
#
# 1. Prevent nested folders from being copied into the container (ex: exclude
# /assets/node_modules when copying /assets)
# 2. Reduce the size of the build context and improve build time (ex. /build, /deps, /doc)
# 3. Avoid sending files containing sensitive information
#
# More information on using .dockerignore is available here:
# https://docs.docker.com/engine/reference/builder/#dockerignore-file
.dockerignore # Dependencies
deps/
_build/
.elixir_ls/
# Ignore git, but keep git HEAD and refs to access current commit hash if needed: # Development files
# .DS_Store
# $ cat .git/HEAD | awk '{print ".git/"$2}' | xargs cat *.iml
# d0b8727759e1e0e7aa3d41707d12376e373d5ecc .idea/
.git .vscode/
!.git/HEAD *.swp
!.git/refs *.swo
*~
# Common development/test artifacts # Test files
/cover/ test/
/doc/ coveralls.json
/test/ cover/
/tmp/
.elixir_ls
# Mix artifacts # Documentation
/_build/ docs/
/deps/ README.md
CLAUDE.md
*.md
# Temporary files
*.log
tmp/
temp/
# Build artifacts
erl_crash.dump
*.ez *.ez
# Generated on crash by the VM # Phoenix specific
erl_crash.dump priv/static/assets/
priv/static/cache_manifest.json
# Static artifacts - These should be fetched and built inside the Docker image # Node modules (if any left)
/assets/node_modules/ node_modules/
/priv/static/assets/ npm-debug.log
/priv/static/cache_manifest.json
# Environment files
.env
.env.*
# Database dumps
*.dump
*.sql
# OS files
Thumbs.db

View file

@ -12,7 +12,11 @@ FROM ${BUILDER_IMAGE} AS builder
# Install build dependencies # Install build dependencies
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y && apt-get install -y --no-install-recommends build-essential git curl \ RUN apt-get update -y && apt-get install -y --no-install-recommends \
gcc \
g++ \
make \
git \
&& apt-get clean && rm -rf /var/lib/apt/lists/* && apt-get clean && rm -rf /var/lib/apt/lists/*
# Prepare build directory # Prepare build directory
@ -33,18 +37,12 @@ COPY mix.exs mix.lock ./
COPY vendor vendor COPY vendor vendor
RUN mix deps.get --only $MIX_ENV RUN mix deps.get --only $MIX_ENV
# Copy application code # Copy all application code
COPY config config COPY config config
COPY priv priv
COPY lib lib COPY lib lib
COPY assets assets COPY assets assets
COPY priv priv
COPY rel rel COPY rel rel
# Copy Gleam source files and configuration
COPY src src
COPY gleam.toml gleam.toml
# Copy pre-compiled Gleam BEAM files
# This is crucial for production builds where gleam compiler is not available
COPY priv/gleam priv/gleam
# Compile all dependencies # Compile all dependencies
RUN mix deps.compile RUN mix deps.compile
@ -74,30 +72,27 @@ FROM ${RUNNER_IMAGE}
# Install runtime dependencies # Install runtime dependencies
RUN apt-get update -y && \ RUN apt-get update -y && \
apt-get install -y --no-install-recommends libstdc++6 openssl libncurses5 locales ca-certificates \ apt-get install -y --no-install-recommends \
libstdc++6 \
openssl \
libncurses5 \
locales \
ca-certificates \
&& apt-get clean && rm -rf /var/lib/apt/lists/* && apt-get clean && rm -rf /var/lib/apt/lists/*
# Set locale # Set locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
ENV LANG="en_US.UTF-8" LANGUAGE="en_US:en" LC_ALL="en_US.UTF-8" ENV LANG="en_US.UTF-8" LANGUAGE="en_US:en" LC_ALL="en_US.UTF-8"
# Set working directory and create it # Set working directory
WORKDIR "/app" WORKDIR "/app"
RUN mkdir -p /app
# Set deployment timestamp to current time during runtime container build # Set deployment timestamp to current time during runtime container build
RUN date -u +"%Y-%m-%dT%H:%M:%SZ" > /app/deployed_at.txt RUN date -u +"%Y-%m-%dT%H:%M:%SZ" > /app/deployed_at.txt
# Copy release from builder # Copy release from builder with correct ownership
COPY --from=builder --chown=nobody:root /app/release ./ COPY --from=builder --chown=nobody:root /app/release ./
# Set ownership for the entire app directory
RUN chown -R nobody:root /app
# Set user and command # Set user and command
USER nobody USER nobody
CMD ["/app/bin/server"] CMD ["/app/bin/server"]
# Optional: Add healthcheck
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:4000/health || exit 1