1

I'm trying to dockerize a simple script (a command line utility). Here is a working Dockerfile:

FROM python:3.9-slim

ARG user=tweaker project=tex-tweak src=tex_tweak

# Non-root user.
RUN useradd -ms /bin/bash "$user"
USER $user
WORKDIR /home/$user
ENV PATH=/home/$user/.local/bin:$PATH

# Source and project files.
RUN mkdir /home/$user/$project
WORKDIR /home/$user/$project
COPY $src ./$src/
COPY pyproject.toml ./
#COPY poetry.lock ./

# Build.
RUN pip install poetry --user && \
    poetry config virtualenvs.create false && \
    poetry install --no-dev && \
    poetry build

CMD ["bash"]

Curiously, this is enough: the target utility somehow gets installed into .local/bin; I can't see why.

python:slim image is 115MB; the resulting image is 174MB. Not unacceptable, but relatively bloated. Multistage build is in order, u suppose. Unfortunately, I can't see how I should move the essentials into the second stage. The idea of selective copying of the .local/bin and .local/lib does not look particularly safe or inviting. Or maybe this is the way?

Or is it possible/advisable to pip install <target>.whl into the second stage?

Alexey Orlov
  • 2,412
  • 3
  • 27
  • 46
  • you can install into a virtual environment and then copy that virtual environment into the second build stage. – jkr Dec 21 '21 at 22:37

1 Answers1

6

Here is an example build that you can reference for multi-stage with Poetry:

https://stackoverflow.com/a/64642121/14305096

FROM python:3.9-slim as base

ENV PYTHONFAULTHANDLER=1 \
    PYTHONHASHSEED=random \
    PYTHONUNBUFFERED=1

RUN apt-get update && apt-get install -y gcc libffi-dev g++
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.1.3

RUN pip install "poetry==$POETRY_VERSION"
RUN python -m venv /venv

COPY pyproject.toml poetry.lock ./
RUN . /venv/bin/activate && poetry install --no-dev --no-root

COPY . .
RUN . /venv/bin/activate && poetry build

FROM base as final

COPY --from=builder /venv /venv
COPY --from=builder /app/dist .
COPY docker-entrypoint.sh ./

RUN . /venv/bin/activate && pip install *.whl
CMD ["./docker-entrypoint.sh"]
Zaffer
  • 1,290
  • 13
  • 32
  • stupid question: why did you pip install poetry? why did you not use RUN apt-get update && apt-get install curl -y && curl -sSL https://install.python-poetry.org | python - --version 1.1.13 to install poetry? what is the difference – PirateApp Aug 01 '22 at 12:09
  • 1
    @PirateApp that is preference. Pip is simpler and as a rule of thumb avoiding curl installs is nice. There were also some changes to the poetry install URL between version 1 and 1.1. So pip is easier, but both options are technically fine. – Zaffer Aug 01 '22 at 20:22