From f957c59f2869f5d541c866b9466aa0d47455333e Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Fri, 15 Dec 2023 13:11:35 -0800 Subject: [PATCH] Simplify the Docker build Since we no longer upload intermediate stages, the separation between the dependencies stage and the install stage became irrelevant and they can be combined. Move the installation of Git from the base image to the dependency image, since it's only required during installation. --- Dockerfile | 26 +++++++++++--------------- scripts/install-base-packages.sh | 19 +++++++------------ scripts/install-dependency-packages.sh | 21 +++++++++++---------- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/Dockerfile b/Dockerfile index 219891aa..7a7d02f0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,12 @@ -# This Dockerfile has four stages: +# This Dockerfile has three stages: # # base-image # Updates the base Python image with security patches and common system # packages. This image becomes the base of all other images. -# dependencies-image -# Installs third-party dependencies (requirements/main.txt) into a virtual -# environment. This virtual environment is ideal for copying across build -# stages. # install-image -# Installs the app into the virtual environment. +# Installs third-party dependencies (requirements/main.txt) and the +# application into a virtual environment. This virtual environment is +# ideal for copying across build stages. # runtime-image # - Copies the virtual environment into place. # - Runs a non-root user. @@ -20,7 +18,7 @@ FROM python:3.12.1-slim-bullseye as base-image COPY scripts/install-base-packages.sh . RUN ./install-base-packages.sh && rm ./install-base-packages.sh -FROM base-image AS dependencies-image +FROM base-image AS install-image # Install system packages only needed for building dependencies. COPY scripts/install-dependency-packages.sh . @@ -29,8 +27,10 @@ RUN ./install-dependency-packages.sh # Create a Python virtual environment ENV VIRTUAL_ENV=/opt/venv RUN python -m venv $VIRTUAL_ENV + # Make sure we use the virtualenv ENV PATH="$VIRTUAL_ENV/bin:$PATH" + # Put the latest pip and setuptools in the virtualenv RUN pip install --upgrade --no-cache-dir pip setuptools wheel @@ -38,24 +38,20 @@ RUN pip install --upgrade --no-cache-dir pip setuptools wheel COPY requirements/main.txt ./requirements.txt RUN pip install --quiet --no-cache-dir -r requirements.txt -FROM dependencies-image AS install-image - -# Use the virtualenv -ENV PATH="/opt/venv/bin:$PATH" - +# Install the application. COPY . /workdir WORKDIR /workdir RUN pip install --no-cache-dir . FROM base-image AS runtime-image -# Create a non-root user +# Create a non-root user. RUN useradd --create-home appuser -# Copy the virtualenv +# Copy the virtualenv. COPY --from=install-image /opt/venv /opt/venv -# Make sure we use the virtualenv +# Make sure we use the virtualenv. ENV PATH="/opt/venv/bin:$PATH" # Switch to the non-root user. diff --git a/scripts/install-base-packages.sh b/scripts/install-base-packages.sh index 620781c1..2fd02247 100755 --- a/scripts/install-base-packages.sh +++ b/scripts/install-base-packages.sh @@ -1,7 +1,7 @@ #!/bin/bash -# This script updates packages in the base Docker image that's used by both the -# build and runtime images, and gives us a place to install additional +# This script updates packages in the base Docker image that's used by both +# the build and runtime images, and gives us a place to install additional # system-level packages with apt-get. # # Based on the blog post: @@ -9,26 +9,21 @@ # Bash "strict mode", to help catch problems and bugs in the shell # script. Every bash script you write should include this. See -# http://redsymbol.net/articles/unofficial-bash-strict-mode/ for -# details. +# http://redsymbol.net/articles/unofficial-bash-strict-mode/ for details. set -euo pipefail # Display each command as it's run. set -x -# Tell apt-get we're never going to be able to give manual -# feedback: +# Tell apt-get we're never going to be able to give manual feedback. export DEBIAN_FRONTEND=noninteractive -# Update the package listing, so we know what packages exist: +# Update the package listing, so we know what packages exist. apt-get update -# Install security updates: +# Install security updates. apt-get -y upgrade -# Example of installing a new package, without unnecessary packages: -apt-get -y install --no-install-recommends git - -# Delete cached files we don't need anymore: +# Delete cached files we don't need anymore. apt-get clean rm -rf /var/lib/apt/lists/* diff --git a/scripts/install-dependency-packages.sh b/scripts/install-dependency-packages.sh index f63ef751..e75df482 100755 --- a/scripts/install-dependency-packages.sh +++ b/scripts/install-dependency-packages.sh @@ -10,25 +10,26 @@ # Bash "strict mode", to help catch problems and bugs in the shell # script. Every bash script you write should include this. See -# http://redsymbol.net/articles/unofficial-bash-strict-mode/ for -# details. +# http://redsymbol.net/articles/unofficial-bash-strict-mode/ for details. set -euo pipefail # Display each command as it's run. set -x -# Tell apt-get we're never going to be able to give manual -# feedback: +# Tell apt-get we're never going to be able to give manual feedback. export DEBIAN_FRONTEND=noninteractive -# Update the package listing, so we know what packages exist: +# Update the package listing, so we know what packages exist. apt-get update -# Install build-essential because sometimes Python dependencies need to build -# C modules, particularly when upgrading to newer Python versions. libffi-dev -# is sometimes needed to build cffi (a cryptography dependency). -apt-get -y install --no-install-recommends build-essential libffi-dev +# Install various dependencies that may be required to install JupyterHub or +# our add-on modules, or are wanted at runtime: +# +# build-essential: sometimes needed to build Python modules +# git: required by setuptools_scm +# libffi-dev: sometimes needed to build cffi, a cryptography dependency +apt-get -y install --no-install-recommends build-essential git libffi-dev -# Delete cached files we don't need anymore: +# Delete cached files we don't need anymore. apt-get clean rm -rf /var/lib/apt/lists/*