User:Arzano/Towards a slim Gentoo container image

From Gentoo Wiki
Jump to: navigation, search

This page describes how to get slim Gentoo based container images.

Current Image

Currently gentoo/stage3-amd64 is used as base image. Furthermore, gentoo/portage is used to copy the full ebuild tree into the container. This way it is possible to install packages.

Consequently, a typical Dockerfile currently looks like this:

FILE Dockerfile
FROM gentoo/portage:latest as portage
# Used as base image
FROM gentoo/stage3-amd64

# Need a portage tree to build packages
COPY --from=gentoo/portage:latest /var/db/repos/gentoo /var/db/repos/gentoo

# Install packages that are needed to build AND run the application
RUN emerge ...

# Copy the application
COPY ./ /var/www/packages.gentoo.org/htdocs/

# Build the application
RUN ...

# Run the application 
CMD ...

Where this falls short

Unfortunately this results in rather large images, as

  • the image contains dependencies that are only needed during the build and not needed at runtime, and
  • the image contains dependencies that are neither needed during build nor at runtime (as they are included in the stage3 base image)

New Image

To solve the problems of the current approach:

  • a multi stage build is used to exclude the dependencies that are only needed during the build
  • a slim Stage 1 base image is used to exclude dependencies that are neither needed during build nor at runtime

Multi Stage Build

A multi stage build is used to build the application / static contents and copy only the required artifacts into the image. The multistage Dockerfile looks like this:

FILE Dockerfile
# ------------------- builder stage
FROM gentoo/stage3-amd64 as builder

# Need a portage tree to build packages
COPY --from=gentoo/portage:latest /var/db/repos/gentoo /var/db/repos/gentoo

# Install packages that are needed to build the application
RUN emerge ...

# Copy the application
COPY ./ /var/www/packages.gentoo.org/htdocs/

# Build the application
RUN ...

# ------------------- production stage

# Use a slim base image
FROM gentoo/stage1-amd64-ruby

# Copy the application
COPY ./ /var/www/packages.gentoo.org/htdocs/

# Copy the required artifacts from the last stage into the image
COPY --from=builder ...

# Run the application 
CMD ...

Stage 1 image

Catalyst can be used to create a stage1 tarball. The linux/amd64/17.1 profile will be modified to:

  • exclude as many non-essential packages as possible, and
  • add further packages which are needed at runtime (as ruby for instance)

Afterwards the Stage 1 image can be created the same way as the Stage 3 image is currently created. [1] This way, a slim base image is created.

Creating the image during builder stage

The stage 1 image including all runtime dependencies can be created during the builder stage like this:

FILE Dockerfile
# ------------------- builder stage
FROM gentoo/stage3-amd64 as builder

# ...

# Specifiy all needed runtime dependencies, for instance redis or ruby or python
RUN ...
# Build the minimal stage 1 image including all runtime dependencies using Catalyst or the like
RUN ...
# Extract the created stage 1 tarball to /gentoo
RUN ...

# ------------------- production stage

FROM scratch

# Use the minimal stage 1 including all runtime dependencies created before
COPY --from=builder /gentoo /

#...

Comparison

As for the packages.g.o image, it turns out that the new image is 15 times smaller than the current image:

Current Image: 3000mb
New Image: 200mb