開発環境を Docker でいい感じにしてくれるやつとして、 Visual Studio では「コンテナー開発ツール」が、 Visual Studio Code には Remote 拡張があります。これらは Dockerfile や docker-compose.yml を用意すると、その中でアプリを動かすことができるやつです。しかし、同じものではないので、挙動はまったく異なります。それぞれメリット、デメリットがあるので、両方使えるとうれしいわけです。そこで、うまいこと両方で使える docker-compose.yml を書いてみようという試みをやっていきます。
それぞれのメリット、デメリット
コンテナ化、特に Docker Compose を使いたい理由として、クラサバ型データベースを開発環境に置きたいという欲求があります。適当にデバッグ実行したら適当なデータベースが動いていると便利です。というわけで、今回は PostgreSQL コンテナとアプリ開発環境が共存することを目標とします。
Visual Studio の Docker 連携は、コンテナにビルド結果とデバッガーの口をマウントして、コンテナ内でアプリを実行してくれます。メリットは、開発環境はホストにあるので、 Visual Studio をフルに使えることです。デメリットは、コンテナ内に入って何か操作するというのが面倒なところです。
VSCode Remote は、コンテナの中で VSCode が動きます。ホストのディレクトリをコンテナにマウントすることで、ホストのファイルを編集できます。メリットは、 VSCode のターミナルからコンテナ内を触り放題なところです。例えば Windows で開発していて、 Linux で動かしたい開発ツールがあるときには便利です。デメリットは、 Visual Studio に慣れた人間にとって、 VSCode の C# 拡張は不足を感じるところです。
データベースを置くという今回の仮定では、データベースを手で操作するときに簡単に環境に入るために VSCode を使いたいものの、メインの開発は Visual Studio でしたい、となり、共存させたい欲求が発生しています。
やっていく
1. Visual Studio で連携を設定する
ここで説明する手順を実行するには、 Visual Studio 2019 で「ASP.NET と Web 開発」または「.NET Core クロスプラットフォームの開発」ワークロードがインストールされている必要があります。
ソリューションエクスプローラーで、 Docker で動かしたいプロジェクトを右クリックし、「コンテナー オーケストレーターのサポート」を追加します。
いろいろ聞かれますが、 OS は Linux、ツールは Docker Compose としておけば OK です。
完了すると、 Dockerfile と「docker-compose」というプロジェクトが生えます。
これで、必要なファイルを Visual Studio に自動生成させることができました。ここから先は生成されたファイル書き換えたり移動させたりして VSCode にフィットさせていきましょう。
2. Dockerfile を改変する
生成された Dockerfile を確認すると、本番ビルド用のスクリプトが書かれています。今回はこれを完全に捨てることにします。ただ、プロジェクトディレクトリ下に Dockerfile がないと Visual Studio が認識してくれないので、ここに開発環境を作成するスクリプトを書きましょう。本番用 Dockerfile はどこか別のところに置いてください……。
最低限必要なのは FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster
だけです。「buster」のところは好きなディストリビューションに変えてください。必要に応じて、例えば今回の仮定ならば postgresql-client を入れたりするのもいいでしょう。
3. docker-compose.yml を改変する
ここからの操作は Visual Studio を破壊するので、すべてが完了するまで Visual Studio は閉じておきましょう。
いま、ソリューションディレクトリ直下に「docker-compose.yml」と「docker-compose.override.yml」があります。直下にあってもわかりにくいので、後で devcontainer.json というファイルを入れることになる .devcontainer というディレクトリをつくっておき、そこに移動させます。
さらに、 docker-compose.override.yml という名前だと Visual Studio 用なのか VSCode 用なのかわかりにくいので、 docker-compose.vs.yml に改名しておくといいでしょう。
いま docker-compose.yml の中身はこのようになっていると思います。
改変が必要なポイントは次のふたつです。
build.context
のパスを正しく直す。 docker-compose.yml を移動したので、それに合わせます。- PostgreSQL を追加する。
改変結果はこんな感じです。 docker-compose.yml の構文バージョンやプロジェクト名は、環境に合わせて書き換えてください。
データベースのデータの永続化は、ホストのパスを指定するか、この docker-compose.yml の外で作成したボリュームを割り当ててください。でないと、 VS と VSCode で Docker Compose のプロジェクト名が異なるので、同じデータを見てくれません。
4. docker-compose.dcproj を改変する
docker-compose.yml を移動したので、 docker-compose.dcproj も書き換えます。これもソリューションディレクトリ直下にあると邪魔なので .devcontainer に移動させてしまいましょう。
さらにファイル名変更を反映して、ディレクトリ外に行ってしまった .dockerignore をプロジェクトから消します。
またソリューションファイルもパスを書き換えます。
5. VSCode 向けの docker-compose.yml をつくる
VSCode 向けに .devcontainer/docker-compose.vscode.yml を作っていきます。ポイントは次のふたつです。
- コンテナが終了しないように無限ループさせる
- 作業ディレクトリをマウントする
実際の YAML で表すとこれだけです。
必要に応じて、ポートを公開するために ports
を追加したりしてください。
参考: VS Code Remote - Containers を Docker Compose で使うのだー! - Mitsuyuki.Shiiba
6. devcontainer.json をつくる
devcontainer.json は VSCode にコンテナ作成を指示する設定ファイルです。これも .devcontainer に置きます。
最小限の devcontainer.json はこんな感じです。
いじり倒したいときは devcontainer.json reference を読むといいでしょう。
完成!
これで準備完了です。 VSCode で「Reopen in Container」を実行すると、コンテナ上で VSCode が動き始めます。 Dockerfile のビルドが走るので気長に待ちましょう。
また、 Visual Studio でも docker-compose プロジェクトをスタートアッププロジェクトに設定して実行できるはずです!
注意!
まとめ
頑張れば Visual Studio でも VSCode でも使える Docker Compose 環境がつくれることを示しました。これで開発が捗ればいいね。捗らんか……。
ここまでの内容を clone するだけでお試しできるものを GitHub に置いておきました。