Docker+VSCodeを用いたPythonの開発環境構築

作成: 2020年11月19日

更新: 2021年06月04日

概要

Docker+VSCode(Remote Containers)を用いたPythonの環境構築方法をまとめる.自分用の備忘録.

↓GithubでTemplate Repository にしました.以下のPython環境を自分のリポジトリのfirst commitにできます.
bana118/python-container-template: Template of vscode remote development container with Python

↓Python以外の言語についても同様のTemplate Repositoryを作りました
Python, Node.js, Go, Rust, LaTeXの開発環境をDocker+VSCodeで構築した

利点

Pythonは環境構築が難しいがDockerを使えばコマンド1つで環境が再現できる.
また上手くいかなくなっても最悪環境ごと破棄し作り直せる.
formatterやlinterを同時に導入することできれいなコードが半強制的に作られる.

Dockerのインストール(Windows)

WSL2とDockerの導入

Dockerのインストール(Mac)

Install Docker Desktop on Mac | Docker Documentation

VSCodeのインストール

以下のリンクからインストール
Download Visual Studio Code - Mac, Linux, Windows

開発方法

参考: 【venv不要】Remote Containersで作る最強のPython開発環境【VSCode/Docker】 - Qiita

各種設定ファイルの設定

以下のようにディレクトリ,ファイルを作成します.${project}は実際のディレクトリ名が入ります.

${project}
    ├── .github
    │   └── workflows
    │       └── lint.yml
    ├── .devcontainer
    │   ├── Dockerfile
    │   └── devcontainer.json
    ├── .vscode
    │   └── extensions.json
    ├── requirements.txt
    └── src
        ├── tests
        │         └── test_example.py
        ├── main.py
        .
        .

また各ファイルは以下のように設定します.

.devcontainer/DockerfileFROM python:3.9.1-slim

RUN apt update \
    && apt install -y --no-install-recommends \
    apt-utils \
    git \
    gcc \
    build-essential \
    && pip install --no-cache-dir \
    autopep8 \
    flake8 \
    pytest \
    && apt autoremove -y \
    && apt clean -y \
    && rm -rf /var/lib/apt/lists/*

"python:3.9.1-slim"のところは使いたいバージョンを設定してください.ここでプロジェクトに直接関わらないライブラリ群のlinterとしてflake8, formatterとしてautopep8をテスト用にpytestをインストールしています.

.devcontainer/devcontainer.json{
    "name": "project-name",
    "dockerFile": "Dockerfile",
    "settings": {
        "terminal.integrated.shell.linux": "/bin/bash",
        "python.pythonPath": "/usr/local/bin/python",
        "python.linting.pylintEnabled": false,
        "python.linting.flake8Enabled": true,
        "python.linting.flake8Args": [
            "--ignore=E402",
            "--max-line-length",
            "120"
        ],
        "python.formatting.provider": "autopep8",
        "python.formatting.autopep8Args": [
            "--ignore",
            "E402",
            "--max-line-length",
            "120"
        ],
        "[python]": {
            "editor.formatOnSave": true
        }
    },
    "extensions": [
        "ms-python.python",
        "ms-python.vscode-pylance"
    ],
    "postCreateCommand": "pip install -r requirements.txt",
}

"name": "project-name",のproject-nameにはgithubのリポジトリ名を入れます.
ここでlinterとしてflake8, formatterとしてautopep8を指定し,オプションで1行あたりの推奨文字数79文字から120文字に変更しています.
--ignoreオプションで402を無視しています.これは以下のようなimportを許容します.
参考: Python スクリプトの親ディレクトリをパスに追加する - Qiita

import sys, os
pardir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pardir)
import main

他にもいくつか規約を無視できるが要検証
(参考: pycodestyle(pep8) エラーコードチートシート - Qiita)
またextensionsにはVSCodeのpython用拡張と静的型解析を可能にするpylanceの拡張が入っています.これによりDocker起動時に自動でこれらの拡張がインストールされます.
またpostCreateCommandによりrequirements.txtに記述されているパッケージが自動でインストールされます.

.vscode/extensions.json{
    "recommendations": [
        "ms-vscode-remote.remote-containers",
        "ms-python.python",
        "ms-python.vscode-pylance"
    ]
}

ここではVSCode起動時にrecommendationsとして表示させるextensionsを指定しています.remote-containers拡張はVSCodeでDockerを起動する拡張です.VSCodeの左隅が緑色になりそこをクリックすることでDockerのコンテナ作成,リビルドなどができます.

ipykernel
numpy
pandas
matplotlib

必要なパッケージを記述します.実際はバージョンを固定するのを推奨します.ipykernelがあると以下のように# %%を書くことでflake8, autopep8の恩恵を受けながらjupyterのようにインタラクティブにコードを実行できます.

src/example.py# %%
print("Hello, world")
.github/workflows/python.ymlname: Python

on:
  push:
    branches:
      - main
      - develop
  pull_request:
    branches:
      - main
      - develop

jobs:
  flake8:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v2
    - name: Setup Python
      uses: actions/setup-python@v2
      with:
        python-version: 3.9.1
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install flake8 pytest
        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
    - name: Run flake8
      run: |
        flake8 src --count --max-line-length=120 --statistic

参考: GitHub ActionsでのPythonの利用 - GitHub ヘルプ
プルリクエスト,push時にflake8によるコードチェックとpytestによるテストを行う.python-versionは用いるバージョンによって変更.
またflake8では命名規則をチェックしないので注意.Pythonのコーディング規約PEP8での命名規則は以下.

対象 規則 備考
パッケージ snake_case アンダースコアなしを推奨
モジュール snake_case アンダースコアなしを推奨
クラス PascalCase
例外 PascalCase
クラス変数 PascalCase
メソッド snake_case 内部メソッドは頭にアンダースコア
引数 snake_case 予約語と被るときは末尾にアンダースコア
変数 snake_case 内部変数は頭にアンダースコア
定数 SNAKE_CASE
src/tests/test_example.py# Example test is required because pytest has Exit Code 5 when no tests running
def test_example():
    assert True

pytestはテストケースが1つもないと正常に終了しないでエラーを返すので1つは必ずテストケースを用意する.

Docker起動

設定ファイルの記述が終わったらVSCodeを該当のディレクトリにて起動します.するとrecommendとしてremote-containers拡張が出るはずなのでインストールします.すると画面の右隅が緑色になるのでクリックします.
出てくるコマンドのリストから「Remote-Containers: Open Folder in Container...」を選びます.
フォルダ選択画面がでたら、プロジェクトのディレクトリを選ぶ.
コンテナが作成されるのでしばらく待ちます.
コンテナが作成し終わったらCtrl+Shift+@でターミナルを開くと以下のようにbashになってディレクトリがworkspacesになったらOK.
Pythonが入っているか確かめます.

> Python -V
# Python 3.9.1