前回までのあらすじ
前回記事はこちらになります。
> Windows上のWSLでコンテナによる開発環境を作ってみる(前準備編)
- Pythonの開発環境をコンテナ上に作成してみたくなった
- そのためにWindows上にDockerを入れたい
- そのためにはWSL2のセットアップが必要だったのでそこからやってみた
ということで前回はWSL2のセットアップとDocker for Desktopが動くところまで行きました。これによりWindows上にPythonを導入する際のインストール形態として、仮想環境という観点で3つの方針がありうることになります。
WindowsへのPythonインストール形態の3パターン
- Windows上にWindows用のPythonをインストールする。実環境へのインストール。
- Windows上のWSL上にLinux用のPythonをインストールする。WSL環境へのインストール。
- Windows上のWSL上で動いているDockerコンテナ内にLinux用のPythonをインストールする。コンテナ環境へのインストール
それぞれ長所短所があると思います。特にGPUなど使って機械学習をゴリゴリ回したい場合は1.になるでしょう。1
Linux環境の方が好きだけどコンテナ運用までは考えてないなら2.になるでしょう。前回説明したファイルの相互参照も手軽に使えます。また、このパターンでも VSCode を WSL に接続して使うことが可能です。
今回やろうとしているのは3.のコンテナ活用パターンです。コンテナを使うメリットについては前回書きましたので割愛します。
Windows上でのPython開発環境にはどんなものがあるか
Pythonを始めようとすると世の中に様々な開発環境があり入り乱れているので何を使ったら良いのかわからなくなります。実はWSLにUbuntuディストリビューションを入れた場合その時点ですでに Python 3.8.10 が入っているようです。
$ python3 -VV
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0]
簡単な開発ならこれでも十分かもしれませんが実際の開発業務でコマンドラインとエディタだけで開発するというようなことはあまりないと思われ、何らかの開発ツールを導入することになると思います。Pythonの開発ツールにはどんな選択肢があるのか、ざっと調べてみました。
名称 | 説明 | URL |
---|---|---|
Anaconda | 科学計算向きのパッケージとして配付されているPython用開発ディストリビューション。機械学習やデータ分析でよく使うライブラリがまとめて入っている。 | https://www.anaconda.com/products/individual |
Spyder | Anaconda をインストールすると一緒に入ってくるIDE。 | https://docs.spyder-ide.org/current/index.html |
PyCharm | JetBrain社が提供するIDE。Spyderより使いやすいという評判あり。機能制限された無料版と有料版がある。 | https://www.jetbrains.com/ja-jp/pycharm/ |
Jupyter Notebook(JupyterLab) | Anacondaと同様、機械学習や統計処理に向いた開発環境。Webブラウザ上から使うインターフェイスが特徴。JupyterLab はJupyter Notebookの後継にあたるもの。 | https://jupyter.org/, https://github.com/jupyterlab/jupyterlab |
Google Colab | 環境構築が不要で、Googleアカウントでサインインするとブラウザ上から使えるWebサービスの一種。機械学習用にGPUも用意されている。無料版と有料版がある。違いは使えるリソースの量や性能だが、無料版でも十分使える。 | http://colab.research.google.com/ |
Visual Studio Code (VSCode) | Microsoftが無料で提供しているエディタであり拡張機能により軽量型の開発環境にもなる。JavaScript の開発でよく名前を見かけるものでかなり人気がある。 | https://azure.microsoft.com/ja-jp/products/visual-studio-code/ |
venv | これは統合開発環境というようなものではなく、Python 内部の機能として仮想環境を作れる機能。コンテナとは若干趣を異にするが目的は似ている。 | https://docs.python.org/ja/3/library/venv.html |
pyenv | 開発環境ではなく一つのマシンに複数のバージョンのpythonをインストールしてそれを切り替えて使えるようにするツール。 | https://github.com/pyenv/pyenv |
Eclipse | 昔からあるIDE。もともと重くて使いづらい上にコンテナ環境での使い方についてあまり情報がなく(Linux版なら可能らしい)、現状のままなら今後主流になっていくであろうコンテナを利用した開発に向かないため、Java開発環境としてもレガシーとなっていく可能性がある。 | https://mergedoc.osdn.jp/ |
Anacondaは開発用途が科学計算やデータサイエンス分野である場合に向いているそうです。一方Web、デスクトップ、組み込み、ゲーム、モバイル等のアプリ開発をする場合は組み込まれているモジュールなどの関係で普通のPythonを使う方が使いやすいとのこと。WSL上のDockerコンテナで Spyderを使うにはX11かWSLgなどを使わないといけないようです。
Jupyter Notebook はその仕組み上コンテナ環境でも使いやすそうなので何らかの理由で VSCode を採用しない場合の有力な選択肢となると思いますが、ブラウザ上で動くという制約上どうしてもVSCodeよりも自由度が落ち軽快さで劣ると思われます。
Google Colab は性能も悪くないようですが、Webサービスなので常時接続環境があることが前提となります。
PyCharm は利用者の評判もよく Dockerを使った開発にも対応しているようです。普及率がそれほどでもないようなので今回はこれ以上調べませんが、時間があれば調べてみたいところです。
WSL + Docker + Python という組み合わせで検索すると出てくる情報としては VSCodeを使うものが圧倒的に多く、WSL + Docker という環境ではこれが今の所主流の開発ツールということになりそうです2。今回は VSCode を使った開発について調べてみます。
Python開発環境のコンテナを用意するための前提知識
- 今回はDockerに関する用語や概念については最低限の説明にとどめます。入門サイトはたくさんあるので読んでいただければと思います。3
- DockerコンテナはDockerイメージから作成します。DockerイメージとはDockerコンテナを作るための静的なイメージで、環境のスナップショットでありテンプレートのようなものです。内部的な構造としてレイヤーを持っているらしいですが、とりあえず最初はそこはあまり気にしなくてもよさそうです。
- 最近はPythonに限らず、Docker Hub4上に開発環境のDockerイメージが開発元から公式に提供されていることが多いようです。Pythonの公式なDockerイメージも開発元から提供されています。
- docker pull コマンドにより、docker hub上のイメージをダウンロード可能です。
$ docker pull <名前空間>/<イメージ名>:<タグ名>
- イメージには名前空間を付けることが可能です。指定しない場合はDocker公式イメージ用の名前空間であるlibraryが検索されます。
- タグというのは取得したいイメージのバージョンを表すのに使う検索キーのようなものです。省略すると latest (最新断面)になります。
- 実際に docker pull で pythonのバージョン3用イメージの最新版を取得してみます。
$ docker pull python:3
3: Pulling from library/python
0c6b8ff8c37e: Pull complete
412caad352a3: Pull complete
e6d3e61f7a50: Pull complete
461bb1d8c517: Pull complete
808edda3c2e8: Pull complete
724cfd2dc19b: Pull complete
8bd4965a24ab: Pull complete
fccd5fa208a8: Pull complete
c7160e53cd12: Pull complete
Digest: sha256:d4641de8caa679bdb32ff6f50e664d36959a67d0b494b355f6f174bccdb5f639
Status: Downloaded newer image for python:3
docker.io/library/python:3
Digest というのがこのイメージを特定するためのハッシュ値です。
Dockerイメージの確認
- ダウンロードしたイメージの確認は docker images コマンドでできます。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
python 3 de529ffbdb66 18 hours ago 886MB
- さらに詳しくイメージの情報を出したければ docker inspect コマンドを使います。
$ docker inspect python:3
[
{
"Id": "sha256:de529ffbdb6623fd5d26e3fde1ac721153657dbe9966fd48075163bfeebb37d2",
"RepoTags": [
"python:3"
],
"RepoDigests": [
"python@sha256:d4641de8caa679bdb32ff6f50e664d36959a67d0b494b355f6f174bccdb5f639"
],
"Parent": "",
"Comment": "",
"Created": "2022-02-04T23:20:30.292106032Z",
"Container": "94b7c5b886bb3171e2b06fe7edb5eff41d6fe3c66bdfdb3738f850f42c2074c2",
"ContainerConfig": {
"Hostname": "94b7c5b886bb",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG=C.UTF-8",
"GPG_KEY=A035C8C19219BA821ECEA86B64E628F8D684696D",
"PYTHON_VERSION=3.10.2",
"PYTHON_PIP_VERSION=21.2.4",
"PYTHON_SETUPTOOLS_VERSION=58.1.0",
"PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/2caf84b14febcda8077e59e9b8a6ef9a680aa392/public/get-pip.py",
"PYTHON_GET_PIP_SHA256=7c5239cea323cadae36083079a5ee6b2b3d56f25762a0c060d2867b89e5e06c5"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"python3\"]"
],
"Image": "sha256:a359f492eb7a7dba11cbce1b5e81f77ff95a5768822bd9949bef4a16c9f03e7f",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "20.10.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG=C.UTF-8",
"GPG_KEY=A035C8C19219BA821ECEA86B64E628F8D684696D",
"PYTHON_VERSION=3.10.2",
"PYTHON_PIP_VERSION=21.2.4",
"PYTHON_SETUPTOOLS_VERSION=58.1.0",
"PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/2caf84b14febcda8077e59e9b8a6ef9a680aa392/public/get-pip.py",
"PYTHON_GET_PIP_SHA256=7c5239cea323cadae36083079a5ee6b2b3d56f25762a0c060d2867b89e5e06c5"
],
"Cmd": [
"python3"
],
"Image": "sha256:a359f492eb7a7dba11cbce1b5e81f77ff95a5768822bd9949bef4a16c9f03e7f",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 885523149,
"VirtualSize": 885523149,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/888b1d71de32b660aa3c7a9360038f9511d4ee1418e5f7e2622015ed316fa372/diff:/var/lib/docker/overlay2/44262362c23ee27612e94090b94bdf2e4feabce7aacb21c1d93ccb22d8b300b0/diff:/var/lib/docker/overlay2/b0df7b2fbab239b50bb0d331c5531337fff1739c7398b2434d4ced8341ddf896/diff:/var/lib/docker/overlay2/3bd03441d03de94a52b9b3538c1af58faf8b64d3ca340d9a67e0358da62c2366/diff:/var/lib/docker/overlay2/9f8d36b5e796f499f3813e24aa7aa492d7b18a8460b7180701ba0b55ba14d8e0/diff:/var/lib/docker/overlay2/35b949d69f4cdf242262616fe12dd5f6dd142fae7d4adb2146108fdbf5ce8d29/diff:/var/lib/docker/overlay2/033890bb3efa672ffeca3a313c21a0f4f1f0dc8b3f8e05c57c2dee0365c93e28/diff:/var/lib/docker/overlay2/2c02ccb8da1c55ee4e4f1fb67fa71b9eaf07930a7f33d93088cfb1fdd71ce0e5/diff",
"MergedDir": "/var/lib/docker/overlay2/32117ba550b5cbd8561c8e8202b257c8af631049c2f6a2bc092f25de71445554/merged",
"UpperDir": "/var/lib/docker/overlay2/32117ba550b5cbd8561c8e8202b257c8af631049c2f6a2bc092f25de71445554/diff",
"WorkDir": "/var/lib/docker/overlay2/32117ba550b5cbd8561c8e8202b257c8af631049c2f6a2bc092f25de71445554/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:0b0f2f2f52795d31dd1107e7ac81adca6aa51769f6ec4e23f745e373ae588995",
"sha256:6398d5cccd2cc2c5989fc2021b9519eb5270bc8e09148b83818d0c1e10c69b98",
"sha256:bed676ceab7ad31ef6668df4b1d025e32744ca8ea6b7618d25cf318863f21fe8",
"sha256:613ab28cf833881e95b4ee02829114c33e9cd98ae2f10a8e46a48e6d88d410e2",
"sha256:204e42b3d47b54f6ee2af1083c0234402afe87eee894949bbb98cf0bb35c6ef7",
"sha256:a3232401de62e32369f9185f10e47f65bbd7ba3ffb27347139e7aae90a3c4d72",
"sha256:2a671b56bca21694aa3ec32de523236c67f436676a2bf8a3e62ead950f655af6",
"sha256:3018490964f804579010465966407950d4c111de257234af9f61aa337c493845",
"sha256:718062cc061ccd766d8a7f87b779e30b06d3f6772486f3a10e6a98278360c104"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
残念ながら今は詳細までは調べません。とりあえずこんなことができるということだけ押さえておきます。
Docker コンテナを起動してみる
- docker run コマンドでコンテナを起動してみます。オプションの -it は対話モードでの動作を指定、--rm はコマンドが終わったらコンテナを自動的に削除するという意味です。
$ docker run -it --rm python:3
Python 3.10.2 (main, Jan 29 2022, 02:41:17) [GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print("Hello")
Hello
>>> import sys
>>> print(sys.version)
3.10.2 (main, Jan 29 2022, 02:41:17) [GCC 10.2.1 20210110]
↑ Pythonが対話モードで起動しているので "Hello" と出力してみた後、バージョンを表示させてみました。コンテナのホストであるUbuntu上のPython のバージョンは3.8.10でしたが、コンテナ内のPythonは3.10.2で、こちらの方が少し新しいようです。
なぜコンテナ起動と同時に対話モードでPythonが起動するかというと、さきほどの inspect の出力で CMD セクションに下記のような記述があったためであるようです。
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"python3\"]"
],
コンテナを特に指定なしで起動した場合に、このコマンドが実行されるようになっているようです。このとき、Docker for Desktop の画面を見るとコンテナが起動しているのがわかります。
- Pythonを終了させると、rmオプションを指定していたのでコンテナも自動削除されます。
$ docker run -it --rm python:3
Python 3.10.2 (main, Jan 29 2022, 02:41:17) [GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print("Hello")
Hello
>>> import sys
>>> print(sys.version)
3.10.2 (main, Jan 29 2022, 02:41:17) [GCC 10.2.1 20210110]
>>> quit()
$
コンテナ起動時にbashを起動してみたら?
- ではコンテナ起動時にいきなりpythonを起動するのではなく、bash を起動させればプロンプトが出るのか?という疑問がわくと思います。やってみると、こうなります。
$ docker run -it --rm python:3 bash
root@333970f0f928:/# pwd
/
root@333970f0f928:/# ls -la
total 72
drwxr-xr-x 1 root root 4096 Feb 5 18:21 .
drwxr-xr-x 1 root root 4096 Feb 5 18:21 ..
-rwxr-xr-x 1 root root 0 Feb 5 18:21 .dockerenv
drwxr-xr-x 1 root root 4096 Jan 26 02:12 bin
drwxr-xr-x 2 root root 4096 Dec 11 17:25 boot
drwxr-xr-x 5 root root 360 Feb 5 18:21 dev
drwxr-xr-x 1 root root 4096 Feb 5 18:21 etc
drwxr-xr-x 2 root root 4096 Dec 11 17:25 home
drwxr-xr-x 1 root root 4096 Jan 26 02:13 lib
drwxr-xr-x 2 root root 4096 Jan 25 00:00 lib64
drwxr-xr-x 2 root root 4096 Jan 25 00:00 media
drwxr-xr-x 2 root root 4096 Jan 25 00:00 mnt
drwxr-xr-x 2 root root 4096 Jan 25 00:00 opt
dr-xr-xr-x 235 root root 0 Feb 5 18:21 proc
drwx------ 1 root root 4096 Jan 29 02:37 root
drwxr-xr-x 3 root root 4096 Jan 25 00:00 run
drwxr-xr-x 1 root root 4096 Jan 26 02:12 sbin
drwxr-xr-x 2 root root 4096 Jan 25 00:00 srv
dr-xr-xr-x 11 root root 0 Feb 5 18:21 sys
drwxrwxrwt 1 root root 4096 Feb 4 23:20 tmp
drwxr-xr-x 1 root root 4096 Jan 25 00:00 usr
drwxr-xr-x 1 root root 4096 Jan 25 00:00 var
root@333970f0f928:/# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
root@333970f0f928:/#
予想通りコマンドプロンプトが出ました。OSの情報を確認するとDebian GNU/Linux 11 (bullseye)と出てくるのが興味深いです。WSL上ではUbuntuが動いていますが、コンテナ内ではDebianが走っているわけです。プロンプトに表示されている 333970f0f928 というのはコンテナのIDです。
C:\Users\smatsu>docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
333970f0f928 python:3 "bash" 10 minutes ago Up 10 minutes boring_goldstine
なお、これもexitするとコンテナが自動的に消えます。
以上でなんとなくコンテナを起動して動かせたので、VSCodeの導入へ進みたいと思います。
Visual Studio Code をDocker で使うための準備
- Docker コンテナにVSCodeをつないで、あたかもコンテナ内で動いているかのように開発が可能となります。そのためにいくつか準備が必要です。VSCodeは既にWindows上にインストールしてある前提で進めます。具体的には、以下の3つの準備をします。
- 拡張機能 VSCode Remote Container をインストールする
- Docker拡張機能をインストールする
- Python開発用拡張機能をインストールする
拡張機能 VSCode Remote Container をインストールする
- VSCode の拡張機能 VSCode Remote Container をインストールします。これはDockerのコンテナ内にあるファイルをVSCodeで開き、開発することを可能にする拡張機能です。
インストールボタン押下だけで簡単にインストールできます。
Docker拡張機能をインストールする
- ついでに Docker 拡張機能も入れておきます。これはDockerの操作をVSCodeからできるようにする拡張機能です。タブからコンテナ一覧を見たり、起動・削除ができるようになるそうです。ただし最初のうちはdockerでコマンド叩いた方が勉強になるかもしれません。
Python開発用拡張機能をインストールする
開発環境イメージを作るためのDockerfileなどを用意する
- VSCode からアクセスするためのコンテナを起動する場合、Dockerfile と docker-compose.yml を用意し、そこを基点にして接続するのが普通のようです。
- DockerfileとはDockerイメージを構築するコマンドをテキストに書いておき、バッチファイルのように実行する機能です。DockerでのIaC(Infrastructure as Code)5を実現する機能とも言えます。Dockerfileを使うことでコードベースでインフラ環境を定義することが可能となります。
- docker-compose.yml とは、docker-composeと呼ばれるツールの設定ファイルです。docker-composeはローカル環境でDockerのオーケストレーションを行うためのツールです。オーケストレーションとは、複数のコンテナから成るサービスを構築・実行する手順を自動的に行うことを言います。(と言っても、今回はコンテナは開発用に1つしか使いません)
- docker-compose.yml と Dockerfile の役割分担を簡単に言うと、docker-compose.ymlがコンテナの起動操作をするための情報で、Dockerfile がイメージを構築するための情報になります。Dockerfileとdocker-compose.yml の内容について詳細に説明していくと大変なので、今回は割愛させていただきます。こちらのページ6を参考にWSL上のUbuntuのホームディレクトリ(/home/smatsu)にファイルを作成します。
optディレクトリはコンテナから共有するためのフォルダです。ここに適当なPythonのソースを入れておきます。後でためしに実行してみるためです。今回は参考にしたページにしたがい、sample.py を入れておきます。
import math
import sys
def main():
val = float(sys.argv[1])
print(math.radians(val))
if __name__ == "__main__":
main()
- Dockerfileの内容です。
FROM python:3
USER root
RUN apt-get update
RUN apt-get -y install locales && \
localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm
RUN apt-get install -y vim less
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
FROM のステートメントでpython:3のイメージをベースにすることを指定し、USER で実行ユーザが root であることを指定しています。あとは普通のlinuxコマンドと環境変数なのでなのでなんとなく想像がつくと思います。
- docker-compose.yml の内容です。
version: '3'
services:
python3:
restart: always
build: .
container_name: 'python3'
working_dir: '/root/'
tty: true
volumes:
- ./opt:/root/opt
今回docker-compose.ymlについての詳細は割愛していますが内容を簡単に説明すると、python3というコンテナを用意し、Dockerfileはカレントディレクトリにあるものを参照し、/root を作業ディレクトリとし、対話モードを有効にし、ホストOSの ./opt ディレクトリをコンテナ上の /root/opt ディレクトリにマウントする、という内容になっています。
これで準備完了です。これまでに作ったdockerイメージとコンテナは紛らわしいので Docker for Desktop 上で消しておきます。
docker-compose を起動する
- WSL上で先ほど作ったdocker-pythonフォルダへ移動しdocker-composeを起動、イメージとコンテナを作成、起動します。
$ cd docker-python/
$ docker compose up -d --build
・・・
(いろいろ出力されますが長いので割愛)
・・・
[+] Running 1/1
⠿ Container python3 Started 0.9s
$
オプションの -d はデタッチドモード(バックグラウンド実行)、--build はコンテナ起動前にDockerfileを参照してイメージをビルドすることを指定しています。
成功すればイメージとコンテナが追加されます。
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-python_python3 latest c025108e0cb3 4 minutes ago 990MB
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
29030d48f75a docker-python_python3 "python3" 4 minutes ago Up 4 minutes python3
python3というのはdocker-compose.ymlの中で指定したコンテナの名前で、この名前でコンテナが出来ているのがわかります。
シェルからコンテナに接続してみる
- docker-compose で起動したコンテナにシェルから接続してみます。
$ docker compose exec python3 bash
root@29030d48f75a:~# ls -la
合計 40
drwx------ 1 root root 4096 2月 6 17:56 .
drwxr-xr-x 1 root root 4096 2月 6 17:38 ..
-rw------- 1 root root 27 2月 6 17:56 .bash_history
-rw-r--r-- 1 root root 571 4月 11 2021 .bashrc
drwxr-xr-x 1 root root 4096 2月 6 17:38 .cache
-rw-r--r-- 1 root root 161 7月 9 2019 .profile
-rw------- 1 root root 0 1月 29 11:37 .python_history
-rw------- 1 root root 820 2月 6 17:47 .viminfo
-rw-r--r-- 1 root root 254 2月 5 08:20 .wget-hsts
drwxr-xr-x 2 1000 1000 4096 1月 16 20:55 opt
root@29030d48f75a:~# python -VV
Python 3.10.2 (main, Jan 29 2022, 02:41:17) [GCC 10.2.1 20210110]
root@29030d48f75a:~#
ここで先ほどのように"docker run -it docker-python_python3 bash"としても似たような動作になりますが、既存のコンテナではない新しいコンテナが起動します。"docker exec -it python3 bash" ならば上のdocker compose execコマンドと同様に既存のコンテナに接続します。なお Docker for Desktop からCLIアイコンをクリックしても同様の動きになります。
- いったんコンテナを終了します。
$ docker compose down
[+] Running 2/2
⠿ Container python3 Removed 10.7s
⠿ Network docker-python_default Removed
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
コンテナがなくなっているのがわかります。
VSCodeでコンテナを起動
- Dockerfile と docker-compose.yml に問題ないことが確認できたのでVSCodeからの接続をしてみます。
- WSL内で "code ." と打つとVSCodeが起動します。先ほど作ったdocker-pythonフォルダで起動してみます。
$ code .
Updating VS Code Server to version 5554b12acf27056905806867f251c859323ff7e9
Removing previous installation...
Installing VS Code Server for x64 (5554b12acf27056905806867f251c859323ff7e9)
Downloading: 100%
Unpacking: 100%
Unpacked 2158 files and folders to /home/smatsu/.vscode-server/bin/5554b12acf27056905806867f251c859323ff7e9.
しかしこれではWSL上のファイルを参照して起動しているだけであって、コンテナに接続しているわけではありません。docker-compose.ymlを右クリックして、Compose Up を選択してみます。
するとターミナルが起動し、docker-compose up が走ってコンテナが起動します。
Docker for Desktop の画面にもコンテナが表示されています。
コンテナにリモート接続
ここでVSCodeの左下の緑色の部分をクリックすると、リモート接続メニューが(なぜか上の方に)出て来ます。
↓ ここでReopen in Container を選択します。
↓ 次に From 'docker-compose.yml' を選択します。
この後、VSCodeが再起動したりいろいろ不思議な動きをするのですが、いろいろ試して7どうにかコンテナが開けました。
サンプルソースを実行する
↑ するとプログラムが走ったようですが、5行目で例外が発生してしまいました。起動時の引数が足りないためインデックスエラーが発生したようです。実行メニューから「デバッグの停止」を選んでいったん終了します。(右上にあるバーの □ アイコンをクリックでも終了できます)
launch.jsonを作成する
↑ 「実行とデバッグをカスタマイズするには、launch.json ファイルを作成します。」と表示されています。これをクリックするとlaunch.json が生成されました。調べてみると、ここに args というプロパティを追加すると、引数として渡されるようです。
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"args": ["180"]
}
]
}
↓ .vscode というフォルダが作られ、そこにlaunch.jsonファイルが格納されています。
再度実行してみる。
↑ ターミナルに 3.141592653589793 という値が表示され、sample.py プログラムが正常終了したのがわかります。
デバッグ実行をブレークしてみる
- 今度はデバッグ実行を途中でブレークしてみます。
↑ 6行目にブレークポイントを置いてみました。F5でデバッグ実行されます。
↑ ブレークしました。argvに ['/root/opt/sample.py', '180'] という値が入っているのが見えます。
引数が格納される argv は配列変数で、0番目にプログラムのパスが入り、1番目にコマンドライン引数が渡されるということがわかります。ついでにウォッチ式で特殊変数の name の値も表示させています。これはこのモジュールの起動の仕方を判別するための特殊な変数ですが、長くなりましたのでここでは深入りしません。
まとめ
以上で、WSL、Docker、VSCode という3つのツールを連動させ、コンテナ環境で Python の開発ができるところまでたどり着きました。しかしこれはあくまで開発のスタートラインについただけであって、ここから先が本当の開発になります。そのためには Python や Docker の使い方はもちろん、開発内容のテーマ(機械学習、スクレイピング、作業自動化など)についてさらに勉強が必要になるでしょう。
今回の記事はここでいったん終了とします。ここまで読んでいただきありがとうございました。
-
WSL上でGPUを動かすCUDA on WSL2という仕組みもNVIDIAから提供されているらしい。参照:待ってました CUDA on WSL 2 ↩
-
コンテナが不要であれば必ずしもコンテナを使う必要はなく WSL + VSCode という形でも開発は可能です。 ↩
-
入門サイトの例としては http://y-ohgi.com/introduction-docker/ の評価が高いようです。 ↩
-
Docker Hub とは、the Docker Communityが提供しているイメージ管理用サービス。一種のリポジトリのようなもの。https://hub.docker.com/ ↩
-
Infrastructure as Codeはインフラの構成をコードに落とし込み宣言的に環境を構築する手法。 ↩
-
この辺りはまだまだ環境に不慣れなため、実際にはいろいろトラブって試行錯誤しています。もう少しちゃんと分かってきたら説明を加えるかも知れません。 ↩