IntelliJ + Docker + Pythonの環境構築

# はじめに
Macbookを買い換えたのでPythonの開発環境を作り直すことになるのですが、ローカルに直接Pythonをインストールすると、ついうっかりglobalにパッケージをインストールしてしまったり、venvを使っていても環境を作り直したいときに一手間が面倒だったり、ということが嫌だったのでDockerを使って構築することにしました。


# IntelliJにPluginインストール
IntelliJにDocker Pluginが入っていない場合は `Preferences > Plugins`からインストールします。

<img width="1126" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/94541c73-1208-1dc5-2546-a6abaf21cc35.png">

# Pythonプロジェクトの作成
次にIntelliJを立ち上げてPythonプロジェクトを作成します。
Dockerの必要なイメージはこの後作るので、ここではとりあえず適当なProject SDKを選んでおきます。（ここではPython2.7(venv)になっています）
それ以外はデフォルトのままで良くて、プロジェクトを作成します。

<img width="1324" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/8d78202b-b4e5-323f-085f-b22a61c3fe4b.png">

# IntelliJ上でDockerfileを作成してイメージをビルドする

今回はPythonQiitaというプロジェクト名にしました。最初にPython環境をDockerイメージにしておく必要があるので、プロジェクトフォルダの直下に`Dockerfile`を作成します。（場所はどこでも良い）

<img width="657" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/5f4bd347-31b8-e222-c5bd-581ce95d38ad.png">

Dockerfileにはベースとなるイメージファイル、初期設定コマンドなどを書いておきます。
今回は`python:3`イメージを使います。パッケージに`pandas` `numpy`を入れておきます。

<img width="667" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/3a5e8c3e-a72a-4a02-df37-800ce6e5c412.png">

作成したDockerfileを右クリックして、メニューから`Create Dockerfile`を選択します。

<img width="523" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/d8dc2710-f680-6bb4-7a87-c2752a6b22d3.png">

Configurationウィンドウが表示されるので`Image tag`を入力します。このタグ名は後で使います。ここでは`python_qiita`としました。
`Run built image`のチェックは外しておきます。これをオンにしておくと、イメージをビルドした後、コンテナとして起動してくれます。`Container name`を入力すると、そのコンテナ名で起動するようになっています。

<img width="694" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/dcab840b-0efc-a86e-4661-e6bd4c114c5f.png">

下記の<img width="14" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/b8190960-f1fc-c627-b22b-2920ac4fb851.png">から作成したDockerfile設定を起動すればイメージがビルドされます。Deploy Logに`'python_qiita Dockerfile: Dockerfile' has been deployed successfully.`と出て完了したことが分かります。

<img width="508" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/9e47a589-2199-ee6b-671f-755c9a68cf66.png">

イメージが作成されるとServicesビューにイメージ名が表示され、ビルドが成功したことが分かります。

<img width="446" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/e671ef1a-533a-eded-d978-25ccacf38c27.png">


# ビルドしたイメージをProject SDKとして設定する

Dockerイメージがビルドできると、プロジェクトで利用するSDKとして利用できるようになります。コンテナはSDKにはならないので注意が必要です。

`FIle > Project Structure`を開き、Project項目にある`New`ボタンを押し、ポップアップにある`Python SDK`を選択します。
<img width="1022" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/9c621556-7b85-8e2b-411a-92d405c87dc3.png">

Python Interpreterを選択するウィンドウが表示されるので、左メニューにある`Docker`を選びます。すると、Image nameに先ほどビルドしたDockerイメージのタグ名が選択できるようになっていることを確認してOKボタンを押します。

<img width="961" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/52e27004-8a9c-d2bb-83ab-1967deeb94c6.png">


Project StructureのSDKs項目に`Remote Python 3.7.4 Docker...`が表示されており、packagesにDockerfileに書いたパッケージがインストールされていることが分かります。venvなどの環境では、ここでパッケージの追加・削除ができますが、DockerイメージのPythonだと追加・削除はできません。パッケージの構成が変わるたびにイメージをビルドしなおす必要があります。

<img width="1136" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/32900c18-72bc-3845-e96c-d192e4f9653c.png">

# Pythonの実行とデバッグ
ここまでくれば後は通常通りPythonファイルを作成して実行するだけですが、、、
設定を完了した直後だと、IntelliJがPythonの構成を適切に読み込めていないらしく、一度プロジェクトを閉じて開きなおす必要があります。さらに、画面下に下記のような更新中のインジケータが完了するまで待たないといけません。ここだけが難点です。仕組みはわかりませんが、改善されることに期待したいですね。

<img width="815" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/f6d62133-ad81-b1ea-8b92-cd2eb14badb8.png">

ここまで出来ればPythonのコード補完や実行、デバッグがIntelliJ上でできるようになっています。下記はpandasをインポートして実行した状態。
<img width="570" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/27ab4835-083d-e69d-f07c-791bcf7179a6.png">


# 不便なこと

環境はDockerで構築できるのでポータブルになるし、気軽に作り直せることは実行環境面で非常に便利に感じます。一方で、いくつか不便に思うことがあるので書いておきます。

### Dockerイメージをビルドしなおすと構成読み込みに時間がかかる
上述のSDKを設定した直後と同様に、イメージをビルドし直してPythonパッケージの構成を変えたとしても、すぐに反映されません。プロジェクトを再起動するなどして、IntelliJが再認識するのを待つ必要があります（数分）。
構成見直しが不要になってくると気になりませんが、プロジェクトの初期フェーズでは煩わしいです。

### matplotlibなどの`show()`的なことができない
当たり前ですが、Docker上で実行するので`show()`のようなウィンドウを立ち上げることができません。諦めてファイルに保存して確認するしかないです。


# まとめ
紹介したような不便なところもありますが、環境も汚れないしポータブルであることは便利だと感じています。今までだと、パッケージの再構築が面倒だったり、requirements.txtのようなものに書きださなければならなかった環境が、Dockerfileにまとまるし、必要ならイメージをレポジトリで保存しておく事もできるのは良い感じだなと。
venvとどちらが楽か、と聞かれるとvenvだと思いますが、新しい環境で色々とやってみる方が今の自分の好みに合っているので、暫くはDockerで進めてみようと思います。