VSCode内の統合ターミナルから、Docker内でアプリを実行するために使った力技


2019年8月21日 追記

この記事の内容は古く、大きく遠回りしています。
読む必要はありません。

VSCodeのリモートデベロップメントを使おう。
https://code.visualstudio.com/docs/remote/remote-overview

ボクはリモートデベロップメント(linux vm)を使っていますが、快適です。

はじめに

Windows上にVMを立て、
VM上のDockerコンテナでアプリケーションを実行させているのですが、
・毎回dockerイメージをビルドするのも面倒くさい。
・Windows上で編集したファイルをLinuxにコピーするのも面倒くさい。
・Windows上のVMだから、F1からのタスクが定義できなくて実行が面倒くさい。
・毎回docker runとか叩きたくない。

といった悩みがありました。
私なりに解決策を考えてみたので、
誰かの役に立てばと思います。

WindowsとLinuxのファイルコピーが面倒くさい。

WindowsとLinuxでファイル共有する方法は沢山あると思います。

WinSCPを使う。
 →いちいちSyncされているかを意識しなければいけないのが面倒かと思った
 (実際意識する必要はないかもです。あんまり触ってないです。いい加減ですね。。。)

Linux上にSambaを立てちゃう。
 →SambaはSambaで、ファイル作成時の権限の設定してあげないといけなかったり、
  SambaのユーザとLinuxのユーザーをマッピングしなければいけなかったりと、
  複雑化しそうなので手を出したくなくなった。

vagrantとVirtualBoxでファイル共有設定しちゃう。
  →guest additionが入らないことがよくあったので、避けた

色々理由をつけて避けましたが、
私が選んだのはコレでした。

dokany+win-sshfs
https://github.com/masaeedu/win-sshfs
https://github.com/dokan-dev/dokany
※Dokanのバージョンは。1.1.0.2000にすること。
 GUI版もあるので、その場合は、他の型のQiitaの記事を参考に、インストールするといいと思います。

なんとSSHの接続先に、ドライブレターを割り当て、
ファイルシステムとして操作することができます!

dockerイメージを毎回ビルドしないとアプリが実行できない

pythonやruby等のインタプリタ言語を書いているとき、
dockerイメージをビルド→docker runで実行という流れでやってしまっており、
インタプリタ言語の利点を殺してしまっていると感じました。

そこで、

・dockerホストと、コンテナでディスク共有してしまえばいいじゃないか?
 コードの編集はdockerホスト上で、
 コードの実行は、コンテナの中から実行すればいいんじゃないのか?

・開発中のコンテナはアプリを包まずベースとして定義。
 リリース用のコンテナは、別で定義できないかな?

と考えました。

まず、コンテナとdockerホストで、ディスク共有ですが、
-vオプションを使えば簡単にできます。
・・・が、そんな長いコマンドは打ってられないし、覚えてられないので、
makefileにタスクを切っておきます。

makefile抜粋
RELEASE_CONTAINER := hogehoge
BASE_CONTAINER := $(RELEASE_CONTAINER)-base
APP_ROOT := /app
CONTAINER_APP_ROOT := /app
MAIN_APPLICATION := entrypoint.sh

# ベースのコンテナは、頻繁に利用、更新されると思ったので、
# 先頭に定義して「make」だけで実行するようにした。
commit: var
    docker image build -t $(BASE_CONTAINER) \
    --target base \
    .

# 試行錯誤中、コンテナの中に入りたいときは沢山ある。
# なんで「make shell」でコンテナの中に入るタスクを定義
shell: var
    docker container run -ti \
    --network host \
    -v $(ROOT_DIR)$(APP_ROOT):$(CONTAINER_APP_ROOT) \
    --rm $(BASE_CONTAINER) \
    /bin/sh 

# いちいち /app/entorypoint.shをコンテナの中で実行するのは面倒なので、
# これも「make run」でタスクをていぎ
run: var
    docker container run -ti \
    --network host \
    -v $(ROOT_DIR)$(APP_ROOT):$(CONTAINER_APP_ROOT) \
    --rm $(BASE_CONTAINER) \
    /app/entrypoint.sh

# リリース用のコンテナを作る定義
release: var
    docker image build -t $(RELEASE_CONTAINER) \
    --target release \
    .

var:
    $(eval ROOT_DIR := $(shell pwd))

次に、ベースのコンテナと、リリース用のコンテナを分けるため、
マルチステージビルドをDockerfile上に定義

Dockerfile
FROM alpine:latest as base

RUN apk add python3
RUN pip3 install --upgrade pip
COPY /app/requirements.txt /requirements.txt
RUN pip3 install -r /requirements.txt

FROM base as release
COPY /app /app
ENTRYPOINT ["/app/entrypoint.sh"]

 
 
 
 
マルチステージビルドと、dockerの-vオプション、
makefileを駆使すれば、それなりに使いやすくなり、
以下のような形でコンテナへのアクセスが楽になった。

[root@localhost hogehoge]# make shell
docker container run -ti \
--network host \
-v /home/hoge_user/develop/hogehoge/app:/app \
--rm hogehoge-base \
/bin/sh
/ #

VSCodeからmakefileで定義したタスクが実行できない。

SSH接続先のmakefileをいい感じに実行できる。
そんな楽なものは見つけることができなかった。

なので、VSCodeの拡張を導入し、
統合ターミナル上ですぐにSSHログインできるようにし、
makeを単純に実行することにした。

そこで利用したのが、
SSHExtention
https://github.com/VitalyKondratiev/vscode-sshextension

こんな感じでコンフィグを書いておくと、F1から簡単にSSHログインできる。

    "sshextension.serverList": [
        {
            "name": "hogehogevm",
            "host": "192.168.56.100",
            "port": 22,
            "username": "root",
            "privateKey": "C:\\Users\\hoge_user\\develop\\keys\\id_rsa",
            "path": "/develop"
        },
    ],
    "sshextension.openProjectCatalog": true

終わりに

ここまでやったことによって

①VSCodeからSSHFSでマウントした先をディレクトリとして開く
②コードを編集
③F1からSSHでVM接続へのショートカットを呼び出し→SSHでVMにログイン
④VMの中でmake run実行

という流れで編集~コード実行までできるようになった。