🐍

SingularityでPyenv&Poetry環境構築

2023/03/17に公開

SingularityでPoetryが使いたい

これまでSingualrity上のPythonパッケージ管理はpipで行っていました.
最近,以下の記事をきっかけにPoetryの存在を知り,調べていくうちに虜になりました.
Python環境構築[Pyenv+Poetry]|研究のためのPython開発環境

今後,開発したプログラムの公開も見据え,環境の再現性を担保するためにもPoetryを導入したいと思います.

また副次的な産物として,Singularityでpipを使う場合,新しいパッケージの追加はdefファイルを再記述してbuildし直す必要がありましたが,Poetryではイメージ内から新たなパッケージの追加が可能です.もちろん,pyproject.tomlに追加したパッケージは自動で記録されるので,後の環境再現も問題ありません.

Definition File

先程の記事に従い,Singularityイメージを作成するDefinition Fileを以下の通り記述しました.

pyenvpoetry.def
Bootstrap: docker
From: nvidia/cuda:11.3.1-cudnn8-devel-ubuntu20.04

%environment
	export TZ=Asia/Tokyo
	export CUDA_PATH=/usr/local/cuda
	export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH

	export PYENV_ROOT="/opt/pyenv"
	export PATH="$PYENV_ROOT/bin:$PATH"

	export POETRY_HOME=/opt/poetry
    export PATH=$POETRY_HOME/bin:$PATH
    
    # PyenvのPythonを利用
    export PATH=$PYENV_ROOT/shims:$PATH

%post
    perl -p -i.bak -e 's%(deb(?:-src|)\s+)https?://(?!archive\.canonical\.com|security\.ubuntu\.com)[^\s]+%$1http://ftp.riken.jp/Linux/ubuntu/%' /etc/apt/sources.list

	export DEBIAN_FRONTEND=noninteractive
	export TZ=Asia/Tokyo

	export PYENV_ROOT="/opt/pyenv"
	export PATH="$PYENV_ROOT/bin:$PATH"
	export PYTHON_VERSION=3.11
	export POETRY_ROOT="/opt/poetry"

	apt-get -y update
	apt-get -y dist-upgrade
    apt-get -y install \
		build-essential \
        curl \
        git \
        libbz2-dev \
        libffi-dev \
        libreadline-dev \
        libsqlite3-dev \
        libssl-dev \
        liblzma-dev \
        llvm \
        make \
        tk-dev \
        wget \
        xz-utils \
        zlib1g-dev

	# Install pyenv
    git clone https://github.com/pyenv/pyenv.git $PYENV_ROOT

	
	eval "$(pyenv init --path)"

	pyenv install $PYTHON_VERSION
	pyenv local $PYTHON_VERSION

	# Install poetry
	curl -sSL https://install.python-poetry.org | POETRY_HOME=$POETRY_ROOT python -

%labels
    Author msn
    Version v1.0.1

今後,GPUの活用(PyTorchの導入)を視野に入れているため,ベースにDockerで配布されているcudaイメージを使用していますが,シンプルなUbuntu環境でも問題ないと思います.

注意点として,Build時に%postセクションのカレントディレクトリは/rootとなり,各インストール先に影響します.
そこで,今回は/opt以下に明示的にインストールしています.また,インストール先へのパス開通を%environmentセクションで行い,shell実行時に反映されるようにしています.

検証

以下のコマンドでBuildしました.
私の環境では,--fakeroot権限のみが許可されているため,以下のようなコマンドでBuildしています.

build
singularity build --fakeroot pyenvpoetry.sif pyenvpoetry.def

Build完了後にコンテナ内に入り,パスの開通と,Python, Poetryの動作確認を行いました.

イメージ化した後でもパッケージの追加インストールが可能なことを確認しました.

Pyenvによる追加のバージョンインストールは,Pyenvのインストール先である/opt/pyenvが一般ユーザで書き込み不能なため,失敗しました.
複数のPythonバージョンを使用する場合は,予めdefファイルによるインストールが必要だと考えられます.

