Python3の実行環境をDockerで用意するという記事を書いたのだが、これに少し追加情報
環境
Windows PC + Docker Desktop
lintに困る
Dockerを実行環境としてVS Codeで開発を行うのは快適なのだが一つ問題点がある。lintだ。
VS CodeからはWindowsのPythonを見ているので、ここにpip等でモジュールが入っていないとlintで怒られる。
かと言ってWindows側に綺麗に入れるのは面倒くさいし、それをしたくないからコンテナを実行環境にしているわけである。
Interpreterとしてコンテナ内部のPythonを指定したいのだ。
ググること1分もたたずに、答えが見つかりました。
VS Code Remote Development Extension
名前もそのままでした。いつものようにExtensionとして入れれば準備OK。
本家のマニュアルも非常に充実しているが、充実しすぎてて迷子になってしまう。
なので、既存で既に動いているコンテナにどうやって繋ぐか、という点に絞る。
とりあえずやってみる
こういう構成で始めます。
test2
│ docker-compose.yml
└─app
│ Dockerfile
└─src
| test.py
version: '3.7'
services:
remotedev:
build:
context: ./app
dockerfile: Dockerfile
container_name: remotedev
command: /bin/sh -c "while :; do sleep 10; done"
まずVS codeで上記のフォルダを開いておく。何かしょうもないことを間違っている気はするがこうしないとFrom docker-compose.ymlの選択肢が出てこない。
VS codeにExtensionを入れると左下にこんなのが出てくるのでクリックする。
次にRemote-Containers: Open Folder in Container..を選ぶ
フォルダを選ぶダイアログが出てくるのでdocker-compose.ymlがあるフォルダを選ぶ(ここではtest2)
更に次のような選択肢が出てくるのでFrom docker-compose.ymlを選ぶ
この時点で新しいコンテナが自動的に作成されている。
c:\source\test2>docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c7586573d867 test2_remotedev "/bin/sh -c 'while s…" 8 minutes ago Up 8 minutes remotedev
このコンテナが上記のdocker-compose.ymlをベースにRemote Containersとして使えるようにしたものである。
最初はこれがどういう設定で立ち上がってきているのかよく理解できなかった。
docker-compose.ymlを重ねて使う
さて元のフォルダ(test2)を見てみる。
test2
│ docker-compose.yml
├─.devcontainer
│ devcontainer.json
│ docker-compose.yml
└─app
│ Dockerfile
└─src
│ test.py
.devcontainerという新しいフォルダにdevcontainer.jsonとdocker-compose.ymlが自動で生成されている。
うまく行くと何をやっているのかさっぱりわからなかったのだが、ひょんなことから失敗してコマンドがわかった。
いろいろやってるっぽいが結局これを実行している
docker-compose -f c:\source\test2\docker-compose.yml -f c:\source\test2\.devcontainer\docker-compose.yml
ここの説明が非常にわかりやすい。
※docker-composeで複数環境を構築
まぁ、要するに後に設定した方で上書きされるということである。
何が書いてあるかというとこんな感じ(長いので一部コメントは消してます)
version: '3.7'
services:
# Update this to the name of the service you want to work with in your docker-compose.yml file
remotedev:
#...省略
volumes:
# Update this to wherever you want VS Code to mount the folder of your project
- .:/workspace:cached
#...省略
# Overrides default command so things don't shut down after the process ends.
command: /bin/sh -c "while sleep 1000; do :; done"
大したことは無くてvolumesで"test2"をコンテナ内の"/workspace"にマウントしているだけである。
**command:**はコンテナが落ちないようにするためのものである
実際コンテナ内部はこんな感じ
c:\source\test2>docker exec -it remotedev bash
[root@c7586573d867 workspace]# ls
app docker-compose.yml
[root@c7586573d867 workspace]# ls app/src/
test.py
VS codeはこんな風に見えている。
Extensionを見るとLOCALとDEV CONTAINERで分けてあり、DEV CONTAINER側には何もない。
なのでこの状態では普段利用しているPythonのExtensionが全く効いていないわけだ。
ではこのあたりの設定をどうすればよいのかというと、それが**.devcontainer/devcontainer.json**である。
これもコメントだらけなので殆ど省略する
{
"name": "Existing Docker Compose (Extend)",
// Update the 'dockerComposeFile' list if you have more compose files or use different names.
// The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
"dockerComposeFile": [
"..\\docker-compose.yml",
"docker-compose.yml"
],
// The 'service' property is the name of the service for the container that VS Code should
// use. Update this value and .devcontainer/docker-compose.yml to the real service name.
"service": "remotedev",
// The optional 'workspaceFolder' property is the path VS Code should open by default when
// connected. This is typically a file mount in .devcontainer/docker-compose.yml
"workspaceFolder": "/workspace",
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": null
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": []
// ...省略
}
基本的には**"extensions"**以外は無視して良いんじゃないかと思う。
ここには各extensionの下記の部分を入力すればよい(ms-python.python)
こんな感じ
"extensions": ["ms-python.python","dbaeumer.vscode-eslint"]
最後にこのコンテナをRebuildする
左下の緑の部分をクリックしてRemote-Containers: Rebuild Container
立ち上げてPythonファイルを表示すると
と聞いてくるのでInstallをクリックするとpipでインストールしてくれる。
これで今までPyPDF2やtabulaでimportのところに赤い波線が出てうっとうしかったのだがすっきりした。
※閉じるときは左下の緑をクリックしてClose Remote Connectionから閉じておこう。VS codeをそのまま閉じると次回も接続しに行ってしまう
virtualenvを自動で有効にしているコンテナは気をつけよう
元々centos/python-36-centos7:latestというイメージをベースにしていた。
CentOS7ベースで既にPythonが入っていたのであとはJDK突っ込むだけだったので楽だったのだ。
しかしこれのせいでlintがが有効にならず悩んだ。
Pylintをインストールするか?と聞いてくるところまでは問題なかったが、pipでのpylintのインストールにどうしても失敗する。
(app-root) bash-4.2# /opt/app-root/bin/python /opt/app-root/src/.vscode-server/extensions/ms-python.python-2020.4.76186/pythonFiles/pyvsc-run-isolated.py pip install -U pylint --user
Can not perform a '--user' install. User site-packages are not visible in this virtualenv.
どうやらvirutualenvが有効なってるから無理、ってことらしい。
そこでこのイメージのDockerfileの最後の部分を見てみるとこうなってた
https://github.com/sclorg/s2i-python-container/blob/master/3.6/Dockerfile
# - Create a Python virtual environment for use by any application to avoid
# potential conflicts with Python packages preinstalled in the main Python
# installation.
# - In order to drop the root user, we have to make some directories world
# writable as OpenShift default security model is to run the container
# under random UID.
RUN source scl_source enable rh-python36 && \
virtualenv ${APP_ROOT} && \
chown -R 1001:0 ${APP_ROOT} && \
fix-permissions ${APP_ROOT} -P && \
rpm-file-permissions
何か色々面倒なので結局素のCentOS7からBuildすることにした