タイトルが長いね。

やりたいこと

WSL2上のDockerコンテナでPythonを実行し、matplotlibでグラフや画像を表示したい。
なので、実はVisual Studio Codeは関係ないのですが、同様の構成で困っている人もいるかもと思い、書いておきます。

参考にした記事

主にこちらの記事を参考にしました。
Container + Visual Studio Codeを使ったPython3の開発環境の作り方

できあがりの環境イメージ

  • Windows 10 Home
  • Visual Studio Code
  • Xサーバ
  • WSL2
  • Docker Desktop

環境構築の手順

あちらこちらの記事を参考にしたので、個別の手順の詳細説明はありません。
なお、WSL2、Docker Desktop、Visual Studio Codeのインストールの説明は割愛します。

  1. Remote Containersのインストール
  2. Dockerコンテナを準備する
  3. Python拡張機能をインストールする
  4. Xサーバをインストールする
  5. DISPLAY環境変数を設定する

Remote Containersのインストール

Visual Studio Code(VSCode)に拡張機能であるRemote Containersをインストールします。
ブラウザで下記のサイトにアクセスしてダウンロードします。

https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers

「Install」をクリックするとVSCodeでインストールが始まります。

Dockerコンテナを準備する

Dockerfileを用意します。といっても特別なインストールは不要です。
例えばこんな感じで。

FROM python:3.8.5
RUN pip install --upgrade pip
RUN pip install pylint matplotlib numpy
ENV DISPLAY host.docker.internal:0.0

最後の一行が重要です。説明は後述。
コンテナの起動は後ほどVSCodeから行うので起動しなくて良いですが、起動することの確認はしておきましょう。

Python拡張機能をインストールする

こちらもVSCodeにインストールします。Remote Containerと一緒に入れれば良いのでは?
と思ったあなたは多分正しいです。
すみません。自分が確認した手順で書いてますので・・

インストール方法ですが、Pythonファイルを新規作成して保存します。
例えば「hello.py」という名前で保存すると、拡張子「py」に反応して拡張機能のインストール画面が出ます。

この画面が出たら「Create a Python File」をクリックします。後は画面の指示に従って進めます。

こちらも特に難しいことはないと思います。

Xサーバをインストールする

WSL2(とDockerコンテナ)はグラフや画像を表示できないので、WindowsホストにXサーバを立てて表示できるようにします。
この雑な説明で分かる方は先へ進んでください。

Xサーバについて簡単に説明

UNIX(Linux含む)ではX Windows System(以下X)というグラフィックを表示する仕組みを使います。Xでは画面表示するサーバと画面表示したいクライアントがあり、クライアントがXサーバに表示を依頼します。Xサーバは表示要求を処理する。ごく簡単に説明すると、こんな感じです。
詳しくはWikipediaをどうぞ。

ここでのポイントは画面表示をサーバ・クライアント方式で実現しているということ。別マシンのXサーバを指定すれば、画像表示するアプリが稼働しているマシンと、画面表示するマシンを分離することが出来ます。

Xサーバの導入はWindowsホストに行います。そして画面表示機能を持たないDockerコンテナにはXサーバの場所としてWindowsホストを設定します。これでmatplotlibで作ったグラフを表示することが出来ます。めでたし、めでたし。

Windowsで動作するXサーバはいくつかあるようですが、VcXsrv X Serverがよく使われているようです。
インストール方法は下記が参考になります。
WSL2+Ubuntu 20.04でGUIアプリを動かす

DISPLAY環境変数を設定する

DISPLAY環境変数というのは、Xサーバの場所を指定するものです。
Dockerfileを再掲します。

FROM python:3.8.5
RUN pip install --upgrade pip
RUN pip install pylint matplotlib numpy
ENV DISPLAY host.docker.internal:0.0

設定値について少し説明すると、DISPLAYにはXサーバのホスト名かIPアドレスを指定します。
例えばVMwareなど仮想環境でLinuxデスクトップを使用している場合は、グラフなどの表示クライアントとXサーバが同一マシン上に存在することになります。この場合は loaclhost:0.0 とすればOKです。
末尾の :0.0 の説明は割愛します。

ところがWSL2やその上で稼働するDockerコンテナでは localhost を指定してもうまく表示できません。
そこで localhostの 代わりに host.docker.internal を使用します。host.docker.internal はDockerから見たWindowsホストのIPアドレスが設定されています。なので、これを指定することでWindowsホストに表示できるようになります。
ちょっと回りくどいですが、WSL2の実装の影響だとか。

なお、ここまでの説明にVSCodeが出てきていません。記事の冒頭に書いたとおり、グラフィックの表示問題はVSCodeに関係なく、WSL2(とDocker)を使うと発生する問題ということです。

できあがり

お疲れ様でした。環境構築は以上です。
記事の冒頭に記載した参考ページを見ながら操作してみてください。

簡単なグラフ表示の例を貼っておきます。
ソースはこちらを参考にしました。

実行結果

Windowsの画面上にWindowsアプリとXサーバの表示が同居しています。ソリテアと電卓がWindowsアプリ。グラフと大きな目(xeyes)がXサーバの表示です。