F_clef
@F_clef

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Docker on wsl2でpipenvの環境構築をするとpythonのバージョンが指定したものにならない

pipenvをつかったプロジェクトを動かす用のコンテナを作成しようとしています。
以下の流れで実現しようと考えました。

  • イメージ
    • pyenvのインストール
    • pipenvのインストール
  • コンテナ起動時
    • 指定したgitプロジェクトのクローン
    • プロジェクト内のPipfileを解析して仮想環境作成
    • pipenv install

ところがコンテナを実行すると、Pipfileを解析して取得したpythonのバージョンではなく、
システムデフォルトのバージョンの仮想環境が作られてしまいます。
以下に各種ファイルを掲載します。
どこが誤っているかご教示いただけますでしょうか。

Dockerfile

Dockerfile
FROM python:3.8-slim-buster

# 必要なパッケージのインストール
RUN apt-get -y update
RUN apt-get -y upgrade
RUN apt-get install -y git make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev

# pyenvのインストール
RUN git clone https://github.com/yyuu/pyenv.git /.pyenv
ENV PYENV_ROOT /.pyenv
ENV PATH $PYENV_ROOT/bin:$PATH
RUN pyenv init - | bash

# pipenvのインストール
RUN pip install pipenv
ENV PIPENV_VENV_IN_PROJECT 1

# プロジェクト配備用ディレクトリ
RUN mkdir /app
# スクリプト配備用ディレクトリ
RUN mkdir /script 

# コンテナ起動時スクリプト
COPY up.sh /script

WORKDIR /app
EXPOSE 80
RUN chmod +x /script/up.sh
ENTRYPOINT [ "/script/up.sh" ]

コンテナ起動時スクリプト

/script/up.sh
#!/bin/bash

# git情報を環境変数から取得
gitCloneUrl=${GIT_CLONE_URL}
gitUserName=${GIT_USER_NAME}
gitPassword=${GIT_PASSWORD}

# プロジェクトディレクトリ名の解析
gitCloneTarget=`echo ${gitCloneUrl} | sed -r "s#^(https?://)(.*)#\1${gitUserName}:${gitPassword}@\2#g"`
projectName=`echo ${gitCloneUrl} | sed -r "s#.*/(\w+)\.git#\1#g"`
echo "■ ■ ■ PROJECT NAME <${projectName}> ■ ■ ■"

# gitからプロジェクト取得
git clone ${gitCloneTarget}

# プロジェクトのpythonバージョンの解析
cd ${projectName}
pythonVersion=`grep python_version Pipfile | sed -r 's/python_version = "(.+)"/\1/g'`
echo "■ ■ ■ PYTHON VERSION <${pythonVersion}> ■ ■ ■"
yes Y | pipenv --python ${pythonVersion}

curPath=`pwd`
export APP_ROOT=${curPath}

# /app/run.sh : コンテナ起動時に渡すスクリプト。アプリケーション起動コマンドが書いてある。
chmod +x /app/run.sh
/app/run.sh
while true; do sleep 1000; done

起動ログ

3行目に記述がある通り、この時動かしたかったプロジェクトで指定しているpythonのバージョンは3.7なのですが、
7行目にある通り、システムデフォルトの3.8.5で仮想環境が作られます。

■ ■ ■ PROJECT NAME <プロジェクト名> ■ ■ ■
Cloning into 'プロジェクト名'...
■ ■ ■ PYTHON VERSION <3.7> ■ ■ ■
Warning: Python 3.7 was not found on your system…
Creating a virtualenv for this project…
Pipfile: /app/プロジェクト名/Pipfile
Using default python from /usr/local/bin/python (3.8.5) to create virtualenv…
⠧ Creating virtual environment...created virtual environment CPython3.8.5.final.0-64 in 484ms
   creator CPython3Posix(dest=/app/プロジェクト名/.venv, clear=False, global=False)
   seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/root/.local/share/virtualenv)
     added seed packages: pip==20.2.2, setuptools==49.6.0, wheel==0.35.1
   activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

✔ Successfully created virtual environment! 

コンテナのbashを起動してコマンドを入力して仮想環境を作ろうとすると、
指定したバージョンのpythonをインストールするか尋ねられて、期待するバージョンの仮想環境が作られます。

コマンドの手入力
# pipenv --python 3.7
Warning: Python 3.7 was not found on your system…
Would you like us to install CPython 3.7.9 with Pyenv? [Y/n]: Y
Installing CPython 3.7.9 with /.pyenv/bin/pyenv (this may take a few minutes)…

他にも必要なファイルがあったらご指示ください。
よろしくお願いいたします。

0

1Answer

pyenvやpipenvは初めて使うのと、コンテナで使ったことがないのでズレているかもしれません。

pipenvがpythonのインストールをしない条件に該当しているのが原因のようです。インストール時にでてくるはずの「Would you like us...」が出てこないのでこれで検索して探しました。

以下のどちらかを満たさない場合はインストールが行われません

  • pipenvはインタラクティブモードか(sys.stdin.isatty()がTrueを返すか) code
    • これのせいでpythonからは標準入力をそもそも読み取らない処理に分岐されてしまっているようです(yesコマンドの意味がない)
  • 環境変数 PIPENV_YES が True に相当する値が設定されているか code

このいずれかを満たすには、以下のいずれかを行えばいいはずです。今回は後者がよいかとおもいます。

  • docuer run -it イメージ名 で起動する
  • pipenv実行前に ENV PIPENV_YES 1 を Dockerfileに書いておく
1Like

Comments

  1. @F_clef

    Questioner

    まさにこれでした。

    以下対応で解決できました。
    ありがとうございました!

    > pipenv実行前に ENV PIPENV_YES 1 を Dockerfileに書いておく

Your answer might help someone💌