Skip to content

Commit fb3e50e

Browse files
committed
Optimize Docker images & add multi-architecture support
- Reduce image size by implementing multi-stage build - Remove torchaudio package and optimize PyTorch installation - Add GPU/CPU variant support via build arguments - Enable multi-architecture builds (amd64/arm64) with proper manifests - Fix Renku compatibility by setting provenance: false - Simplify container environment variables and working directory - Create architecture-specific tags for better image management
1 parent b14c079 commit fb3e50e

File tree

3 files changed

+100
-26
lines changed

3 files changed

+100
-26
lines changed

.github/workflows/docker-build.yml

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ jobs:
2929
strategy:
3030
matrix:
3131
arch: [amd64, arm64]
32+
variant: [cpu, cuda]
3233
fail-fast: false
3334
steps:
3435
- name: Checkout code
@@ -54,10 +55,10 @@ jobs:
5455
with:
5556
images: ghcr.io/${{ github.repository }}
5657
tags: |
57-
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
58-
type=ref,event=pr
59-
type=ref,event=tag
60-
type=sha,format=short
58+
type=raw,value=${{ matrix.variant }}-${{ matrix.arch }},enable=${{ github.ref == 'refs/heads/main' }}
59+
type=raw,value=${{ matrix.variant }}-${{ matrix.arch }}-pr-${{ github.event.pull_request.number }},enable=${{ github.event_name == 'pull_request' }}
60+
type=raw,value=${{ matrix.variant }}-${{ matrix.arch }}-${{ github.ref_name }},enable=${{ startsWith(github.ref, 'refs/tags/') }}
61+
type=raw,value=${{ matrix.variant }}-${{ matrix.arch }}-sha-${{ github.sha }},prefix=
6162
6263
- name: Build and push
6364
uses: docker/build-push-action@v6
@@ -67,3 +68,47 @@ jobs:
6768
push: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
6869
tags: ${{ steps.meta.outputs.tags }}
6970
labels: ${{ steps.meta.outputs.labels }}
71+
provenance: false
72+
build-args: |
73+
PYTORCH_VARIANT=${{ matrix.variant }}
74+
outputs: |
75+
type=image,name=ghcr.io/${{ github.repository }},push-by-digest=false,name-canonical=false,push=true,annotation-index.org.opencontainers.image.description=A containerized Python tutorial environment with Jupyter Lab (${{ matrix.variant }} variant, ${{ matrix.arch }} architecture).,annotation-index.org.opencontainers.image.source=https://github.com/${{ github.repository }},annotation-index.org.opencontainers.image.authors=Empa Scientific IT <scientificit@empa.ch>,annotation-index.org.opencontainers.image.licenses=MIT,annotation-index.org.opencontainers.image.variant=pytorch-${{ matrix.variant }}-${{ matrix.arch }}
76+
77+
create-manifests:
78+
needs: build-and-push
79+
runs-on: ubuntu-latest
80+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
81+
permissions:
82+
packages: write
83+
steps:
84+
- name: Log in to GHCR
85+
uses: docker/login-action@v3
86+
with:
87+
registry: ghcr.io
88+
username: ${{ github.actor }}
89+
password: ${{ secrets.GITHUB_TOKEN }}
90+
91+
- name: Create and push CPU manifest
92+
uses: docker/build-push-action@v6
93+
with:
94+
context: .
95+
target: builder
96+
platforms: linux/amd64,linux/arm64
97+
push: true
98+
provenance: false
99+
tags: |
100+
ghcr.io/${{ github.repository }}:cpu
101+
${{ startsWith(github.ref, 'refs/tags/') && format('ghcr.io/{0}:cpu-{1}', github.repository, github.ref_name) || '' }}
102+
${{ github.ref == 'refs/heads/main' && format('ghcr.io/{0}:latest', github.repository) || '' }}
103+
104+
- name: Create and push CUDA manifest
105+
uses: docker/build-push-action@v6
106+
with:
107+
context: .
108+
target: builder
109+
platforms: linux/amd64,linux/arm64
110+
push: true
111+
provenance: false
112+
tags: |
113+
ghcr.io/${{ github.repository }}:cuda
114+
${{ startsWith(github.ref, 'refs/tags/') && format('ghcr.io/{0}:cuda-{1}', github.repository, github.ref_name) || '' }}

Dockerfile

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,8 @@
1-
# Use the jupyter/minimal-notebook as the base image
2-
FROM quay.io/jupyter/minimal-notebook:latest
1+
# Stage 1: Build environment
2+
FROM quay.io/jupyter/minimal-notebook:latest as builder
33

