-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Docs/docker best practices #9542
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 25 commits
4bc181b
0f565f8
9afee37
29a7ca9
2ca1352
25c30d9
45e964e
a9b16f2
32d4e36
e2d89e8
5500497
8e616ad
4e4159f
aaa83a3
f0b51e9
8d62c5a
08ad09c
b8f105c
85c7f6e
439feae
c541178
452caed
10454a3
246e181
93540eb
21ec55e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| FROM python:3.11-slim | ||
|
|
||
| ARG POETRY_VERSION=1.8 | ||
|
|
||
| # See https://python-poetry.org/docs/#ci-recommendations | ||
| RUN pip install "poetry==${POETRY_VERSION}" | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| # --- Reproduce the environment --- | ||
| # You can comment the following two lines if you prefer to manually install | ||
| # the dependencies from inside the container. | ||
| COPY pyproject.toml poetry.lock /app/ | ||
|
|
||
| RUN poetry install --no-root | ||
| # --- --- --- --- --- --- --- --- --- | ||
|
|
||
| ENTRYPOINT ["bash"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # Minimum Poetry image | ||
|
|
||
| ## Description | ||
|
|
||
| Minimum-poetry is the minimum-constructible image containing poetry, from an official python base image. | ||
|
|
||
| Expected size: ~218 MB, virtual env layer excluded. | ||
|
|
||
| ## Use cases | ||
|
|
||
| This image is especially useful when you don't yet have in mind a clear idea of the environment requirements you need, but need a reproducible first starting point for a python development environment. It' a quick and easy way to start. | ||
|
|
||
| ## How to use it | ||
|
|
||
| Run the following commmands from the *minimum-poetry* folder. They are just an example of how to use it. You can wrrite your custom commands according to Docker API. For more information about Docker please see the [official documentation](https://docs.docker.com/). | ||
|
|
||
| ### Build the image | ||
|
|
||
| ```bash | ||
| # This will build the image | ||
|
|
||
| TAG="minimum-poetry:0.1.0" | ||
| docker build \ | ||
| -t $TAG \ | ||
| --build-arg POETRY_VERSION="1.8.3" \ | ||
| "." | ||
| ``` | ||
|
|
||
| ### Run the container | ||
|
|
||
| ```bash | ||
| # This will run the container | ||
|
|
||
| docker run \ | ||
| --rm -it \ | ||
| -v ${PWD}:/app/shared \ | ||
| "$TAG" | ||
| ``` |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| [tool.poetry] | ||
| name = "minimum-poetry" | ||
| version = "0.1.0" | ||
| description = "A minimum functioning example of Docker image based on Poetry" | ||
| authors = ["gianfa <gian.angelini@hotmail.com>"] | ||
| readme = "README.md" | ||
|
|
||
| [tool.poetry.dependencies] | ||
| python = "^3.9" | ||
|
|
||
| numpy = "^2.0.0" | ||
| matplotlib = "^3.9.1" | ||
| pandas = "^2.2.2" | ||
|
|
||
|
|
||
| [build-system] | ||
| requires = ["poetry-core"] | ||
| build-backend = "poetry.core.masonry.api" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| FROM python:3.11-slim as builder | ||
|
|
||
| # --- Install Poetry --- | ||
| ARG POETRY_VERSION=1.8 | ||
|
|
||
| ENV POETRY_HOME=/opt/poetry | ||
| ENV POETRY_VIRTUALENVS_IN_PROJECT=1 | ||
| ENV POETRY_VIRTUALENVS_CREATE=1 | ||
| ENV PYTHONDONTWRITEBYTECODE=1 | ||
| ENV PYTHONUNBUFFERED=1 | ||
| # Tell Poetry where to place its cache and virtual environment | ||
gianfa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ENV POETRY_CACHE_DIR=/opt/.cache | ||
|
|
||
| RUN pip install "poetry==${POETRY_VERSION}" | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| # --- Reproduce the environment --- | ||
| # You can comment the following two lines if you prefer to manually install | ||
| # the dependencies from inside the container. | ||
| COPY pyproject.toml poetry.lock /app/ | ||
|
|
||
| # Install the dependencies and clear the cache afterwards. | ||
| # This may save some MBs. | ||
| RUN poetry install --no-root && rm -rf $POETRY_CACHE_DIR | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not using: This allows saving poetry package cache in local docker builder, which can be reused later. And it is not included into final image. |
||
|
|
||
| # Now let's build the runtime image from the builder. | ||
| # We'll just copy the env and the PATH reference. | ||
| FROM python:3.11-slim as runtime | ||
|
|
||
| ENV VIRTUAL_ENV=/app/.venv | ||
| ENV PATH="/app/.venv/bin:$PATH" | ||
|
|
||
| COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV} | ||
|
|
||
| ENTRYPOINT ["bash"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # Minimum Poetry multistage image | ||
|
|
||
| ## Description | ||
|
|
||
| poetry-multistage is a minimum-constructible multistage image containing Poetry, from an official Python base image. | ||
|
|
||
| Expected size: ~130MB, virtual env layer excluded. | ||
|
|
||
| ## Use cases | ||
|
|
||
| The usefulness of this image lies in the Dockerfile that shows an example of how to build a multistage image, to optimize the construction of the virtual environment. Always use it as a starting point for your images that you want to optimize in size. | ||
|
|
||
| ## How to use it | ||
|
|
||
| Run the following commmands from the *poetry-multistage* folder. They are just an example of how to use it. You can wrrite your custom commands according to Docker API. For more information about Docker please see the [official documentation](https://docs.docker.com/). | ||
|
|
||
| ### Build the image | ||
|
|
||
| ```bash | ||
| # This will build the image | ||
|
|
||
| TAG="poetry-multistage:0.1.0" | ||
| docker build \ | ||
| -t $TAG \ | ||
| --build-arg POETRY_VERSION="1.8.3" \ | ||
| "." | ||
| ``` | ||
|
|
||
| ### Run the container | ||
|
|
||
| ```bash | ||
| # This will run the container | ||
|
|
||
| docker run \ | ||
| --rm -it \ | ||
| -v ${PWD}:/app/shared \ | ||
| "$TAG" | ||
| ``` |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| [tool.poetry] | ||
| name = "poetry-multistage" | ||
| version = "0.1.0" | ||
| description = "A minimum functioning example of multistage Docker image based on Poetry" | ||
| authors = ["gianfa <gian.angelini@hotmail.com>"] | ||
| readme = "README.md" | ||
|
|
||
| [tool.poetry.dependencies] | ||
| python = "^3.9" | ||
|
|
||
| numpy = "^2.0.0" | ||
| matplotlib = "^3.9.1" | ||
| pandas = "^2.2.2" | ||
|
|
||
|
|
||
| [build-system] | ||
| requires = ["poetry-core"] | ||
| build-backend = "poetry.core.masonry.api" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| --- | ||
| title: "Docker Best Practices" | ||
| draft: false | ||
| type: docs | ||
| layout: "docs" | ||
|
|
||
| menu: | ||
| docs: | ||
| weight: 130 | ||
| --- | ||
|
|
||
| # Docker Best Practices | ||
|
|
||
| Poetry is a very valuable tool for increasing the robustness and reproducibility of a virtual environment on which your python code is based. When integrating Poetry into a Docker image, adopting some best practices will help improve build efficiency, container security, and help achieve lighter images. In this section, we will explore best practices for creating optimized and secure Docker images for projects managed with Poetry. | ||
| This section is a developing project, so you are warmly invited to contribute new suggestions. | ||
|
|
||
| ## Best Practices | ||
|
|
||
| The following best practices should be kept in mind | ||
|
|
||
| - [optional] Set the latest python version, in order to get the latest security patch. | ||
| - CAVEAT: It might reduce the reproducibility of the code, between one image build and another, since some function might change from one version of python to another. | ||
| - [highly suggested] Use `pip` to install Poetry (see [CI recommendations]({{< ref "#ci-recommendations" >}})). | ||
| - [highly suggested] Use [Docker cache mounts](https://docs.docker.com/build/cache/optimize/#use-cache-mounts) to reuse the Poetry installation cache and speed up builds. | ||
| - Or alternatively: clear Poetry cache after the installation. | ||
| - [critical] Never hardcode credentials to private sources. | ||
| - [optional] Install Poetry in a dedicated venv | ||
| - [highly suggested] Install the virtual env in the Python project (see `POETRY_VIRTUALENVS_IN_PROJECT`). This will be more convenient for carrying the env around with everything you need, making the project more self-contained. | ||
| - [highly suggested] Take advantage of Docker's layer caching mechanism to rebuild the image much faster. This means that you should reduce the variability points in the Dockerfile and the files linked to it (e.g. ARGS that may change). In alternative you can move them as far down in the Dockerfile as possible. For more info please see: | ||
| - https://docs.docker.com/build/cache/ | ||
| - https://pythonspeed.com/docker/ | ||
| - [highly suggested] copy source code only after `poetry install`. For more info see: [FAQ]({{< relref "faq/#poetry-busts-my-docker-cache-because-it-requires-me-to-copy-my-source-files-in-before-installing-3rd-party-dependencies" >}}) | ||
|
|
||
| ## Images examples and use cases | ||
|
|
||
| Below are general examples of Docker images, along with their typical use cases, to help you get started with developing your specific application. | ||
|
|
||
| ### Minimum-poetry | ||
|
|
||
| [Minimum-poetry](https://github.com/gianfa/poetry/tree/docs/docker-best-practices/docker-examples/minimum-poetry/README.md) is the minimum-constructible image containing poetry, from an official python base image. | ||
|
|
||
| Expected size: ~218 MB, virtual env layer excluded. | ||
|
|
||
| #### Specifics | ||
|
|
||
| - Based on *python:3.11-slim* official image. | ||
| - Just installs Poetry via pip. | ||
| - A basic virtual environment is created passing a pyproject.toml, via build context. | ||
|
|
||
| #### Use cases | ||
|
|
||
| As in the case of [Minimum-poetry](https://github.com/gianfa/poetry/tree/docs/docker-best-practices/docker-examples/minimum-poetry/README.md), this image is useful when you need to create a virtual self-content environment, complex at will. | ||
|
|
||
| ### Poetry-multistage | ||
|
|
||
| [Poetry-multistage](https://github.com/gianfa/poetry/tree/docs/docker-best-practices/docker-examples/poetry-multistage/README.md) is a minimum-constructible multistage image containing Poetry, from an official Python base image. It is very similar to [Minimum-poetry](#minimum-poetry), except that it may be more complex as it implements at least 2 more best practices. | ||
|
|
||
| Expected size: ~130MB, virtual env layer excluded. | ||
|
|
||
| #### Specifics | ||
|
|
||
| - Based on *python:3.11-slim* official image. | ||
| - Installs Poetry via pip. | ||
| - A basic virtual environment is created in the project folder (`POETRY_VIRTUALENVS_IN_PROJECT=1`, `POETRY_VIRTUALENVS_CREATE=1`). | ||
| - A multistage build is implemented, allowing you to directly copy only the project virtual env and set its reference in path, so as to minimize memory waste. | ||
|
|
||
| #### Use cases | ||
|
|
||
| The usefulness of this image lies in the Dockerfile that shows an example of how to build a multistage image, to optimize the construction of the virtual environment. Always use it as a starting point for your images that you want to optimize in size. |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using
python:3.11-alpineinstead (124MB vs 48.3MB for python 3.12)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for sharing this suggestion. In fact Alpine may be great for a “the lightest poetry image” version.
In general, I would not recommend Alpine, since it does not seem the best in terms of security and stability (see e.g. https://pythonspeed.com/articles/alpine-docker-python/).
Please feel free to share if you have different thoughts.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's interesting. No, I don't have any other argument other than "I've heard alpine small", and the image size comparison I shared earlier.
I'm not sure why you mention security though ? I didn't see anything related to that in your article
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right.
My answer comes from some rules of thumb like:
Anyway, it was enough to search on docker hub, to compare for example on python 3.11:
So I would say that from the security point of view there are no particular concerns. Finally, alpine team also state that they care about safety :) .
Thank you again