Visual Studio Code の Remote - Containers を使用して Python の開発環境を作る

背景

後で別のエントリに書くと思いますが、あるところで働くことになりました(非正規雇用ですが)。 そこのお仕事で Python を触ることになったのですが、Python の開発環境の構築に困りました。

  • Python での仮想環境はあまり馴染めなさそう
  • ローカル環境を汚したくない

そこで、Docker コンテナに全部収めることにしました。恥ずかしながら、最近まで Visual Studio Code の Remote Development でコンテナに接続できるのを知りませんでした(Remote - WSL と Remote - SSH は使ってるのにね……)。

使用環境

項目
OS Windows 10 Pro 21H1
Docker Docker Desktop for Windows 3.5.1
Visual Studio Code 1.47.0-insider
Remote - Containers 0.128.0

開発環境構築

各種インストール

Docker、VSCode、Remote - Containers(Remote Development で良い)をインストールしておきます。

プロジェクトフォルダの作成

適当な場所にプロジェクトフォルダを作成します。今回は ~/myproj とし、プロジェクトで使用するファイルは ~/myproj/app に保存することにします。

cd
mkdir -p myproj/app && cd myproj

開発用コンテナの作成

今回は既存のプロダクトを動かすため、Python のバージョンは低めにしています。また、パッケージ管理ツールとして Poetry を使用します。 下記の Dockerfile を用意します。

FROM python:3.6

ENV POETRY_HOME=/opt/poetry
RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
RUN cd /usr/local/bin && ln -s /opt/poetry/bin/poetry
RUN poetry config virtualenvs.create false

#COPY ./app/pyproject.toml ./app/poetry.lock* /app/
#WORKDIR /app/
#RUN poetry install --no-root

プロジェクトごとにコンテナを分ける想定なので仮想環境は使用しません。 また、開発環境を別マシンに移す際や、配布する際は末尾3行をアンコメントして使用します。

Dockerfile を作成したらビルド、実行します。

docker build -t myproj .
docker run -dt --name myproj -v $PWD/app:/app myproj 

開発

VSCode を起動し、コンテナにアタッチする

プロジェクトフォルダを VSCode で開きます。自分は Remote - WSL で接続しています。

code-insiders .

VSCodeRemote Explorer から Containers を開き、起動したコンテナのフォルダマークをクリックしてアタッチします。

f:id:tuki9ko:20210714130330p:plain

すると新しいウィンドウでコンテナにアタッチした VSCode が立ち上がります。 フォルダーを開く からマウントしたフォルダ(今回は/app) を開きます。

拡張機能の管理はコンテナごとになるため、必要な拡張機能をインストールしておきます。

プロジェクトの初期化

統合ターミナルを開くとコンテナ内のシェルが使えます。 poetry init でプロジェクトを初期化します。今回はプロジェクト名を myproj とし、そのほかは全てデフォルトとしました。

root@f0bca2a7b8ea:/app# poetry init

This command will guide you through creating your pyproject.toml config.

Package name [app]:  myproj
Version [0.1.0]:  
Description []:  
Author [tuki9ko <arkmisha@gmail.com>, n to skip]:  
License []:  
Compatible Python versions [^3.6]:  

Would you like to define your main dependencies interactively? (yes/no) [yes] 
You can specify a package in the following forms:
  - A single name (requests)
  - A name and a constraint (requests@^2.23.0)
  - A git url (git+https://github.com/python-poetry/poetry.git)
  - A git url with a revision (git+https://github.com/python-poetry/poetry.git#develop)
  - A file path (../my-package/my-package.whl)
  - A directory (../my-package/)
  - A url (https://example.com/packages/my-package-0.1.0.tar.gz)

Search for package to add (or leave blank to continue): 

Would you like to define your development dependencies interactively? (yes/no) [yes] 
Search for package to add (or leave blank to continue): 

Generated file

[tool.poetry]
name = "myproj"
version = "0.1.0"
description = ""
authors = ["tuki9ko <arkmisha@gmail.com>"]

[tool.poetry.dependencies]
python = "^3.6"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"


Do you confirm generation? (yes/no) [yes] 
root@f0bca2a7b8ea:/app# 

パッケージのインストール

今回は試しに numpy を使用してみようと思います。 Poetry で numpy をインストールしますが、そのまま入れると Python のバージョンが低いと怒られるため、1.13.0 を指定してインストールします。

poetry add "numpy==1.13.0"

コードの実行

適当なコードを書いて実行します。 今回は配列を作成して表示するだけのコード(myapp.py)を書きます。

import numpy as np

a = np.array([1, 2, 3])

print(a, a.shape, a.ndim)

統合ターミナルから実行します。

python myapp.py
[1 2 3] (3,) 1

いい感じに実行できました。

今後の運用

同マシンで開発する際はコンテナを起動してVSCodeでアタッチするだけで大丈夫です。 別マシンに移す場合や、開発環境を他人に配布する場合は Dockerfile の末尾3行をアンコメントして一式を渡し、イメージのビルド、コンテナの起動、VSCodeでアタッチすればOKです。

課題

  • プロジェクトを最初から作る場合と、後から参加する場合で Dockerfile の内容が別になってしまっているので、統合できればと思います。
  • パッケージをインストールする際に、OS側で必要なライブラリがあった際に Dockerfile の修正が必要(apt update -y && apt install -y some-package)です。
    • PyAudioportaudio が必要なため、Dockerfile にインストールコマンドを追記しています。
      • apt update -y && apt install -y portaudio19-dev