From 355d44055c21b316528d2d62560d539988d62b25 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:38:00 +0000 Subject: [PATCH 1/5] Initial plan From 852194ef14a317ed0a6f20d0e4af0286bf6a298a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:43:45 +0000 Subject: [PATCH 2/5] Switch both Dockerfiles from ubuntu:22.04 to python:3.10-slim-bookworm Co-authored-by: t0mdavid-m <57191390+t0mdavid-m@users.noreply.github.com> --- Dockerfile | 81 +++++++++++++++++++++++++++++++++++++++++++---- Dockerfile_simple | 63 ++++++++++++++---------------------- 2 files changed, 98 insertions(+), 46 deletions(-) diff --git a/Dockerfile b/Dockerfile index 380508c8..fd7f3dd2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -117,7 +117,76 @@ ENV OPENMS_DATA_PATH="/openms/share/" RUN rm -rf openms-build # Prepare and run streamlit app. -FROM compile-openms AS run-app +# Use a minimal Python base image for the runtime +FROM python:3.10-slim-bookworm AS run-app +ARG PORT=8501 +ARG GITHUB_TOKEN +ENV GH_TOKEN=${GITHUB_TOKEN} +ARG GITHUB_USER=OpenMS +ARG GITHUB_REPO=streamlit-template + +USER root + +# Install only runtime dependencies (not build dependencies) +RUN apt-get -y update && apt-get install -y --no-install-recommends --no-install-suggests \ + libgtk2.0-0 \ + libsvm3 \ + libglpk40 \ + libzip4 \ + zlib1g \ + libxerces-c3.2 \ + libbz2-1.0 \ + libomp5 \ + libhdf5-103-1 \ + libboost-date-time1.74.0 \ + libboost-iostreams1.74.0 \ + libboost-regex1.74.0 \ + libboost-math1.74.0 \ + libboost-random1.74.0 \ + libqt6core6 \ + libqt6gui6 \ + libqt6widgets6 \ + libqt6svg6 \ + libqt6opengl6 \ + libqt6openglwidgets6 \ + libgl1 \ + openjdk-17-jre-headless \ + curl \ + jq \ + cron \ + gnupg \ + wget \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* +RUN update-ca-certificates + +# Install Github CLI (needed for downloading artifacts) +RUN mkdir -p -m 755 /etc/apt/keyrings \ + && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ + && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ + && apt-get update \ + && apt-get install gh -y \ + && rm -rf /var/lib/apt/lists/* + +# Copy OpenMS binaries and libraries from the build stage +COPY --from=compile-openms /openms /openms +COPY --from=compile-openms /thirdparty /thirdparty + +# Set environment variables for OpenMS +ENV PATH="/openms/bin/:/thirdparty/LuciPHOr2:/thirdparty/MSGFPlus:/thirdparty/Sirius:/thirdparty/ThermoRawFileParser:/thirdparty/Comet:/thirdparty/Fido:/thirdparty/MaRaCluster:/thirdparty/MyriMatch:/thirdparty/OMSSA:/thirdparty/Percolator:/thirdparty/SpectraST:/thirdparty/XTandem:/thirdparty/crux:${PATH}" +ENV LD_LIBRARY_PATH="/openms/lib/:${LD_LIBRARY_PATH}" +ENV OPENMS_DATA_PATH="/openms/share/" + +# Copy pyOpenMS and Python packages from build stage +# First install pip requirements +COPY requirements.txt ./requirements.txt +RUN python -m pip install --upgrade pip +RUN grep -Ev '^pyopenms([=<>!~].*)?$' requirements.txt > requirements_cleaned.txt && mv requirements_cleaned.txt requirements.txt +RUN python -m pip install -r requirements.txt + +# Copy pyOpenMS from build stage +COPY --from=compile-openms /root/miniforge3/envs/streamlit-env/lib/python3.10/site-packages/pyopenms* /usr/local/lib/python3.10/site-packages/ # Create workdir and copy over all streamlit related files/folders. # note: specifying folder with slash as suffix and repeating the folder name seems important to preserve directory structure @@ -139,18 +208,16 @@ COPY .streamlit/config.toml /app/.streamlit/config.toml COPY clean-up-workspaces.py /app/clean-up-workspaces.py # add cron job to the crontab -RUN echo "0 3 * * * /root/miniforge3/envs/streamlit-env/bin/python /app/clean-up-workspaces.py >> /app/clean-up-workspaces.log 2>&1" | crontab - +RUN echo "0 3 * * * /usr/local/bin/python /app/clean-up-workspaces.py >> /app/clean-up-workspaces.log 2>&1" | crontab - # create entrypoint script to start cron service and launch streamlit app RUN echo "#!/bin/bash" > /app/entrypoint.sh && \ - echo "source /root/miniforge3/bin/activate streamlit-env" >> /app/entrypoint.sh && \ echo "service cron start" >> /app/entrypoint.sh && \ - echo "streamlit run app.py" >> /app/entrypoint.sh -# make the script executable -RUN chmod +x /app/entrypoint.sh + echo "streamlit run app.py" >> /app/entrypoint.sh && \ + chmod +x /app/entrypoint.sh # Patch Analytics -RUN mamba run -n streamlit-env python hooks/hook-analytics.py +RUN python hooks/hook-analytics.py # Set Online Deployment RUN jq '.online_deployment = true' settings.json > tmp.json && mv tmp.json settings.json diff --git a/Dockerfile_simple b/Dockerfile_simple index 84a01ed4..8807f65d 100644 --- a/Dockerfile_simple +++ b/Dockerfile_simple @@ -7,7 +7,7 @@ # debug container after build (comment out ENTRYPOINT) and run container with interactive /bin/bash shell # prune unused images/etc. to free disc space (e.g. might be needed on gitpod). Use with care.: docker system prune --all --force -FROM ubuntu:22.04 AS stage1 +FROM python:3.10-slim-bookworm AS stage1 ARG OPENMS_REPO=https://github.com/OpenMS/OpenMS.git ARG OPENMS_BRANCH=develop ARG PORT=8501 @@ -23,38 +23,28 @@ ARG GITHUB_REPO=streamlit-template # Step 1: set up a sane build system USER root -RUN apt-get -y update -# note: streamlit in docker needs libgtk2.0-dev (see https://yugdamor.medium.com/importerror-libgthread-2-0-so-0-cannot-open-shared-object-file-no-such-file-or-directory-895b94a7827b) -RUN apt-get install -y --no-install-recommends --no-install-suggests wget ca-certificates libgtk2.0-dev curl jq cron +RUN apt-get -y update && apt-get install -y --no-install-recommends --no-install-suggests \ + wget \ + ca-certificates \ + libgtk2.0-0 \ + curl \ + jq \ + cron \ + gnupg \ + && rm -rf /var/lib/apt/lists/* RUN update-ca-certificates # Install Github CLI -RUN (type -p wget >/dev/null || (apt-get update && apt-get install wget -y)) \ - && mkdir -p -m 755 /etc/apt/keyrings \ - && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ - && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ - && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ - && apt-get update \ - && apt-get install gh -y - -# Download and install miniforge. -ENV PATH="/root/miniforge3/bin:${PATH}" -RUN wget -q \ - https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh \ - && bash Miniforge3-Linux-x86_64.sh -b \ - && rm -f Miniforge3-Linux-x86_64.sh -RUN mamba --version - -# Setup mamba environment. -RUN mamba create -n streamlit-env python=3.10 -RUN echo "mamba activate streamlit-env" >> ~/.bashrc -SHELL ["/bin/bash", "--rcfile", "~/.bashrc"] -SHELL ["mamba", "run", "-n", "streamlit-env", "/bin/bash", "-c"] - -#################################### install streamlit -# install packages +RUN mkdir -p -m 755 /etc/apt/keyrings \ + && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ + && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ + && apt-get update \ + && apt-get install gh -y \ + && rm -rf /var/lib/apt/lists/* + +# Install packages COPY requirements.txt requirements.txt -RUN mamba install pip RUN python -m pip install --upgrade pip RUN python -m pip install -r requirements.txt @@ -81,18 +71,16 @@ COPY .streamlit/config.toml /app/.streamlit/config.toml COPY clean-up-workspaces.py /app/clean-up-workspaces.py # add cron job to the crontab -RUN echo "0 3 * * * /root/miniforge3/envs/streamlit-env/bin/python /app/clean-up-workspaces.py >> /app/clean-up-workspaces.log 2>&1" | crontab - +RUN echo "0 3 * * * /usr/local/bin/python /app/clean-up-workspaces.py >> /app/clean-up-workspaces.log 2>&1" | crontab - # create entrypoint script to start cron service and launch streamlit app -RUN echo "#!/bin/bash" > /app/entrypoint.sh -RUN echo "source /root/miniforge3/bin/activate streamlit-env" >> /app/entrypoint.sh && \ +RUN echo "#!/bin/bash" > /app/entrypoint.sh && \ echo "service cron start" >> /app/entrypoint.sh && \ - echo "streamlit run app.py" >> /app/entrypoint.sh -# make the script executable -RUN chmod +x /app/entrypoint.sh + echo "streamlit run app.py" >> /app/entrypoint.sh && \ + chmod +x /app/entrypoint.sh # Patch Analytics -RUN mamba run -n streamlit-env python hooks/hook-analytics.py +RUN python hooks/hook-analytics.py # Set Online Deployment RUN jq '.online_deployment = true' settings.json > tmp.json && mv tmp.json settings.json @@ -105,8 +93,5 @@ RUN if [ -n "$GH_TOKEN" ]; then \ echo "GH_TOKEN is not set, skipping the release asset download."; \ fi -# make sure that mamba environment is used -SHELL ["mamba", "run", "-n", "streamlit-env", "/bin/bash", "-c"] - EXPOSE $PORT ENTRYPOINT ["/app/entrypoint.sh"] From a6193fb0227fef314d812ef96fd8f24911a9a7ea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:47:06 +0000 Subject: [PATCH 3/5] Add documentation comments about base image changes Co-authored-by: t0mdavid-m <57191390+t0mdavid-m@users.noreply.github.com> --- Dockerfile | 3 ++- Dockerfile_simple | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fd7f3dd2..b1d0ac26 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,6 @@ -# This Dockerfile builds OpenMS, the TOPP tools, pyOpenMS and thidparty tools. +# This Dockerfile builds OpenMS, the TOPP tools, pyOpenMS and thirdparty tools. # It also adds a basic streamlit server that serves a pyOpenMS-based app. +# Uses multi-stage build: Ubuntu for compilation, python:3.10-slim-bookworm for runtime (~150MB lighter) # hints: # build image and give it a name (here: streamlitapp) with: docker build --no-cache -t streamlitapp:latest --build-arg GITHUB_TOKEN= . 2>&1 | tee build.log # check if image was build: docker image ls diff --git a/Dockerfile_simple b/Dockerfile_simple index 8807f65d..d18edfcb 100644 --- a/Dockerfile_simple +++ b/Dockerfile_simple @@ -1,5 +1,6 @@ # This Dockerfile creates a container with pyOpenMS # It also adds a basic streamlit server that serves a pyOpenMS-based app. +# Uses python:3.10-slim-bookworm as base image for smaller image size (~150MB vs ~700MB for ubuntu:22.04) # hints: # build image with: docker build -f Dockerfile_simple --no-cache -t streamlitapp:latest --build-arg GITHUB_TOKEN= . 2>&1 | tee build.log # check if image was build: docker image ls From a56eeee830418f7c3640d044d9b98b0cd65c39cd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:48:48 +0000 Subject: [PATCH 4/5] Address code review feedback: consolidate RUN commands and improve documentation Co-authored-by: t0mdavid-m <57191390+t0mdavid-m@users.noreply.github.com> --- Dockerfile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index b1d0ac26..ca0cfa36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -179,15 +179,17 @@ ENV PATH="/openms/bin/:/thirdparty/LuciPHOr2:/thirdparty/MSGFPlus:/thirdparty/Si ENV LD_LIBRARY_PATH="/openms/lib/:${LD_LIBRARY_PATH}" ENV OPENMS_DATA_PATH="/openms/share/" -# Copy pyOpenMS and Python packages from build stage -# First install pip requirements +# Install Python dependencies and copy pyOpenMS from build stage COPY requirements.txt ./requirements.txt -RUN python -m pip install --upgrade pip -RUN grep -Ev '^pyopenms([=<>!~].*)?$' requirements.txt > requirements_cleaned.txt && mv requirements_cleaned.txt requirements.txt -RUN python -m pip install -r requirements.txt +RUN python -m pip install --upgrade pip && \ + grep -Ev '^pyopenms([=<>!~].*)?$' requirements.txt > requirements_cleaned.txt && \ + mv requirements_cleaned.txt requirements.txt && \ + python -m pip install -r requirements.txt -# Copy pyOpenMS from build stage +# Copy pyOpenMS from build stage (built with mamba in compile-openms stage) +# Source path is from mamba environment, target is system site-packages COPY --from=compile-openms /root/miniforge3/envs/streamlit-env/lib/python3.10/site-packages/pyopenms* /usr/local/lib/python3.10/site-packages/ + # Create workdir and copy over all streamlit related files/folders. # note: specifying folder with slash as suffix and repeating the folder name seems important to preserve directory structure From 3bbd82539be3bf33ed5279111e7a3842913f3763 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:50:20 +0000 Subject: [PATCH 5/5] Improve pyOpenMS copy documentation to clarify wildcard pattern Co-authored-by: t0mdavid-m <57191390+t0mdavid-m@users.noreply.github.com> --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index ca0cfa36..b426ae3e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -188,6 +188,7 @@ RUN python -m pip install --upgrade pip && \ # Copy pyOpenMS from build stage (built with mamba in compile-openms stage) # Source path is from mamba environment, target is system site-packages +# The wildcard matches both pyopenms/ package dir and pyopenms-*.dist-info/ metadata COPY --from=compile-openms /root/miniforge3/envs/streamlit-env/lib/python3.10/site-packages/pyopenms* /usr/local/lib/python3.10/site-packages/ # Create workdir and copy over all streamlit related files/folders.