Help us understand the problem. What is going on with this article?

Docker内Pythonで、JupyterやFlaskを使う開発環境の構築(VSCode/code-server両対応)

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 $_

お好みでGitの初期化をしておきます。

$ git init .
$ wget https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore --output-document=.gitignore

パッケージ管理にはPoetryを使います。Poetryでの環境構築用に、Dockerfileとdocker-compose.ymlを記述します。

Dockerfile
FROM python:3.8.3-slim
WORKDIR /app

RUN pip install poetry

コンテナイメージには使いたいPythonのバージョンが含まれたものを指定します。将来的にはイメージ内に色々な依存パッケージのインストールをしたくなる事を見据えつつ、最初はイメージの容量を軽くしておきたいためslimイメージを使います。

docker-compose.yml
version: '3.4'
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 notebook --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

もしコンピュータのローカル環境ではなく公開されたサーバ上で実行するならば、このような設定は避けたほうが良いと思います。

dockerの用意ができたら、Poetryをセットアップします。

$ docker-compose run --rm web poetry init --no-interaction
$ docker-compose run --rm web poetry add jupyter notebook flask

Dockerのビルド時に$ poetry installするように、コマンドを追加します。

Dockerfile
FROM python:3.8.3-slim
WORKDIR /app

RUN pip install poetry
COPY pyproject.toml ./
RUN poetry install

Flaskで立ち上げるためのindex.pyを配置します。

index.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, World!"

ビルドして完成です。

$ docker-compose build

利用方法

$ docker-compose up した後

VSCodeでDocker内のPythonを利用する

まずVSCodeに下記をインストールしておきます。

VSCode上のDocker拡張機能で対象のコンテナを選んで「Attach Visual Studio Code」します。
image.png

※Windowsの場合、Remote - WSL拡張機能でWSL2にRemoteアクセスしているVSCodeではコンテナにアクセスすることができません。Windows上に(Remoteを使っていない)VSCodeのウィンドウを開いて「Attach Visual Studio Code」してください。

コンテナにリモートアクセスするVSCodeウィンドウを開いたら、Python拡張機能(ms-python.python)を「インストール on Container」ボタンでインストールし、VSCodeをReloadします。

VSCodeの>Python: Select Interpreter等で表示されるPythonが、Docker内のもの(今回の例ならば/usr/local/bin/pythonにあるPython 3.8.3)になっていれば成功です。

image.png

VSCode上でJupyterを使う

上記方法でコンテナにアタッチしたVSCodeで、>Python: Specify local or remote Jupyter server for connectionsExistingを選択してhttp://localhost:8888/と入力します。
または、.vscode/settings.jsonというファイルを作成します。

.vscode/settings.json
{
  "python.dataScience.jupyterServerURI": "http://localhost:8888/"
}

VSCodeをReloadし、>Python: Create New Blank Jupyter Notebookすることで、VSCode上でJupyterを使うことができます。

image.png

パスワードを求められた場合は、空文字のままEnterを入力すればOKです。

image.png

code-serverでDocker内のPythonを利用する

VSCodeではなくcode-serverを使うとブラウザで動作するため、特にChromebookの場合LinuxのGUI環境ではなくChrome上で軽快に動作します。Python等の拡張機能もコンテナ内に含められるため、開発環境ごとコード化できるメリットもあります。

デメリットは、イメージの容量が大きくなります。(約1GB追加で必要)

code-serverを利用するには、コンテナにcode-serverと拡張機能を含めてビルドするようにします。

Dockerfile
FROM python:3.8.3-slim AS python
WORKDIR /app

RUN pip install poetry
COPY pyproject.toml ./
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を追加します。

docker-compose.yml
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 connectionshttp://note:8888/のようにjupyterが動いているコンテナを指定します。

.vscode/settings.json
{
  "python.dataScience.jupyterServerURI": "http://note:8888/"
}

参考文献

また、本稿にて作成したコードの全文は下記のリポジトリになります。

https://github.com/s2terminal/python-dev

suzuki_sh
Windowsでコンピュータの世界が広がります
https://www.s2terminal.com
finergy-a-tm
大阪府大阪市北区角田町8番1号 梅田阪急ビル オフィスタワー35F
https://finergy.a-tm.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした