Pythonを少し使ってみようと思ったのですが、環境構築するために色々インストールするのは嫌でした。なのでDockerを使って環境を構築してみました。
インタラクティブな環境およびWebの両方を利用できて、VSCode(またはcode-server)で開発できる環境を目指します。特にVSCodeのPython拡張機能からDocker内Pythonで動作するJupyterへの接続にはハマる所がありましたので、環境構築手順を本稿にメモとして残します。
要件
- CLIでPythonプログラムが実行できる
- Jupyterを利用して、インタラクティブにPythonが実行できる
- Flaskを利用して、WebでPythonのアウトプットができる
- Visual Studio Codeまたはcode-serverで、Pythonのランタイムを利用したコード補完等ができる
上記が全部できる開発環境を構築します。実際に本記事を利用するときは、必要な箇所をかいつまんで利用してください。
環境
下記の環境で動作確認済
- Windows 10 WSL 2 Ubuntu 16.04.5 + docker 18.09.6 + docker desktop 2.3.0.3
- ChromeOS Crostini (Linux) Debian 9.11 + docker 19.03.4
環境構築手順
まず適当な作業用ディレクトリを切ります。
$ mkdir python-dev && cd $_
または、$ poetry new
を使っても良いと思います。
$ docker run --interactive --tty --rm --volume $(pwd):/app --workdir /app python:3.9.5-slim sh
# pip install poetry
# poetry new --src python-dev
$ cd python-dev
お好みでGitの初期化をしておきます。
$ git init .
$ wget https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore --output-document=.gitignore
パッケージ管理にはPoetryを使います。Poetryでの環境構築用に、Dockerfileとdocker-compose.ymlを記述します。
FROM python:3.9.5-slim
WORKDIR /app
# VS Code Remote Containerを使う場合はGitをコンテナ内にインストールすることを推奨
RUN apt-get update && apt-get install -y \
git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN pip install poetry
コンテナイメージには使いたいPythonのバージョンが含まれたものを指定します。将来的にはイメージ内に色々な依存パッケージのインストールをしたくなる事を見据えつつ、最初はイメージの容量を軽くしておきたいためslimイメージを使います。
version: '3.9'
services:
web:
build: .
volumes:
- .:/app
environment:
- FLASK_APP=index.py
ports:
- 127.0.0.1:5000:5000
command: "poetry run flask run --host=0.0.0.0"
note:
build: .
volumes:
- .:/app
ports:
- 127.0.0.1:8888:8888
command: "poetry run jupyter lab --no-browser --ip=0.0.0.0 --port=8888 --allow-root --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.disable_check_xsrf=True"
今回はコンテナ内のJupyterにホストからアクセスする都合上、Jupyterのセキュリティ機能を無効化するためにいくつかの設定を入れています。
--NotebookApp.token=''
--NotebookApp.password=''
--NotebookApp.disable_check_xsrf=True
もしコンピュータのローカル環境ではなく公開されたサーバ上で実行するならば、このような設定は避けたほうが良いと思います。
WebサーバやNotebookは使わないという場合も、VS Codeで開発するならコンテナが立ち上がりっぱなしになっていた方が便利です。以下のようなdocker-compose.yml
で、起動しっぱなしにできます。
version: '3'
services:
app:
build: .
volumes:
- .:/app
command: /bin/sh -c "echo 'docker dev ready'; while sleep 1000; do :; done"
dockerの用意ができたら、Poetryをセットアップします。
$ docker-compose run --rm web poetry init --no-interaction
$ docker-compose run --rm web poetry add jupyterlab flask
Dockerのビルド時に$ poetry install
するように、コマンドを追加します。
FROM python:3.9.5-slim
WORKDIR /app
RUN pip install poetry
COPY pyproject.toml ./
RUN poetry config virtualenvs.in-project true
RUN poetry install
Flaskで立ち上げるためのindex.pyを配置します。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, World!"
ビルドして完成です。
$ docker-compose build
利用方法
$ docker-compose up
した後
- CLIで使う
$ docker-compose run --rm web python --version
- Webで使う
- http://127.0.0.1:5000 にアクセスします。
- Jupyterで使う
- http://127.0.0.1:8888 にアクセスします。
VSCodeでDocker内のPythonを利用する
まずVSCodeに下記をインストールしておきます。
- Remote Development拡張機能(ms-vscode-remote.vscode-remote-extensionpack)
- Docker
拡張機能(ms-azuretools.vscode-docker)
VSCode上のDocker拡張機能で対象のコンテナを選んで「Attach Visual Studio Code」します。
※Windowsの場合、Remote - WSL拡張機能でWSL2にRemoteアクセスしているVSCodeではコンテナにアクセスすることができません。Windows上に(Remoteを使っていない)VSCodeのウィンドウを開いて「Attach Visual Studio Code」してください。
コンテナにリモートアクセスするVSCodeウィンドウを開いたら、Python拡張機能(ms-python.python)を「インストール on Container」ボタンでインストールし、VSCodeをReloadします。
または.vscode/extensions.json
にこのように記述すれば、環境を問わずVS Codeでこのリポジトリを開くと拡張機能のインストールを勧めてくるようになります。
{
"recommendations": [
"ms-python.vscode-pylance",
"ms-python.python"
]
}
VSCodeの>Python: Select Interpreter
等で表示されるPythonが、Docker内のもの(今回の例ならば/usr/local/bin/python
にあるPython 3.9.5)になっていれば成功です。
VSCode上でJupyterを使う
上記方法でコンテナにアタッチしたVSCodeで、>Python: Specify local or remote Jupyter server for connections
でExisting
を選択してhttp://localhost:8888/
と入力します。
または、.vscode/settings.json
というファイルを作成します。
{
"python.dataScience.jupyterServerURI": "http://localhost:8888/"
}
VSCodeをReloadし、>Python: Create New Blank Jupyter Notebook
することで、VSCode上でJupyterを使うことができます。
パスワードを求められた場合は、空文字のままEnterを入力すればOKです。
Pylance拡張機能で静的型チェックをする
VS CodeのPylance拡張機能を使うと、静的型チェックができます。
インストールしたらお好みで設定します。個人的にはstrict modeで有効化し、pyrightconfig.json
で各種設定を緩和して使うことが多いです。
{
"python.analysis.typeCheckingMode": "strict"
}
{
"reportMissingTypeStubs": "information",
"reportUnknownParameterType": "information",
"reportUnknownMemberType": "information",
"reportUnknownArgumentType": "information"
}
下記のような型エラーが表示されるようになれば成功です。
code-serverでDocker内のPythonを利用する
VSCodeではなくcode-serverを使うとブラウザで動作するため、特にChromebookの場合LinuxのGUI環境ではなくChrome上で軽快に動作します。Python等の拡張機能もコンテナ内に含められるため、開発環境ごとコード化できるメリットもあります。
デメリットは、イメージの容量が大きくなります。(約1GB追加で必要)
code-serverを利用するには、コンテナにcode-serverと拡張機能を含めてビルドするようにします。
FROM python:3.9.5-slim AS python
WORKDIR /app
RUN pip install poetry
COPY pyproject.toml ./
RUN poetry config virtualenvs.create false --local
RUN poetry install
FROM python AS code-server
RUN apt-get update && apt-get install -y curl
RUN curl -fsSL https://code-server.dev/install.sh | sh
RUN code-server \
--install-extension ms-python.python \
--install-extension ms-ceintl.vscode-language-pack-ja
docker-composeにも、code-serverを起動するserviceを追加します。
version: '3.4'
services:
web:
build:
context: .
target: python
volumes:
- .:/app
environment:
- FLASK_APP=index.py
ports:
- 127.0.0.1:5000:5000
command: "poetry run flask run --host=0.0.0.0"
note:
build:
context: .
target: python
volumes:
- .:/app
ports:
- 127.0.0.1:8888:8888
command: "poetry run jupyter notebook --no-browser --ip=0.0.0.0 --port=8888 --allow-root --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.disable_check_xsrf=True"
code:
build:
context: .
target: code-server
ports:
- 127.0.0.1:8080:8080
volumes:
- ./:/app
entrypoint: "code-server --auth none --bind-addr=0.0.0.0:8080 /app"
これで$ docker-compose build
すれば完成です。(少し時間がかかります)
http://127.0.0.1:8080 にアクセスすると、ブラウザ上でVSCodeが利用できます。
code-serverでJupyterを使うには、>Python: Specify local or remote Jupyter server for connections
でhttp://note:8888/
のようにjupyterが動いているコンテナを指定します。
{
"python.dataScience.jupyterServerURI": "http://note:8888/"
}
参考文献
- Unable to connect to an authless remote jupyter server · Issue #7137 · microsoft/vscode-python
- Installing extensions from command line · Issue #171 · cdr/code-server
また、本稿にて作成したコードの全文は下記のリポジトリになります。