├── .github ├── dependabot.yml └── workflows │ └── docker-image.yml ├── Makefile ├── LICENSE ├── Dockerfile └── README.md /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "docker" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 Joseph Hale 2 | # 3 | # This software is released under the MIT License. 4 | # https://opensource.org/licenses/MIT 5 | 6 | build: 7 | docker build \ 8 | --tag thehale/python-poetry:latest \ 9 | --build-arg BUILDKIT_INLINE_CACHE=1 \ 10 | --cache-from thehale/python-poetry:latest \ 11 | . 12 | 13 | build-version: 14 | docker build \ 15 | --tag thehale/python-poetry:$(POETRY_VERSION)-py$(PYTHON_IMAGE_TAG) \ 16 | --build-arg POETRY_VERSION=$(POETRY_VERSION) \ 17 | --build-arg PYTHON_IMAGE_TAG=$(PYTHON_IMAGE_TAG) \ 18 | --build-arg BUILDKIT_INLINE_CACHE=1 \ 19 | --cache-from thehale/python-poetry:$(POETRY_VERSION)-py$(PYTHON_IMAGE_TAG) \ 20 | . 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Joseph Hale 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 Joseph Hale 2 | # 3 | # This software is released under the MIT License. 4 | # https://opensource.org/licenses/MIT 5 | 6 | # Default to the latest slim version of Python 7 | ARG PYTHON_IMAGE_TAG=slim 8 | 9 | ############################################################################### 10 | # POETRY BASE IMAGE - Provides environment variables for poetry 11 | ############################################################################### 12 | FROM python:${PYTHON_IMAGE_TAG} AS python-poetry-base 13 | # Default to the latest version of Poetry 14 | ARG POETRY_VERSION="" 15 | 16 | ENV POETRY_VERSION=${POETRY_VERSION} 17 | ENV POETRY_HOME="/opt/poetry" 18 | ENV POETRY_VIRTUALENVS_IN_PROJECT=true 19 | ENV POETRY_NO_INTERACTION=1 20 | 21 | ENV PATH="$POETRY_HOME/bin:$PATH" 22 | 23 | 24 | ############################################################################### 25 | # POETRY BUILDER IMAGE - Installs Poetry and dependencies 26 | ############################################################################### 27 | FROM python-poetry-base AS python-poetry-builder 28 | RUN apt-get update \ 29 | && apt-get install --no-install-recommends --assume-yes curl 30 | # Install Poetry via the official installer: https://python-poetry.org/docs/master/#installing-with-the-official-installer 31 | # This script respects $POETRY_VERSION & $POETRY_HOME 32 | RUN curl -sSL https://install.python-poetry.org | python3 - 33 | 34 | 35 | ############################################################################### 36 | # POETRY RUNTIME IMAGE - Copies the poetry installation into a smaller image 37 | ############################################################################### 38 | FROM python-poetry-base AS python-poetry 39 | COPY --from=python-poetry-builder $POETRY_HOME $POETRY_HOME 40 | RUN groupadd --gid 1000 nonroot \ 41 | && useradd --uid 1000 --gid 1000 --no-create-home --shell /bin/bash nonroot -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | env: 8 | DOCKER_REGISTRY: ${{secrets.DOCKER_REGISTRY}} 9 | DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}} 10 | DOCKER_ACCESS_TOKEN: ${{secrets.DOCKER_ACCESS_TOKEN}} 11 | GITHUB_CONTAINER_REGISTRY: ghcr.io 12 | 13 | jobs: 14 | 15 | build: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | - name: Build the Docker Image 22 | run: make build 23 | - name: Login to DockerHub 24 | run: echo -n $DOCKER_ACCESS_TOKEN | docker login $DOCKER_REGISTRY -u $DOCKER_USERNAME --password-stdin 25 | - name: Push Image to DockerHub 26 | run: docker push thehale/python-poetry:latest 27 | - name: Tag the image for the GitHub Container Registry 28 | run: docker tag thehale/python-poetry:latest ghcr.io/thehale/python-poetry:latest 29 | - name: Login to GitHub Container Registry 30 | run: echo -n ${{ secrets.GITHUB_TOKEN }} | docker login $GITHUB_CONTAINER_REGISTRY -u ${{ github.actor }} --password-stdin 31 | - name: Push Image to GitHub Container Registry 32 | run: docker push ghcr.io/thehale/python-poetry:latest 33 | 34 | 35 | build-versions: 36 | 37 | runs-on: ubuntu-latest 38 | 39 | strategy: 40 | matrix: 41 | python_image_tag: ["3.9-slim", "3.10-slim", "3.11-slim", "3.12-slim", "3.13-slim", "3.14-slim"] 42 | poetry_version: ["1.8.5", "2.2.1"] 43 | 44 | steps: 45 | - uses: actions/checkout@v3 46 | - name: Build the Docker Image 47 | run: > 48 | make build-version \ 49 | POETRY_VERSION=${{ matrix.poetry_version }} \ 50 | PYTHON_IMAGE_TAG=${{ matrix.python_image_tag }} 51 | - name: Login to DockerHub 52 | run: echo -n $DOCKER_ACCESS_TOKEN | docker login $DOCKER_REGISTRY -u $DOCKER_USERNAME --password-stdin 53 | - name: Push Image to DockerHub 54 | run: docker push thehale/python-poetry:${{ matrix.poetry_version }}-py${{ matrix.python_image_tag }} 55 | - name: Login to GitHub Container Registry 56 | run: echo -n ${{ secrets.GITHUB_TOKEN }} | docker login $GITHUB_CONTAINER_REGISTRY -u ${{ github.actor }} --password-stdin 57 | - name: Tag the image for the GitHub Container Registry 58 | run: docker tag thehale/python-poetry:${{ matrix.poetry_version }}-py${{ matrix.python_image_tag }} ghcr.io/thehale/python-poetry:${{ matrix.poetry_version }}-py${{ matrix.python_image_tag }} 59 | - name: Push Image to GitHub Container Registry 60 | run: docker push ghcr.io/thehale/python-poetry:${{ matrix.poetry_version }}-py${{ matrix.python_image_tag }} 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # [Python Poetry](https://github.com/python-poetry/poetry) in Docker 9 | 10 | 11 | 12 | [![](https://badgen.net/docker/pulls/thehale/python-poetry)](https://hub.docker.com/r/thehale/python-poetry) 13 | [![](https://badgen.net/github/license/thehale/docker-python-poetry)](https://github.com/thehale/docker-python-poetry/blob/master/LICENSE) 14 | [![](https://badgen.net/badge/icon/Sponsor/pink?icon=github&label)](https://github.com/sponsors/thehale) 15 | [![Joseph Hale's software engineering blog](https://jhale.dev/badges/website.svg)](https://jhale.dev) 16 | [![](https://jhale.dev/badges/follow.svg)](https://www.linkedin.com/comm/mynetwork/discovery-see-all?usecase=PEOPLE_FOLLOWS&followMember=thehale) 17 | 18 | Robust, lightweight, configurable `python-poetry` Docker images for any use 19 | case. 20 | 21 | _NOTE: This repository is **not** an official project from the creators of 22 | Python Poetry. Hopefully you find it useful anyway!_ 23 | 24 | ## Quickstart 25 | 26 | Most of the time, you will be using these images as a base image for your own 27 | Dockerfiles (e.g. devcontainers, building Python applications, etc.) 28 | 29 | ```Dockerfile 30 | FROM thehale/python-poetry 31 | 32 | RUN poetry --version 33 | # Your build steps here. 34 | ``` 35 | 36 | However, you can also download and run the latest `python-poetry` Docker image 37 | by pulling it from DockerHub. 38 | 39 | ``` 40 | docker pull thehale/python-poetry 41 | docker run --rm thehale/python-poetry poetry --version 42 | ``` 43 | 44 | There are tagged images for all the latest stable versions of `python-poetry` 45 | for all versions of Python that Poetry supports (>3.7). You can see the [full 46 | tag list on DockerHub](https://hub.docker.com/r/thehale/python-poetry/tags). 47 | 48 | ## Build Your Own Image 49 | 50 | This repo automatically builds images for the latest stable versions of 51 | `python-poetry` for all supported versions of Python (>3.7). 52 | 53 | - You can see the full build matrix in 54 | [.github/workflows/docker-image.yml](https://github.com/thehale/docker-python-poetry/blob/master/.github/workflows/docker-image.yml) 55 | 56 | However, if you need a combination that isn't automatically built, you can 57 | easily create your own by modifying the command below to contain your preferred 58 | values for `POETRY_VERSION` and `PYTHON_IMAGE_TAG`: 59 | 60 | ```bash 61 | make build-version \ 62 | POETRY_VERSION="1.1.13" \ 63 | PYTHON_IMAGE_TAG="3.10-slim" 64 | ``` 65 | 66 | ## Non-root User 67 | 68 | > [!NOTE] 69 | > 70 | > This section was adapted from the Node.js docs for [**Non-root 71 | > user**](https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#non-root-user) 72 | > in their Docker images. 73 | 74 | 75 | By default, Docker runs commands inside the container as root which violates the [Principle of Least Privilege (PoLP)](https://en.wikipedia.org/wiki/Principle_of_least_privilege) when superuser permissions are not strictly required. You want to run the container as an unprivileged user whenever possible. The nonroot images provide the `nonroot` user for such purpose. The Docker Image can then be run with the `nonroot` user in the following way: 76 | 77 | ``` 78 | -u "nonroot" 79 | ``` 80 | 81 | Alternatively, the user can be activated in the `Dockerfile`: 82 | 83 | ```Dockerfile 84 | FROM thehale/python-poetry:1.8.3 85 | ... 86 | # At the end, set the user to use when running this image 87 | USER nonroot 88 | ``` 89 | 90 | > [!TIP] 91 | > 92 | > When using the `nonroot` user, remember to assign the corresponding ownership 93 | > to your application tree (e.g. `chmod`). 94 | 95 | Note that the `nonroot` user is neither a build-time nor a run-time dependency 96 | and it can be removed or altered, as long as the functionality of the 97 | application you want to add to the container does not depend on it. 98 | 99 | If you do not want nor need the user created in this image, you can remove it with the following: 100 | 101 | ```Dockerfile 102 | # For debian based images use: 103 | RUN userdel -r nonroot 104 | 105 | # For alpine based images use: 106 | RUN deluser --remove-home nonroot 107 | ``` 108 | 109 | If you need to change the uid/gid of the user, you can use: 110 | 111 | ```Dockerfile 112 | RUN groupmod -g 999 nonroot && usermod -u 999 -g 999 nonroot 113 | ``` 114 | 115 | If you need another name for the user (ex. `myapp`), execute: 116 | 117 | ```Dockerfile 118 | RUN usermod -d /home/myapp -l myapp nonroot 119 | ``` 120 | 121 | For alpine based images, you do not have `groupmod` nor `usermod`, so to change the uid/gid you have to delete the previous user: 122 | 123 | ```Dockerfile 124 | RUN deluser --remove-home nonroot \ 125 | && addgroup -S nonroot -g 999 \ 126 | && adduser -S -G nonroot -u 999 nonroot 127 | ``` 128 | 129 | ## License 130 | 131 | This project is licensed under the terms of the [MIT License](https://choosealicense.com/licenses/mit/). 132 | --------------------------------------------------------------------------------