Skip to the content.

Layer Optimization

Applies to: Both legacy and user namespace modes

Layer Count Limit

Red Hat container certification enforces LayerCountAcceptable: images must have fewer than 40 layers. Each FROM, RUN, COPY, and ADD instruction creates a layer.

Multi-Stage Builds

Separate build-time dependencies from runtime to minimize image size and attack surface.

# Build stage — large, has compilers
FROM registry.access.redhat.com/ubi9/go-toolset:latest AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server .

# Runtime stage — minimal
FROM registry.access.redhat.com/ubi9/ubi-micro:latest
COPY --from=builder --chown=1001:0 /app/server /server
COPY --chown=1001:0 LICENSE /licenses/LICENSE
USER 1001
EXPOSE 8080
ENTRYPOINT ["/server"]

Benefits:

Cache-Friendly Ordering

Place instructions that change infrequently early and instructions that change frequently late:

FROM registry.access.redhat.com/ubi9/ubi-minimal:latest

# 1. System packages — rarely change
RUN microdnf install -y nodejs npm && microdnf clean all

# 2. Dependencies — change when package.json changes
COPY package.json package-lock.json ./
RUN npm ci --production

# 3. Application code — changes every commit
COPY --chown=1001:0 src/ ./src/

USER 1001
EXPOSE 8080
CMD ["node", "src/index.js"]

If src/ changes but package.json doesn’t, layers 1–2 are cached.

Package Cache Cleanup

Package manager caches persist in the layer where they were created. Clean in the same RUN instruction as the install:

Correct

# ✅ Install and clean in the same layer
RUN microdnf install -y \
      python3 python3-pip \
      shadow-utils && \
    microdnf clean all && \
    rm -rf /var/cache/yum /var/cache/dnf

Incorrect

# ❌ Cache persists in the first layer — second RUN doesn't help
RUN microdnf install -y python3 python3-pip
RUN microdnf clean all

Consolidate RUN Instructions

Chain related operations to reduce layer count:

# ✅ Single layer for all setup
RUN microdnf install -y nodejs npm && \
    microdnf clean all && \
    mkdir -p /app/data /app/logs && \
    chgrp -R 0 /app/data /app/logs && \
    chmod -R g=u /app/data /app/logs

# ❌ Four layers for the same operations
RUN microdnf install -y nodejs npm
RUN microdnf clean all
RUN mkdir -p /app/data /app/logs
RUN chgrp -R 0 /app/data /app/logs && chmod -R g=u /app/data /app/logs

Don’t Install Unnecessary Packages

# ✅ --nodocs skips man pages and documentation
RUN dnf install --nodocs -y httpd && dnf clean all

# ✅ --no-install-recommends equivalent for microdnf
RUN microdnf install -y --nodocs python3 && microdnf clean all

.containerignore / .dockerignore

Prevent build context bloat by excluding unnecessary files:

# .containerignore
.git
node_modules
*.md
tests/
docs/
.env

COPY vs ADD

Gotchas

Sources