From 9a546b5e481582f1e4425bab191d2bd20ddfab85 Mon Sep 17 00:00:00 2001 From: Jonas Metzener Date: Wed, 22 Jan 2025 15:31:47 +0100 Subject: [PATCH] feat(build): use multi stage docker build for smaller images --- .github/workflows/tests.yml | 4 +-- Dockerfile | 52 +++++++++++++++++++++++++------------ Makefile | 4 +-- docker-compose.override.yml | 2 +- poetry.lock | 4 ++- pyproject.toml | 3 +++ 6 files changed, 46 insertions(+), 23 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9e7c1939..b0eac51b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: python-version: "3.12" cache: "poetry" - name: Install dependencies - run: poetry install --all-extras + run: poetry install --all-extras --with dev - name: Run gitlint run: poetry run gitlint --contrib contrib-title-conventional-commits - name: Run ruff check @@ -120,7 +120,7 @@ jobs: run: | sudo apt-get update sudo apt-get install -y --no-install-recommends util-linux unoconv libreoffice-writer - poetry install --all-extras + poetry install --all-extras --with dev - name: Set environment run: | echo "ENV=dev" >> .env diff --git a/Dockerfile b/Dockerfile index 00797673..ff64f384 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,40 @@ +FROM python:3.12 AS build + +ARG ENV=docker + +ENV PYTHONUNBUFFERED=1 +ENV POETRY_VIRTUALENVS_CREATE=false +ENV POETRY_HOME=/opt/poetry +ENV APP_HOME=/app + +WORKDIR $APP_HOME + +RUN pip install -U poetry + +# Install project dependencies +COPY pyproject.toml poetry.lock $APP_HOME/ +RUN \ + --mount=type=cache,target=.cache/pypoetry \ + poetry install --no-root --all-extras $(test "$ENV" = "dev" && echo "--with dev") + +# Install project itself +COPY . $APP_HOME +RUN \ + --mount=type=cache,target=.cache/pypoetry \ + poetry install --only-root + FROM python:3.12-slim +ARG UID=901 + # Needs to be set for users with manually set UID ENV HOME=/home/document-merge-service - -ENV PYTHONUNBUFFERED=1 ENV DJANGO_SETTINGS_MODULE=document_merge_service.settings -ENV APP_HOME=/app ENV UWSGI_INI=/app/uwsgi.ini ENV MEDIA_ROOT=/var/lib/document-merge-service/media ENV DATABASE_DIR=/var/lib/document-merge-service/data -ARG UID=901 +WORKDIR $APP_HOME RUN mkdir -p $APP_HOME $DATABASE_DIR/tmp $MEDIA_ROOT /var/www/static \ && useradd -u $UID -r document-merge-service --create-home \ @@ -21,30 +45,24 @@ RUN mkdir -p $APP_HOME $DATABASE_DIR/tmp $MEDIA_ROOT /var/www/static \ # root. && chown -R document-merge-service:root $DATABASE_DIR $MEDIA_ROOT $HOME /var/www/static -WORKDIR $APP_HOME - RUN \ - --mount=type=cache,target=/var/cache/apt \ + --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ apt-get update && apt-get install -y --no-install-recommends \ - build-essential \ default-libmysqlclient-dev \ libreoffice-writer \ - pkg-config \ unoconv \ util-linux \ wait-for-it \ && rm -rf /var/lib/apt/lists/* -RUN pip install -U poetry - USER document-merge-service -ARG ENV=docker -COPY pyproject.toml poetry.lock $APP_HOME/ -RUN if [ "$ENV" = "dev" ]; then poetry install --no-root --all-extras; else poetry install --no-root --all-extras --without dev; fi - -COPY . $APP_HOME +COPY --from=build /usr/local/lib/python3.12/site-packages/ /usr/local/lib/python3.12/site-packages/ +COPY --from=build /usr/local/bin/ /usr/local/bin/ EXPOSE 8000 -CMD /bin/sh -c "poetry run python ./manage.py migrate && poetry run uwsgi" +COPY . $APP_HOME + +CMD ["/bin/sh", "-c", "./manage.py migrate && uwsgi"] diff --git a/Makefile b/Makefile index 37987f5e..7eca0041 100644 --- a/Makefile +++ b/Makefile @@ -8,13 +8,13 @@ start: ## Start the development server @docker compose up -d --build test: ## Test the project - @docker compose exec document-merge-service poetry run sh -c "ruff format --diff --fix . && ruff check --diff . && mypy document_merge_service && pytest --no-cov-on-fail --cov --create-db" + @docker compose exec document-merge-service sh -c "ruff format --diff --fix . && ruff check --diff . && mypy document_merge_service && pytest --no-cov-on-fail --cov --create-db" shell: ## Shell into document merge service @docker compose exec document-merge-service poetry shell format: ## Format python code with ruff check - @docker compose exec document-merge-service poetry run ruff format --diff . + @docker compose exec document-merge-service ruff format --diff . dmypy: ## Run mypy locally (starts a deamon for performance) dmypy run document_merge_service diff --git a/docker-compose.override.yml b/docker-compose.override.yml index cd3dcd4e..bc0548f9 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -17,7 +17,7 @@ services: [ "/bin/sh", "-c", - "poetry run python ./manage.py migrate && poetry run python ./manage.py runserver 0.0.0.0:8000" + "./manage.py migrate && ./manage.py runserver 0.0.0.0:8000" ] environment: - ENV=dev diff --git a/poetry.lock b/poetry.lock index c34a61c9..252138c6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -509,6 +509,7 @@ files = [ {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, @@ -519,6 +520,7 @@ files = [ {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, @@ -3145,4 +3147,4 @@ s3 = ["boto3"] [metadata] lock-version = "2.0" python-versions = ">=3.10.0,<3.13" -content-hash = "489e50dee6404318973b37dc46b6d232fe72732e3f4fffb8bf161a4762cbdadf" +content-hash = "b80931356526abebde4e791ede6178d0ae440667f8e960a8489f21e05f6720fc" diff --git a/pyproject.toml b/pyproject.toml index 552d738e..0d1cb30f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,9 @@ uWSGI = "^2.0.21" xltpl = "~0.21" poetry = "^2.0.0" +[tool.poetry.group.dev] +optional = true + [tool.poetry.group.dev.dependencies] django-stubs = "5.1.1" factory-boy = "3.3.1"