4-
# Metadata labels
5-
LABEL org.opencontainers.image.title="Python Tutorial"
6-
LABEL org.opencontainers.image.description="A containerized Python tutorial environment with Jupyter Lab."
7-
LABEL org.opencontainers.image.authors="Empa Scientific IT <scientificit@empa.ch>"
8-
LABEL org.opencontainers.image.url="https://github.com/empa-scientific-it/python-tutorial"
9-
LABEL org.opencontainers.image.source="https://github.com/empa-scientific-it/python-tutorial"
10-
LABEL org.opencontainers.image.version="1.0.0"
11-
LABEL org.opencontainers.image.licenses="MIT"
12-
13-
# Set environment variables for the tutorial and repository
14-
ENV BASENAME="python-tutorial"
15-
ENV REPO=${HOME}/${BASENAME}
16-
ENV IPYTHONDIR="${HOME}/.ipython"
4+
# Define build argument for PyTorch variant (cpu or cuda)
5+
ARG PYTORCH_VARIANT=cpu
176

187
# Switch to root user to install additional dependencies
198
USER root
@@ -33,16 +22,59 @@ USER ${NB_UID}
3322
# Set up the Conda environment
3423
COPY docker/environment.yml /tmp/environment.yml
3524
RUN mamba env update -n base -f /tmp/environment.yml && \
25+
# Install PyTorch packages without cache - conditionally based on variant
26+
if [ "$PYTORCH_VARIANT" = "cpu" ]; then \
27+
echo "Installing CPU-only PyTorch" && \
28+
pip install --no-cache-dir torch torchvision --index-url https://download.pytorch.org/whl/cpu; \
29+
else \
30+
echo "Installing CUDA-enabled PyTorch" && \
31+
pip install --no-cache-dir torch torchvision; \
32+
fi && \
33+
# Clean up all package caches to reduce image size
3634
mamba clean --all -f -y && \
35+
# Remove pip cache
36+
rm -rf ~/.cache/pip && \
3737
fix-permissions "${CONDA_DIR}" && \
3838
fix-permissions "/home/${NB_USER}"
3939

40-
# Prepare IPython configuration (move earlier in the build)
41-
RUN mkdir -p ${HOME}/.ipython/profile_default
40+
# Stage 2: Runtime environment - creates a lighter final image
41+
FROM quay.io/jupyter/minimal-notebook:latest
42+
43+
# Inherit build argument for image labeling
44+
ARG PYTORCH_VARIANT=cpu
45+
46+
# Metadata labels
47+
LABEL org.opencontainers.image.title="Python Tutorial"
48+
LABEL org.opencontainers.image.description="A containerized Python tutorial environment with Jupyter Lab."
49+
LABEL org.opencontainers.image.authors="Empa Scientific IT <scientificit@empa.ch>"
50+
LABEL org.opencontainers.image.url="https://github.com/empa-scientific-it/python-tutorial"
51+
LABEL org.opencontainers.image.source="https://github.com/empa-scientific-it/python-tutorial"
52+
LABEL org.opencontainers.image.version="1.0.0"
53+
LABEL org.opencontainers.image.licenses="MIT"
54+
LABEL org.opencontainers.image.variant="pytorch-${PYTORCH_VARIANT}"
55+
56+
# Switch to root user to install minimal dependencies
57+
USER root
58+
RUN apt-get update && \
59+
apt-get install -y --no-install-recommends \
60+
libgl1 && \
61+
apt-get clean && \
62+
rm -rf /var/lib/apt/lists/*
63+
64+
# Switch back to the default notebook user
65+
USER ${NB_UID}
66+
67+
# Copy the conda environment from the builder stage
68+
COPY --from=builder ${CONDA_DIR} ${CONDA_DIR}
69+
70+
# Copy home directory with configurations
71+
COPY --from=builder --chown=${NB_UID}:${NB_GID} /home/${NB_USER} /home/${NB_USER}
72+
73+
# Prepare IPython configuration
4274
COPY --chown=${NB_UID}:${NB_GID} binder/ipython_config.py ${HOME}/.ipython/profile_default/
4375

44-
# Set the working directory to the repository
45-
WORKDIR ${REPO}
76+
# Set the working directory to user's home (repository will be cloned here by Renku)
77+
WORKDIR /home/${NB_USER}
4678

4779
# Use the default ENTRYPOINT from the base image to start Jupyter Lab
4880
ENTRYPOINT ["tini", "-g", "--", "start.sh"]

docker/environment.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,5 @@ dependencies:
2626
- python-dotenv
2727
- pillow
2828
- opencv-python
29-
- torch
30-
- torchaudio
31-
- torchvision
3229
- albumentations
3330
- grad-cam

0 commit comments

Comments
 (0)