check
which pyenv
# /opt/pyenv/bin/pyenv

which poetry
# /opt/poetry/bin/poetry

### poetryの動作チェック ###
poetry init
# (出力省略)すべてreturnを押して進める

poetry shell
which python
# /{USERHOME}/.cache/pypoetry/virtualenvs/hoge-h8c379Fr-py3.11/bin/python

# ndjsonがインストールされていないことを確認
python
# Python 3.11.2 (main, Mar 16 2023, 16:36:22) [GCC 9.4.0] on linux
# Type "help", "copyright", "credits" or "license" for more information.
>>> import ndjson
## Traceback (most recent call last):
##   File "<stdin>", line 1, in <module>
## ModuleNotFoundError: No module named 'ndjson'
>>> exit()

# ndjsonをインストールして追加を確認
poetry add ndjson
## Using version ^0.3.1 for ndjson
## 
## Updating dependencies
## Resolving dependencies... (0.1s)
## 
## Writing lock file
## 
## Package operations: 1 install, 0 updates, 0 removals
## 
##   • Installing ndjson (0.3.1)

python
# Python 3.11.2 (main, Mar 16 2023, 16:36:22) [GCC 9.4.0] on linux
# Type "help", "copyright", "credits" or "license" for more information.
>>> import ndjson
# Errorが出ず成功

exit  # poetry shellからの退出

cd ../
mkdir foo
cd foo

### pyenvの追加バージョンインストール -> 失敗 ###
pyenv install 3.9
# perl: warning: Setting locale failed.
# perl: warning: Please check that your locale settings:
#         LANGUAGE = (unset),
#         LC_ALL = (unset),
#         LC_TERMINAL = "iTerm2",
#         LANG = "en_US.UTF-8"
#     are supported and installed on your system.
# perl: warning: Falling back to the standard locale ("C").
# Downloading Python-3.9.16.tar.xz...
# -> https://www.python.org/ftp/python/3.9.16/Python-3.9.16.tar.xz
# Installing Python-3.9.16...
# 
# BUILD FAILED (Ubuntu 20.04 using python-build 2.3.15-1-g4ef81b5c)
# 
# Inspect or clean up the working tree at /tmp/python-build.20230317101532.1581633
# Results logged to /tmp/python-build.20230317101532.1581633.log
# 
# Last 10 log lines:
# changing mode of build/scripts-3.9/idle3 from 644 to 755
# changing mode of build/scripts-3.9/2to3 from 644 to 755
# renaming build/scripts-3.9/pydoc3 to build/scripts-3.9/pydoc3.9
# renaming build/scripts-3.9/idle3 to build/scripts-3.9/idle3.9
# renaming build/scripts-3.9/2to3 to build/scripts-3.9/2to3-3.9
# Creating directory /opt/pyenv/versions/3.9.16/bin
# /usr/bin/install: cannot create directory '/opt/pyenv/versions/3.9.16': Read-only file system
# Creating directory /opt/pyenv/versions/3.9.16/lib
# /usr/bin/install: cannot create directory '/opt/pyenv/versions/3.9.16': Read-only file system
# make: *** [Makefile:1313: altbininstall] Error 1

むすび

SingularityでPyenvとPoetryによるPython環境構築を行いました.
Poetryによって環境再現性が高く,Singularityの利点の一つである再現性をより高めることができます.
また従来のpipではイメージ化してからパッケージの追加が不可能でした.一方,PoetryのaddコマンドはBuild後でも追加ができることから,パッケージ追加のためにdefファイルの修正・再Buildが不要だとわかり,開発の効率化が期待されます.
ただし,Pyenvによって複数のPythonバージョンをBuild後にインストールすることはできませんでした.予めdefファイルで必要なバージョンをインストールしておくか,Pyenvのインストール先を一般ユーザが書込み可能な領域を選択する(Singularityでは不可能?)必要があり,さらなる検証が必要です.

今後は今回の環境にPyTorchの導入を試みます.

GitHubで編集を提案

Discussion