DEV Community

loading...

Dockerfile with fine-tuned Python and native dependencies

Pacharapol Withayasakpunt
Currently interested in TypeScript, Vue, Kotlin and Python. Looking forward to learning DevOps, though.
・2 min read

It's not only about installing Python3 in Docker and use it.

RUN apt install python3
Enter fullscreen mode Exit fullscreen mode

But it is also about getting Python version right (e.g. pyenv, akin to rbenv, nvm, gvm), along with native dependencies (yes, usually C++ or C).

People may forget that Python sometimes needs native libraries, which is not really Python; and OS-dependent, e.g. OpenCV, ffmpeg and MeCab. That's why I use Docker - for reproducibility into the remote server.

It is also the answer of this question; but I don't quite know the answer yet...

Note: I have just started trying to learn docker, so I'm a beginner

Currently, I'm using poetry and pyenv to make my python project. I'm using pyenv for my python version, and poetry for creating and managing my python projects. But, I want to also use docker So, how can…

My Dockerfile

FROM debian:buster-slim

RUN apt-get update
RUN apt-get install -y --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

ENV HOME="/root"
WORKDIR ${HOME}
RUN apt-get install -y git
RUN git clone --depth=1 https://github.com/pyenv/pyenv.git .pyenv
ENV PYENV_ROOT="${HOME}/.pyenv"
ENV PATH="${PYENV_ROOT}/shims:${PYENV_ROOT}/bin:${PATH}"

ENV PYTHON_VERSION=3.8.6
RUN pyenv install ${PYTHON_VERSION}
RUN pyenv global ${PYTHON_VERSION}

RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -

WORKDIR /app

RUN apt-get install -y mecab-ipadic-utf8
RUN touch /usr/local/etc/mecabrc

COPY poetry.lock pyproject.toml ./
RUN /bin/bash -c 'source $HOME/.poetry/env && POETRY_VIRTUALENVS_IN_PROJECT=true poetry install --no-dev --no-root'

COPY . .

ENTRYPOINT [ "/bin/bash", "-c", "source .venv/bin/activate && uvicorn server:app --host=0.0.0.0" ]
Enter fullscreen mode Exit fullscreen mode

What I really wanted to do

  1. How do I source ., exec $SHELL or modify .profile / .bash_profile in Dockerfile?

Actually, so far, I have found people telling to use virtualenvwrapper.sh, but no, I don't get it...

SHELL ["/bin/bash", "-c", "source /usr/local/bin/virtualenvwrapper.sh"]
Enter fullscreen mode Exit fullscreen mode

Actually, I did find two ways to manage it.

  • source . && cmd before every lines - this works perfectly.
  • Create a dummy shell wrapper wrapper.sh. This seems to superficially work, but it doesn't.
#!/bin/bash

${1}
${@:2}
Enter fullscreen mode Exit fullscreen mode
  1. How do I create ENTRYPOINT that source?

I temporarily made it with the below, but this feels so unbeautiful...

ENTRYPOINT [ "/bin/bash", "-c", "source .venv/bin/activate && uvicorn server:app --host=0.0.0.0" ]
Enter fullscreen mode Exit fullscreen mode

Discussion (2)

Collapse
copypasteengineer profile image
CopyPasteEngineer

Not sure what your use case is. Generally, I'll use python as the base image instead of a bare debian. So you can ensure that, when calling python command, it always reaches to the right one. Hence, no need to use pyenv and calling source every time.

Just replace

FROM debian...
Enter fullscreen mode Exit fullscreen mode

with

FROM python:3.8
Enter fullscreen mode Exit fullscreen mode

and remove all the scripts relating to installing python and pyenv.
That should do.

Other dependencies should be able to be installed by apt and pip command.

note: You could find more variation of python base images here:

Collapse
patarapolw profile image
Pacharapol Withayasakpunt Author • Edited

Thanks. I forgot about that.

The only real use case is, to be able to choose Operating System to install native deps. I am pretty sure about Ubuntu and half sure about Debian. I barely trust Alpine.