Create Docker Images with Conda and Poetry

Create Docker Images with Conda and Poetry

Poetry is a common tool used for Python packaging and dependency management. Conda is a virtual environment system commonly used in data science. This article goes over how to build Saturn Cloud images with Poetry and Conda. This approach is pretty general, and can be used to build your own docker images even if you’re not a Saturn Cloud user.

The Saturn Cloud image build tool understands conda and pip configuration. If your organization uses poetry, you can build docker images using poetry using your pyproject.toml file. To do so, enter the following into the postBuild section of the image build.

mkdir -p /tmp/poetry

tee -a /tmp/poetry/pyproject.toml > /dev/null <<EOT

[tool.poetry]
name = "my-package"
version = "0.1.0"
description = "The description of the package"
license = "MIT"
authors = [
    "Hugo Shi <hugo@saturncloud.io>",
]
[tool.poetry.dependencies]
# Compatible Python versions
python = ">=3.8"
flask = "2.2.2"

# Dependency groups are supported for organizing your dependencies
[tool.poetry.group.dev.dependencies]
pytest = "^7.1.2"

EOT

export POETRY_HOME=/opt/poetry
export PATH=/opt/poetry/bin:${PATH}
sudo mkdir -p /opt/poetry
sudo chown jovyan:jovyan -R /opt/poetry
curl -sSL https://install.python-poetry.org | python -
mamba install -n saturn python=3.9 pip ipykernel
export PATH=/opt/saturncloud/envs/saturn/bin:${PATH}
poetry config cache-dir /opt/poetry
poetry config virtualenvs.create false
poetry config virtualenvs.prefer-active-python true
export CONDA_PREFIX=/opt/saturncloud/envs/saturn
export CONDA_DEFAULT_ENV=saturn
cd /tmp/poetry && poetry install
/opt/saturncloud/envs/saturn/bin/python -m ipykernel install --name python3 --prefix=/opt/saturncloud

How does this work?

Configuration Files

mkdir -p /tmp/poetry

tee -a /tmp/poetry/pyproject.toml > /dev/null <<EOT

[tool.poetry]
name = "my-package"
version = "0.1.0"
description = "The description of the package"
license = "MIT"
authors = [
    "Hugo Shi <hugo@saturncloud.io>",
]
[tool.poetry.dependencies]
# Compatible Python versions
python = ">=3.8"
flask = "2.2.2"

# Dependency groups are supported for organizing your dependencies
[tool.poetry.group.dev.dependencies]
pytest = "^7.1.2"

EOT

The above snippet dumps your pyproject.toml file into /tmp/poetry. If you are building images outside of Saturn Cloud and would prefer to do this directly in the Dockerfile, you can also do:

COPY pyproject.toml /tmp/poetry/pyproject.toml

Installing Poetry

export POETRY_HOME=/opt/poetry
export PATH=/opt/poetry/bin:${PATH}
sudo mkdir -p /opt/poetry
sudo chown jovyan:jovyan -R /opt/poetry
curl -sSL https://install.python-poetry.org | python -

The above creates a POETRY_HOME directory, and installs poetry into it. The Saturn Cloud image builder does not allow you to set ENV vars in the docker image. To do so, you could add the following to your resource start scripts:

export POETRY_HOME=/opt/poetry
export PATH=/opt/poetry/bin:${PATH}

If you are building docker images outside of Saturn Cloud, you could do:

ENV POETRY_HOME=/opt/poetry
ENV PATH=/opt/poetry/bin:${PATH}

Setting up the conda environment with the ipykernel

mamba install -n saturn python=3.9 pip ipykernel
export PATH=/opt/saturncloud/envs/saturn/bin:${PATH}
export CONDA_PREFIX=/opt/saturncloud/envs/saturn
export CONDA_DEFAULT_ENV=saturn

The above installs python, pip, and ipykernel into a conda env. ipykernel. ipykernel is only necessary to use this env with Jupyter. Poetry tries to detect the currently activated conda env, to figure out which python to use. setting CONDA_PREFIX and CONDA_DEFAULT_ENV helps poetry figure out which Python environment we want.

Instaling packages from pyproject.toml

poetry config cache-dir /opt/poetry
poetry config virtualenvs.create false
poetry config virtualenvs.prefer-active-python true
cd /tmp/poetry && poetry install
/opt/saturncloud/envs/saturn/bin/python -m ipykernel install --name python3 --prefix=/opt/saturncloud

Here we configure poetry so that it does not create a virtual env (since we want to use the existing conda env). The poetry install command should install python packages into the activated conda environment.