From 0a778c135f37243277d1dbac2a6490455b228cfc Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Fri, 26 Mar 2021 13:42:58 -0500 Subject: [PATCH] Make pip install faster in Docker build for Complement testing (#9610) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make pip install faster in Docker build for [Complement](https://github.com/matrix-org/complement) testing. If files have changed in a `COPY` command, Docker will invalidate all of the layers below. So I changed the order of operations to install all dependencies before we `COPY synapse /synapse/synapse/`. This allows Docker to use our cached layer of dependencies even when we change the source of Synapse and speed up builds dramatically! `53.5s` -> `3.7s` builds 🤘 As an alternative, I did try using BuildKit caches but this still took 30 seconds overall on that step. 15 seconds to gather the dependencies from the cache and another 15 seconds to `Installing collected packages`. Fix https://github.com/matrix-org/synapse/issues/9364 --- changelog.d/9610.docker | 1 + docker/Dockerfile | 82 ++++++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 42 deletions(-) create mode 100644 changelog.d/9610.docker diff --git a/changelog.d/9610.docker b/changelog.d/9610.docker new file mode 100644 index 000000000..056252a66 --- /dev/null +++ b/changelog.d/9610.docker @@ -0,0 +1 @@ +Speed up Docker builds and make it nicer to test against Complement while developing (install all dependencies before copying the project). diff --git a/docker/Dockerfile b/docker/Dockerfile index a442b3459..5b7bf0277 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -25,42 +25,40 @@ LABEL org.opencontainers.image.licenses='Apache-2.0' # install the OS build deps RUN apt-get update && apt-get install -y \ - build-essential \ - libffi-dev \ - libjpeg-dev \ - libpq-dev \ - libssl-dev \ - libwebp-dev \ - libxml++2.6-dev \ - libxslt1-dev \ - openssl \ - rustc \ - zlib1g-dev \ - && rm -rf /var/lib/apt/lists/* + build-essential \ + libffi-dev \ + libjpeg-dev \ + libpq-dev \ + libssl-dev \ + libwebp-dev \ + libxml++2.6-dev \ + libxslt1-dev \ + openssl \ + rustc \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* -# Build dependencies that are not available as wheels, to speed up rebuilds -RUN pip install --prefix="/install" --no-warn-script-location \ - cryptography \ - frozendict \ - jaeger-client \ - opentracing \ - # Match the version constraints of Synapse - "prometheus_client>=0.4.0" \ - psycopg2 \ - pycparser \ - pyrsistent \ - pyyaml \ - simplejson \ - threadloop \ - thrift - -# now install synapse and all of the python deps to /install. -COPY synapse /synapse/synapse/ +# Copy just what we need to pip install COPY scripts /synapse/scripts/ COPY MANIFEST.in README.rst setup.py synctl /synapse/ +COPY synapse/__init__.py /synapse/synapse/__init__.py +COPY synapse/python_dependencies.py /synapse/synapse/python_dependencies.py +# To speed up rebuilds, install all of the dependencies before we copy over +# the whole synapse project so that we this layer in the Docker cache can be +# used while you develop on the source +# +# This is aiming at installing the `install_requires` and `extras_require` from `setup.py` RUN pip install --prefix="/install" --no-warn-script-location \ - /synapse[all] + /synapse[all] + +# Copy over the rest of the project +COPY synapse /synapse/synapse/ + +# Install the synapse package itself and all of its children packages. +# +# This is aiming at installing only the `packages=find_packages(...)` from `setup.py +RUN pip install --prefix="/install" --no-deps --no-warn-script-location /synapse ### ### Stage 1: runtime @@ -69,16 +67,16 @@ RUN pip install --prefix="/install" --no-warn-script-location \ FROM docker.io/python:${PYTHON_VERSION}-slim RUN apt-get update && apt-get install -y \ - curl \ - gosu \ - libjpeg62-turbo \ - libpq5 \ - libwebp6 \ - xmlsec1 \ - libjemalloc2 \ - libssl-dev \ - openssl \ - && rm -rf /var/lib/apt/lists/* + curl \ + gosu \ + libjpeg62-turbo \ + libpq5 \ + libwebp6 \ + xmlsec1 \ + libjemalloc2 \ + libssl-dev \ + openssl \ + && rm -rf /var/lib/apt/lists/* COPY --from=builder /install /usr/local COPY ./docker/start.py /start.py @@ -91,4 +89,4 @@ EXPOSE 8008/tcp 8009/tcp 8448/tcp ENTRYPOINT ["/start.py"] HEALTHCHECK --interval=1m --timeout=5s \ - CMD curl -fSs http://localhost:8008/health || exit 1 + CMD curl -fSs http://localhost:8008/health || exit 1