Python
docker
Pipenv

DockerコンテナをPipenvでセットアップする

この記事の概要

  • Dockerコンテナにインストールするpython packageをpipenvで管理する手順を説明します。
  • 概要:
    1. DockerfileでホストOSからコンテナにPipfile, Pipfile.lockCOPY.
    2. pipenv install --systemオプションでdockerコンテナに直にインストール。
    3. Dockerコンテナ内がPipenvで設定される。

動機

  • ほとんどのケースでPipfileによる管理だけで十分なんだけど、極たまにDockerを使った環境を使う必要がある。
  • その時、Dokcerの中の環境を(ホストOSにある)Pipfileで管理したい。

みたいなニーズがありました。

手順

Pipenvによる環境構築

  • とりあえず、python 3.5でnumpyを使うプロジェクトだったと仮定します。
  • まず、Pipenvで環境を構築します。
$ mkdir pipenv_docker  # 適当なディレクトリ
$ cd pipenv_docker
$ pipenv install --python 3.5
$ pipenv install numpy
$ pipenv shell
  • 今回はプロジェクトの内容は関係ないのですが、numpyのバージョンを出力するtest.pyファイルを用意しておきます。
$ echo 'import numpy; print(numpy.__version__)' > test.py
$ python test.py 
1.14.5
  • この時点でカレントディレクトリの中身はこうです。
  • pipenvによる環境構築が出来ました。
$ ls
Pipfile      Pipfile.lock test.py

Dockerによる環境構築

  • まず、Ubuntu上でpython 3.5が動作してpipenvが動かせる環境を作ります。
    • pipenvによるセットアップはこの後やります。
    • Dockerfileの内容は色々適当ですのでご注意ください。
    • FROM ubuntu:16.04で構築しますが、他のディストリビューションでも(aptを除いて)そう大きく変わらない手順になると思います。
Dockerfile
FROM ubuntu:16.04

# ubuntu:16.04には設定されてないので設定しておく
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8

# 適当なディレクトリ作って移動
RUN mkdir /var/app
WORKDIR /var/app

# python, curl install
RUN apt update && apt install -y python3.5 curl

# pip install: https://pip.pypa.io/en/stable/installing/
RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
RUN python3.5 get-pip.py

# pipenv install
RUN pip install pipenv

# 先程のtest.pyもコピーしておきます
COPY test.py ./

この時点で一回起動してみましょう。

$ docker build . -t pipenv_docker
$ docker run -it pipenv_docker  # コンテナ起動, 以下、コンテナのshell

root@8fe8f243a0b9:/var/app# pipenv --version
pipenv, version 2018.7.1

はい、pipenvのインストールまで出来ました。
さらにDockerfileに追記していきます。

Dockerfile追記
# Pipfile: host -> container
COPY Pipfile ./
COPY Pipfile.lock ./

# Pipfileからインストール. ただしpipenvの仮想環境は作らずにcontainerに直接入れる
RUN pipenv install --system
  • ホストOSからPipfileとPipfile.lockをCOPYしてpipenv installを行っています。
  • この時、container内に更に仮想環境を作る必要は無いので--sysytemを付けてcontainerに直接インストールしています。

出来たので動かしてみます。

$ docker build . -t pipenv_docker
$ docker run -it pipenv_docker  # コンテナ起動, 以下、コンテナのshell

root@4f51d99fc8ff:/var/app# python3.5 test.py
1.14.5

Pipfile内で指定されているnumpyが読み込めています。
pipenvでdocker container内の環境が構築できました。

補足: Pipfile.lockを参照させない場合

先程の手順で、Pipfile.lockCOPYせずにPipfileだけCOPYした場合、エラーになります。

Dockerfile追記
# Pipfile: host -> container
COPY Pipfile ./
# COPY Pipfile.lock ./  # コメントアウト

# Pipfileからインストール. ただしpipenvの仮想環境は作らずにcontainerに直接入れる
RUN pipenv install --system

エラー

...
Warning: --system is intended to be used for Pipfile installation, not installation of specific packages. Aborting.
See also: --deploy flag.
The command '/bin/sh -c pipenv install --system' returned a non-zero code: 1

Pipfile.lockを無視してPipfileからインストールしたい場合は、pipenv install --sysytem--skip-lockオプションを加えれば行けます。