diff --git a/docker-compose.yml b/docker-compose.yml index a4bd91547..0f4c753b3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -74,8 +74,10 @@ services: hasher-api: build: context: . - dockerfile: ./docker/hasher-api/Dockerfile + dockerfile: ./docker/pixl-python/Dockerfile + target: hasher_api args: + PIXL_PACKAGE_DIR: hasher <<: *build-args-common environment: <<: [*proxy-common, *pixl-common-env] @@ -93,7 +95,6 @@ services: networks: - pixl-net healthcheck: - test: ["CMD", "curl", "-f", "http://hasher-api:8000/heart-beat"] interval: 10s timeout: 30s retries: 5 @@ -102,9 +103,11 @@ services: orthanc-anon: build: context: . - dockerfile: ./docker/orthanc-anon/Dockerfile + dockerfile: ./docker/orthanc/Dockerfile + target: pixl_orthanc_anon args: <<: *build-args-common + ORTHANC_DIR: orthanc-anon ORTHANC_CONCURRENT_JOBS: ${ORTHANC_CONCURRENT_JOBS} platform: linux/amd64 command: /run/secrets @@ -171,9 +174,11 @@ services: orthanc-raw: build: context: . - dockerfile: ./docker/orthanc-raw/Dockerfile + dockerfile: ./docker/orthanc/Dockerfile + target: pixl_orthanc_raw args: <<: *build-args-common + ORTHANC_DIR: orthanc-raw ORTHANC_RAW_MAXIMUM_STORAGE_SIZE: ${ORTHANC_RAW_MAXIMUM_STORAGE_SIZE} ORTHANC_RAW_JOB_HISTORY_SIZE: ${ORTHANC_RAW_JOB_HISTORY_SIZE} ORTHANC_CONCURRENT_JOBS: ${ORTHANC_CONCURRENT_JOBS} @@ -249,8 +254,10 @@ services: export-api: build: context: . - dockerfile: ./docker/export-api/Dockerfile + dockerfile: ./docker/pixl-python/Dockerfile + target: export_api args: + PIXL_PACKAGE_DIR: pixl_export <<: *build-args-common environment: <<: @@ -297,8 +304,10 @@ services: imaging-api: build: context: . - dockerfile: ./docker/imaging-api/Dockerfile + dockerfile: ./docker/pixl-python/Dockerfile + target: imaging_api args: + PIXL_PACKAGE_DIR: pixl_imaging <<: *build-args-common depends_on: queue: @@ -308,7 +317,6 @@ services: orthanc-anon: condition: service_healthy healthcheck: - test: curl -f http://0.0.0.0:8000/heart-beat interval: 10s timeout: 30s retries: 5 diff --git a/docker/hasher-api/Dockerfile b/docker/hasher-api/Dockerfile deleted file mode 100644 index 0481ea95b..000000000 --- a/docker/hasher-api/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) University College London Hospitals NHS Foundation Trust -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -FROM python:3.12.4-slim-bullseye@sha256:26ce493641ad3b1c8a6202117c31340c7bbb2dc126f1aeee8ea3972730a81dc6 -SHELL ["/bin/bash", "-o", "pipefail", "-e", "-u", "-x", "-c"] - -ARG TEST="false" - -# OS setup -RUN export DEBIAN_FRONTEND=noninteractive && \ - apt-get update && \ - apt-get install --yes --no-install-recommends procps ca-certificates \ - iproute2 git curl libpq-dev curl gnupg g++ locales tzdata -RUN sed -i '/en_GB.UTF-8/s/^# //g' /etc/locale.gen && locale-gen - -# clean up -RUN apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* - -WORKDIR /app - -# Install requirements before copying modules -COPY ./pixl_core/pyproject.toml ./pixl_core/pyproject.toml -COPY ./hasher/pyproject.toml . -RUN --mount=type=cache,target=/root/.cache \ - pip3 install --no-cache-dir pixl_core/ \ - && pip3 install --no-cache-dir /app/ - -COPY ./pixl_core/ pixl_core/ -COPY ./hasher/ . -RUN --mount=type=cache,target=/root/.cache \ - pip install --no-cache-dir --force-reinstall --no-deps pixl_core/ . && \ - if [ "$TEST" = "true" ]; \ - then pip install --no-cache-dir --force-reinstall --no-deps pixl_core/[test] \ - --no-cache-dir --force-reinstall --no-deps .[test]; fi - -ENTRYPOINT ["uvicorn", "hasher.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/docker/imaging-api/Dockerfile b/docker/imaging-api/Dockerfile deleted file mode 100644 index 73fa0728b..000000000 --- a/docker/imaging-api/Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) University College London Hospitals NHS Foundation Trust -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -FROM python:3.12.4-slim-bullseye@sha256:26ce493641ad3b1c8a6202117c31340c7bbb2dc126f1aeee8ea3972730a81dc6 -SHELL ["/bin/bash", "-o", "pipefail", "-e", "-u", "-x", "-c"] - -ARG TEST="false" - -RUN export DEBIAN_FRONTEND=noninteractive && \ - apt-get update && \ - apt-get install --yes --no-install-recommends \ - procps \ - ca-certificates \ - iproute2 \ - libpq-dev \ - curl \ - gnupg \ - locales \ - tzdata -RUN sed -i '/en_GB.UTF-8/s/^# //g' /etc/locale.gen && locale-gen -RUN apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* - -WORKDIR /app - -# Install requirements before copying modules -COPY ./pixl_core/pyproject.toml ./pixl_core/pyproject.toml -COPY ./pixl_imaging/pyproject.toml ./pixl_imaging/pyproject.toml -RUN --mount=type=cache,target=/root/.cache \ - pip3 install --no-cache-dir pixl_core/ \ - && pip3 install --no-cache-dir pixl_imaging/ - -COPY ./pixl_core/ pixl_core/ -COPY ./pixl_imaging/ . -RUN --mount=type=cache,target=/root/.cache \ - pip install --no-cache-dir --force-reinstall --no-deps pixl_core/ . && \ - if [ "$TEST" = "true" ]; \ - then pip install --no-cache-dir --force-reinstall --no-deps pixl_core/[test] \ - --no-cache-dir --force-reinstall --no-deps .[test]; fi - -ENTRYPOINT ["/app/scripts/migrate_and_run.sh"] diff --git a/docker/orthanc-anon/Dockerfile b/docker/orthanc-anon/Dockerfile deleted file mode 100644 index 7415d0eac..000000000 --- a/docker/orthanc-anon/Dockerfile +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) University College London Hospitals NHS Foundation Trust -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -FROM orthancteam/orthanc:24.7.3@sha256:57a3d037729897331027ddc00c12695b50f1effbbf805f855396f3d0248d2d5f -SHELL ["/bin/bash", "-o", "pipefail", "-e", "-u", "-x", "-c"] - -# Create a virtual environment, recommended since python 3.11 and Debian bookworm based images -# where you get a warning when installing system-wide packages. -RUN export DEBIAN_FRONTEND=noninteractive && \ - apt-get update && \ - apt-get install --yes --no-install-recommends python3-venv tzdata -RUN python3 -m venv /.venv - -# Install curl, used in system tests -RUN apt-get --assume-yes install curl - -# Install requirements before copying modules -COPY ./pixl_core/pyproject.toml /pixl_core/pyproject.toml -COPY ./pixl_dcmd/pyproject.toml /pixl_dcmd/pyproject.toml - -RUN --mount=type=cache,target=/root/.cache \ - /.venv/bin/pip install pixl_core/ \ - && /.venv/bin/pip install pixl_dcmd/ - -ENV PYTHONPATH=/.venv/lib64/python3.11/site-packages/ -COPY ./orthanc/orthanc-anon/plugin/download_dicom_spec.py /etc/orthanc/download_dicom_spec.py -RUN --mount=type=cache,target=/root/.cache \ - python3 /etc/orthanc/download_dicom_spec.py - -COPY ./orthanc/orthanc-anon/plugin/pixl.py /etc/orthanc/pixl.py - -COPY ./pixl_core/ /pixl_core -RUN --mount=type=cache,target=/root/.cache \ - /.venv/bin/pip install --no-cache-dir --force-reinstall --no-deps ./pixl_core - -COPY ./pixl_dcmd/ /pixl_dcmd -RUN --mount=type=cache,target=/root/.cache \ - /.venv/bin/pip install --no-cache-dir --force-reinstall --no-deps ./pixl_dcmd - -ARG ORTHANC_CONCURRENT_JOBS -COPY ./orthanc/orthanc-anon/config /run/secrets - -RUN sed -i "s/\${ORTHANC_CONCURRENT_JOBS}/${ORTHANC_CONCURRENT_JOBS:-5}/g" /run/secrets/orthanc.json diff --git a/docker/orthanc-raw/Dockerfile b/docker/orthanc/Dockerfile similarity index 68% rename from docker/orthanc-raw/Dockerfile rename to docker/orthanc/Dockerfile index d0e6800cf..e1d3b2482 100644 --- a/docker/orthanc-raw/Dockerfile +++ b/docker/orthanc/Dockerfile @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -FROM orthancteam/orthanc:24.7.3@sha256:57a3d037729897331027ddc00c12695b50f1effbbf805f855396f3d0248d2d5f +FROM orthancteam/orthanc:24.7.3@sha256:57a3d037729897331027ddc00c12695b50f1effbbf805f855396f3d0248d2d5f AS pixl_orthanc_apt SHELL ["/bin/bash", "-o", "pipefail", "-e", "-u", "-x", "-c"] # Create a virtual environment, recommended since python 3.11 and Debian bookworm based images @@ -20,6 +20,24 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && \ apt-get install --yes --no-install-recommends python3-venv tzdata RUN python3 -m venv /.venv +ENV PYTHONPATH=/.venv/lib64/python3.11/site-packages/ + +# Install curl for now, but try to remove this dependency +RUN apt-get --assume-yes install curl + +FROM pixl_orthanc_apt AS pixl_orthanc_with_spec +# This part changes rarely, so do it nice and early to avoid redoing it every time we change our code. +# It does have a dependency though, which would normally be fulfilled by our project files, so install that +# manually. +# Do it in dead end build stage to discard this environment afterwards, +# and because the spec is only needed in orthanc-anon. +RUN /.venv/bin/pip install dicom-validator +COPY ./orthanc/orthanc-anon/plugin/download_dicom_spec.py /etc/orthanc/download_dicom_spec.py +RUN --mount=type=cache,target=/root/.cache \ + python3 /etc/orthanc/download_dicom_spec.py + + +FROM pixl_orthanc_apt AS pixl_orthanc_base # Install requirements before copying modules COPY ./pixl_core/pyproject.toml /pixl_core/pyproject.toml @@ -37,17 +55,22 @@ COPY ./pixl_dcmd/ /pixl_dcmd RUN --mount=type=cache,target=/root/.cache \ /.venv/bin/pip install --no-cache-dir --force-reinstall --no-deps ./pixl_dcmd -COPY ./orthanc/orthanc-raw/plugin/pixl.py /etc/orthanc/pixl.py +ARG ORTHANC_DIR +COPY ./orthanc/${ORTHANC_DIR}/plugin/pixl.py /etc/orthanc/pixl.py +COPY ./orthanc/${ORTHANC_DIR}/config /run/secrets # Orthanc can't substitute environment veriables as integers so copy and replace before running +ARG ORTHANC_CONCURRENT_JOBS +RUN sed -i "s/\${ORTHANC_CONCURRENT_JOBS}/${ORTHANC_CONCURRENT_JOBS:-5}/g" /run/secrets/orthanc.json + +FROM pixl_orthanc_base AS pixl_orthanc_raw + ARG ORTHANC_RAW_MAXIMUM_STORAGE_SIZE ARG ORTHANC_RAW_JOB_HISTORY_SIZE -ARG ORTHANC_CONCURRENT_JOBS ARG PIXL_DICOM_TRANSFER_TIMEOUT -COPY ./orthanc/orthanc-raw/config /run/secrets RUN sed -i "s/\${ORTHANC_RAW_MAXIMUM_STORAGE_SIZE}/${ORTHANC_RAW_MAXIMUM_STORAGE_SIZE:-0}/g" /run/secrets/orthanc.json RUN sed -i "s/\${ORTHANC_RAW_JOB_HISTORY_SIZE}/${ORTHANC_RAW_JOB_HISTORY_SIZE:-100}/g" /run/secrets/orthanc.json -RUN sed -i "s/\${ORTHANC_CONCURRENT_JOBS}/${ORTHANC_CONCURRENT_JOBS:-5}/g" /run/secrets/orthanc.json RUN sed -i "s/\${ORTHANC_RAW_STABLE_SECONDS}/${PIXL_DICOM_TRANSFER_TIMEOUT:-600}/g" /run/secrets/orthanc.json -ENV PYTHONPATH=/.venv/lib64/python3.11/site-packages/ +FROM pixl_orthanc_base AS pixl_orthanc_anon +COPY --from=pixl_orthanc_with_spec /root/dicom-validator /root/dicom-validator diff --git a/docker/export-api/Dockerfile b/docker/pixl-python/Dockerfile similarity index 74% rename from docker/export-api/Dockerfile rename to docker/pixl-python/Dockerfile index 48f633148..84f188c57 100644 --- a/docker/export-api/Dockerfile +++ b/docker/pixl-python/Dockerfile @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -FROM python:3.12.4-slim-bullseye@sha256:26ce493641ad3b1c8a6202117c31340c7bbb2dc126f1aeee8ea3972730a81dc6 +FROM python:3.12.4-slim-bullseye@sha256:26ce493641ad3b1c8a6202117c31340c7bbb2dc126f1aeee8ea3972730a81dc6 AS pixl_python_base SHELL ["/bin/bash", "-o", "pipefail", "-e", "-u", "-x", "-c"] ARG TEST="false" @@ -31,20 +31,32 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ RUN sed -i '/en_GB.UTF-8/s/^# //g' /etc/locale.gen && locale-gen RUN apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* +HEALTHCHECK CMD /usr/bin/curl -f http://0.0.0.0:8000/heart-beat || exit 1 + WORKDIR /app +# specify what we're installing using build time arg +ARG PIXL_PACKAGE_DIR # Install requirements before copying modules COPY ./pixl_core/pyproject.toml ./pixl_core/pyproject.toml -COPY ./pixl_export/pyproject.toml ./pixl_export/pyproject.toml +COPY ./$PIXL_PACKAGE_DIR/pyproject.toml ./$PIXL_PACKAGE_DIR/pyproject.toml RUN pip3 install --no-cache-dir pixl_core/ \ - && pip3 install --no-cache-dir pixl_export/ + && pip3 install --no-cache-dir $PIXL_PACKAGE_DIR/ +# Install our code COPY ./pixl_core/ pixl_core/ -COPY ./pixl_export/ . +COPY ./$PIXL_PACKAGE_DIR/ . RUN pip install --no-cache-dir --force-reinstall --no-deps pixl_core/ \ --no-cache-dir --force-reinstall --no-deps . && \ if [ "$TEST" = "true" ]; then pip install --no-cache-dir pixl_core/[test] .[test]; fi -HEALTHCHECK CMD /usr/bin/curl -f http://0.0.0.0:8000/heart-beat || exit 1 +# Each container should be run with a different entry point +FROM pixl_python_base AS export_api ENTRYPOINT ["uvicorn", "pixl_export.main:app", "--host", "0.0.0.0", "--port", "8000"] + +FROM pixl_python_base AS hasher_api +ENTRYPOINT ["uvicorn", "hasher.main:app", "--host", "0.0.0.0", "--port", "8000"] + +FROM pixl_python_base AS imaging_api +ENTRYPOINT ["/app/scripts/migrate_and_run.sh"] diff --git a/pixl_imaging/tests/docker-compose.yml b/pixl_imaging/tests/docker-compose.yml index 6d247a52d..a72c8b865 100644 --- a/pixl_imaging/tests/docker-compose.yml +++ b/pixl_imaging/tests/docker-compose.yml @@ -68,9 +68,11 @@ services: orthanc-raw: build: context: ../../ - dockerfile: ./docker/orthanc-raw/Dockerfile + dockerfile: ./docker/orthanc/Dockerfile + target: pixl_orthanc_raw args: PIXL_DICOM_TRANSFER_TIMEOUT: 30 + ORTHANC_DIR: orthanc-raw environment: ORTHANC_NAME: "PIXL: Raw" ORTHANC_USERNAME: "orthanc"