你能给我一个Dockerfile的例子吗?我可以在其中安装所有我需要的软件包。锁定和pyproject。toml到我的镜像/容器从Docker?
当前回答
我看到这里所有的答案都是用pip的方式安装诗词,以避免版本问题。 如果定义为安装最合适的版本,则安装诗歌的官方方法是读取poeetry_version env变量。
在github上有一个问题,我认为这张票的解决方案非常有趣:
# `python-base` sets up all our shared environment variables
FROM python:3.8.1-slim as python-base
# python
ENV PYTHONUNBUFFERED=1 \
# prevents python creating .pyc files
PYTHONDONTWRITEBYTECODE=1 \
\
# pip
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100 \
\
# poetry
# https://python-poetry.org/docs/configuration/#using-environment-variables
POETRY_VERSION=1.0.3 \
# make poetry install to this location
POETRY_HOME="/opt/poetry" \
# make poetry create the virtual environment in the project's root
# it gets named `.venv`
POETRY_VIRTUALENVS_IN_PROJECT=true \
# do not ask any interactive question
POETRY_NO_INTERACTION=1 \
\
# paths
# this is where our requirements + virtual environment will live
PYSETUP_PATH="/opt/pysetup" \
VENV_PATH="/opt/pysetup/.venv"
# prepend poetry and venv to path
ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"
# `builder-base` stage is used to build deps + create our virtual environment
FROM python-base as builder-base
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
# deps for installing poetry
curl \
# deps for building python deps
build-essential
# install poetry - respects $POETRY_VERSION & $POETRY_HOME
RUN curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
# copy project requirement files here to ensure they will be cached.
WORKDIR $PYSETUP_PATH
COPY poetry.lock pyproject.toml ./
# install runtime deps - uses $POETRY_VIRTUALENVS_IN_PROJECT internally
RUN poetry install --no-dev
# `development` image is used during development / testing
FROM python-base as development
ENV FASTAPI_ENV=development
WORKDIR $PYSETUP_PATH
# copy in our built poetry + venv
COPY --from=builder-base $POETRY_HOME $POETRY_HOME
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
# quicker install as runtime deps are already installed
RUN poetry install
# will become mountpoint of our code
WORKDIR /app
EXPOSE 8000
CMD ["uvicorn", "--reload", "main:app"]
# `production` image used for runtime
FROM python-base as production
ENV FASTAPI_ENV=production
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
COPY ./app /app/
WORKDIR /app
CMD ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "main:app"]
其他回答
我看到这里所有的答案都是用pip的方式安装诗词,以避免版本问题。 如果定义为安装最合适的版本,则安装诗歌的官方方法是读取poeetry_version env变量。
在github上有一个问题,我认为这张票的解决方案非常有趣:
# `python-base` sets up all our shared environment variables
FROM python:3.8.1-slim as python-base
# python
ENV PYTHONUNBUFFERED=1 \
# prevents python creating .pyc files
PYTHONDONTWRITEBYTECODE=1 \
\
# pip
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100 \
\
# poetry
# https://python-poetry.org/docs/configuration/#using-environment-variables
POETRY_VERSION=1.0.3 \
# make poetry install to this location
POETRY_HOME="/opt/poetry" \
# make poetry create the virtual environment in the project's root
# it gets named `.venv`
POETRY_VIRTUALENVS_IN_PROJECT=true \
# do not ask any interactive question
POETRY_NO_INTERACTION=1 \
\
# paths
# this is where our requirements + virtual environment will live
PYSETUP_PATH="/opt/pysetup" \
VENV_PATH="/opt/pysetup/.venv"
# prepend poetry and venv to path
ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"
# `builder-base` stage is used to build deps + create our virtual environment
FROM python-base as builder-base
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
# deps for installing poetry
curl \
# deps for building python deps
build-essential
# install poetry - respects $POETRY_VERSION & $POETRY_HOME
RUN curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
# copy project requirement files here to ensure they will be cached.
WORKDIR $PYSETUP_PATH
COPY poetry.lock pyproject.toml ./
# install runtime deps - uses $POETRY_VIRTUALENVS_IN_PROJECT internally
RUN poetry install --no-dev
# `development` image is used during development / testing
FROM python-base as development
ENV FASTAPI_ENV=development
WORKDIR $PYSETUP_PATH
# copy in our built poetry + venv
COPY --from=builder-base $POETRY_HOME $POETRY_HOME
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
# quicker install as runtime deps are already installed
RUN poetry install
# will become mountpoint of our code
WORKDIR /app
EXPOSE 8000
CMD ["uvicorn", "--reload", "main:app"]
# `production` image used for runtime
FROM python-base as production
ENV FASTAPI_ENV=production
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
COPY ./app /app/
WORKDIR /app
CMD ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "main:app"]
这是对@Claudio提供的答案的一个小修改,它使用了@sobolevn在他的回答中描述的新的诗歌安装-无根特性。
为了强制poetry将依赖项安装到特定的virtualenv中,首先需要启用它。
. /path/to/virtualenv/bin/activate && poetry install
因此,将这些添加到@Claudio的答案中
FROM python:3.10-slim as base
ENV PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
PYTHONUNBUFFERED=1
WORKDIR /app
FROM base as builder
ENV PIP_DEFAULT_TIMEOUT=100 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1 \
POETRY_VERSION=1.3.1
RUN pip install "poetry==$POETRY_VERSION"
COPY pyproject.toml poetry.lock README.md ./
# if your project is stored in src, uncomment line below
# COPY src ./src
# or this if your file is stored in $PROJECT_NAME, assuming `myproject`
# COPY myproject ./myproject
RUN poetry config virtualenvs.in-project true && \
poetry install --only=main --no-root && \
poetry build
FROM base as final
COPY --from=builder /app/.venv ./.venv
COPY --from=builder /app/dist .
COPY docker-entrypoint.sh .
RUN ./.venv/bin/pip install *.whl
CMD ["./docker-entrypoint.sh"]
如果您需要将其用于开发目的,您可以通过替换这一行来添加或删除——no-dev
RUN . /venv/bin/activate && poetry install --no-dev --no-root
就像@sobolevn的回答中显示的那样
RUN . /venv/bin/activate && poetry install --no-root $(test "$YOUR_ENV" == production && echo "--no-dev")
在添加适当的环境变量声明之后。
该示例使用debian-slim的图像作为基础,但是,将其调整为基于阿尔卑斯的图像应该是一项微不足道的任务。
多阶段Docker构建与诗歌和venv
不要禁用virtualenv创建功能。virtualenv在Docker构建中发挥了作用,因为它们提供了一种优雅的方式来利用多阶段构建。简而言之,构建阶段将所有内容安装到virtualenv中,而最后阶段只是将virtualenv复制到一个小映像中。
在复制代码之前,先使用诗歌导出并安装固定的需求。这将允许您使用Docker构建缓存,并且永远不会因为更改代码中的一行而重新安装依赖项。
不要使用诗意安装来安装代码,因为它将执行可编辑的安装。相反,使用诗歌构建来构建一个轮子,然后将其安装到您的virtualenv中。(感谢PEP 517,这整个过程也可以通过简单的pip install .来执行,但由于构建隔离,您最终将安装另一个Poetry副本。)
下面是一个Dockerfile安装Flask应用到Alpine镜像的例子,它依赖于Postgres。本例使用入口点脚本激活virtualenv。但一般来说,没有入口点脚本也没问题,因为您可以在CMD指令中简单地引用/venv/bin/ Python的Python二进制文件。
Dockerfile
FROM python:3.7.6-alpine3.11 as base
ENV PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
PYTHONUNBUFFERED=1
WORKDIR /app
FROM base as builder
ENV PIP_DEFAULT_TIMEOUT=100 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1 \
POETRY_VERSION=1.0.5
RUN apk add --no-cache gcc libffi-dev musl-dev postgresql-dev
RUN pip install "poetry==$POETRY_VERSION"
RUN python -m venv /venv
COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt | /venv/bin/pip install -r /dev/stdin
COPY . .
RUN poetry build && /venv/bin/pip install dist/*.whl
FROM base as final
RUN apk add --no-cache libffi libpq
COPY --from=builder /venv /venv
COPY docker-entrypoint.sh wsgi.py ./
CMD ["./docker-entrypoint.sh"]
docker-entrypoint.sh
#!/bin/sh
set -e
. /venv/bin/activate
while ! flask db upgrade
do
echo "Retry..."
sleep 1
done
exec gunicorn --bind 0.0.0.0:5000 --forwarded-allow-ips='*' wsgi:app
wsgi.py
import your_app
app = your_app.create_app()
在将诗歌与docker一起使用时,有几件事需要记住。
安装
安装诗歌的官方方式是:
curl -sSL https://install.python-poetry.org | python3 -
这种方式允许诗歌及其依赖从你的依赖中分离出来。但是,在我看来,这不是一件很好的事情,有两个原因:
诗歌版本可能会得到更新,它会破坏你的构建。在这种情况下,您可以指定poeetry_version环境变量。安装程序将尊重它 我不喜欢在没有任何保护措施的情况下,将来自互联网的文件传输到我的容器中
所以,我使用pip安装'poetry==$ poeetry_version '。如您所见,我仍然建议固定您的版本。
另外,把这个版本固定在pyproject中。Toml也是:
[build-system]
# Should be the same as `$POETRY_VERSION`:
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
它将保护您避免本地和docker环境之间的版本不匹配。
缓存的依赖关系
我们想要缓存我们的需求,并且只在pyproject时重新安装它们。汤姆或诗歌。锁定文件更改。否则构建会很慢。为了实现工作缓存层,我们应该放:
COPY poetry.lock pyproject.toml /code/
在安装诗词之后,但在添加任何其他文件之前。
Virtualenv
接下来要记住的是virtualenv创建。我们在docker中不需要它。它已经被孤立了。因此,我们使用诗意配置virtualenvs。创建假设置关闭它。
开发vs生产
如果你像我一样使用相同的Dockerfile进行开发和生产,你将需要根据一些环境变量安装不同的依赖集:
poetry install $(test "$YOUR_ENV" == production && echo "--no-dev")
通过这种方式,$YOUR_ENV将控制将安装哪些依赖集:all(默认)或仅生产带有——no-dev标志。
你可能还想添加一些更好的体验选项:
——无互动不要问任何互动问题 ——no-ansi标志,使您的输出更日志友好
结果
你会得到类似的结果:
FROM python:3.6.6-alpine3.7
ARG YOUR_ENV
ENV YOUR_ENV=${YOUR_ENV} \
PYTHONFAULTHANDLER=1 \
PYTHONUNBUFFERED=1 \
PYTHONHASHSEED=random \
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100 \
POETRY_VERSION=1.0.0
# System deps:
RUN pip install "poetry==$POETRY_VERSION"
# Copy only requirements to cache them in docker layer
WORKDIR /code
COPY poetry.lock pyproject.toml /code/
# Project initialization:
RUN poetry config virtualenvs.create false \
&& poetry install $(test "$YOUR_ENV" == production && echo "--no-dev") --no-interaction --no-ansi
# Creating folders, and files for a project:
COPY . /code
你可以在这里找到一个真实的例子:weakake -django-template
2019年12月17日更新
将诗歌更新到1.0
2022-11-24更新
更新curl命令使用现代诗歌安装脚本
这是最适合我的最小配置:
FROM python:3.7
ENV PIP_DISABLE_PIP_VERSION_CHECK=on
RUN pip install poetry
WORKDIR /app
COPY poetry.lock pyproject.toml /app/
RUN poetry config virtualenvs.create false
RUN poetry install --no-interaction
COPY . /app
注意,它不像@sobolevn的配置那样安全。
作为一个小问题,我将补充一下pyproject是否可以进行可编辑安装。Toml项目,可以删除一两行:
FROM python:3.7
ENV PIP_DISABLE_PIP_VERSION_CHECK=on
WORKDIR /app
COPY poetry.lock pyproject.toml /app/
RUN pip install -e .
COPY . /app