Skip to content

Commit

Permalink
Refactor Python and Orthanc Dockerfiles (#583)
Browse files Browse the repository at this point in the history
Fixes #588 by de-duping the orthanc and PIXL dockerfiles. This was factored out from PR #400 which had become too big.
* Merge three pixl python dockerfiles into one multi-stage dockerfile to
avoid repetition.
* Merge orthanc dockerfiles, downloading dicom spec at a more separate stage.
* Specify healthcheck command in only one place
  • Loading branch information
jeremyestein authored Jan 6, 2025
1 parent 208e74c commit 807f84b
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 168 deletions.
22 changes: 15 additions & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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:
<<:
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down
46 changes: 0 additions & 46 deletions docker/hasher-api/Dockerfile

This file was deleted.

50 changes: 0 additions & 50 deletions docker/imaging-api/Dockerfile

This file was deleted.

53 changes: 0 additions & 53 deletions docker/orthanc-anon/Dockerfile

This file was deleted.

35 changes: 29 additions & 6 deletions docker/orthanc-raw/Dockerfile → docker/orthanc/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
22 changes: 17 additions & 5 deletions docker/export-api/Dockerfile → docker/pixl-python/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"]
4 changes: 3 additions & 1 deletion pixl_imaging/tests/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit 807f84b

Please sign in to comment.