アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

VSCode の Remote - Containers 拡張を試してみた

morishitaです。

先日リリースされたVisual Studio Code May 2019で Stable でもRemote Developmentが使えるようになりました。

これはExtension Packで、次の3つの拡張を含んでいます。

これらは、それぞれ個別にもインストール可能です。

最後のRemote - WSLはWindowsでしか使えないと思うので、macOSユーザの私はスルーなのですが、残りの2つはちょっと気になります。

今回はより利用する機会(=利用できれば便利な場面)が多そうなRemote - Containersを試してみました1

Remote - Containersとは?

環境の構築・再現が容易で、他の環境から隔離させられるDockerコンテナを使った開発環境を使っている方も多いと思います。

Remote - Containersはそんな方々に便利そうな拡張です。
その名の通り、Dockerコンテナ上で動作している開発環境に接続して、あたかもコンテナ上でVSCodeを動作させてるかのようになります2

使ってみる

では、実際に使ってみましょう。

動作確認するにあたり、次のようなdocker-compose.ymlをプロジェクトのルートディレクトリに持つ簡単なRailsアプリケーションを例にします。

version: "3"
volumes: 
  pgdata:
  gem_home:

services:
  postgres:
    image: postgres:10.7
    ports: 
      - 35432:5432
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment: 
      POSTGRES_PASSWORD: pgpassword
  rails:
    build: .
    image: rails-pg
    ports: 
      - 33000:3000
    volumes:
      - .:/rails-pg
      - gem_home:/usr/local/bundle
      - /rails-pg/.git
    depends_on:
      - postgres
    working_dir: /rails-pg
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"

次の2つのコンテナ定義を含むシンプルな構成です。

  • postgres:
    • PostgreSQL 10.7
  • rails
    • Railsのコンテナ。Ruby 2.6.3、Rails 5.2.2
    • プロジェクトルートを/rails-pgマウントしておりRailsを起動できる

docker-compose upを実行すると次のとおりになります。

$ docker-compose ps
       Name                      Command               State            Ports         
--------------------------------------------------------------------------------------
rails-pg_postgres_1   docker-entrypoint.sh postgres    Up      0.0.0.0:35432->5432/tcp
rails-pg_rails_1      bash -c rm -f tmp/pids/ser ...   Up      0.0.0.0:33000->3000/tcp

ブラウザでhttp://localhost:33000/を開くと、Railsアプリケーションにアクセスできます。

開発作業はrailsコンテナに入ってやりたいということになります。

インストール

VS Codeのインストールはできているという前提で進めます。
まずはRemote - Containers - Visual Studio Marketplaceをインストールします。

インストールが完了すると次のような表示がVSCodeのウィンドウの左下角に追加されます。

f:id:HeRo:20190617082959p:plain
VSCode Remote

Railsプロジェクトを開いてみる

Remote - Containersを使う場合には、Fileメニューからプロジェクトのルートディレクトリを開くのではなく、先程の左下の赤い角をクリックします。

すると次のメニューがコマンドパレットに表示されます3

f:id:HeRo:20190618084322p:plain
コマンドパレット

この中から、Remote-Containers: Open Folder in Containerを選択します。ファイル選択ダイアログが表示されるので、docker-compose.ymlのあるプロジェクトのルートディレクトリを選択します。

次にDockerfiledocker-compose.yml、いずれを参照して起動するかを聞かれるので、docker-compose.ymlを選択します。

f:id:HeRo:20190618084358p:plain
docker-composeを選ぶ

最後に、次の様にdocker-compose.yml内のどのコンテナかを聞かれるので、railsを選択します。

f:id:HeRo:20190617083139p:plain
コンテナ選択

すると、VSCodeが再起動して開き直します。

どんな状態で立ち上がっているのか?

ファイルツリーには次の様に表示されます。

f:id:HeRo:20190617083222p:plain
ファイルツリー

rails-pgディレクトリにもともとのプロジェクトルートディレクトリをマウントしているので、この中だけ見えればいいのですが、/が見えてしまっています。

docker-compose.ymlworking_dir: /rails-pgを設定していますが、効いてないようです。

コンテナの起動状態は次のとおりです。

$ docker-compose ps
       Name                      Command               State            Ports         
--------------------------------------------------------------------------------------
rails-pg_postgres_1   docker-entrypoint.sh postgres    Up      0.0.0.0:35432->5432/tcp
rails-pg_rails_1      bash -c rm -f tmp/pids/ser ...   Up      0.0.0.0:33000->3000/tcp

docker-compose up した時と全く同じ様に起動されているようです。

なので、http://localhost:33000/ を開くとRailsアプリケーションにアクセスできます。

VSCodeを閉じると、コンテナも停止されます。

.devcontainer.json

再度、普通にFileメニューからVSCodeでプロジェクトのルートディレクトリを開くと、.devcontainer.jsonというファイルが追加されています4
これはVSCodeが起動するコンテナの開発環境Dev Containerについての設定ファイルです5

上記の操作の結果では次のような内容になっています。

// See https://aka.ms/vscode-remote/devcontainer.json for format details.
{
    "dockerComposeFile": "docker-compose.yml",
    "service": "rails",
    "workspaceFolder": "/",
    "extensions": []
}

このファイルの中にworkspaceFolderの設定項目があります。
この値を"rails-pg"に書き換えて、VSCodeを開き直します。

すると、次のようなダイアログがウィンドウの右下に表示されます。

f:id:HeRo:20190617083458p:plain
再OPENのダイアログ

Reopen in Conrainer をクリックすると.devcontainer.jsonに従ってコンテナでプロジェクトを開いてくれます。

"workspaceFolder": "rails-pg"に書き換えていたので今度はrails-pgディレクトリの中だけが次の様にファイルツリーに表示されます。

f:id:HeRo:20190617083550p:plain
rails-pgに絞り込まれたファイルツリー

これで余計なファイルを見なくて済むしうっかり変更してしまうということもなくなるでしょう。

ターミナルがコンテナ内で開く

Dev Containerでプロジェクトを開いた状態で、VSCode内のターミナルを起動してみると、それもコンテナ内で動作しています。

f:id:HeRo:20190617083651p:plain
コンテナ内で動作するターミナル

Railsの開発は折りに触れ、bundle installや、rails g …コマンドを使うので、ターミナルを開いたらすでにコンテナの中というのは便利です。
この状態のVSCodeを使っっているならコンテナの外か内かを意識しないで済みそうです。

その他、気になったところ

コンテナ側に拡張を入れ直す必要がある

Dev Container環境で利用したい拡張はすでにインストールしていてもコンテナ側に再度インストールする必要があります。 そもそもEXTENTIONマネージャの表示からして、次の様にDEV CONTAINERLOCALに分かれています。

f:id:HeRo:20190617084324p:plain
Dev ContainerとLOCALに別れた拡張マネージャ

私はEditorConfig for VS Codeは普段からインストールしています。Dev Container環境だと次の様にIntall in Dev Containerという表示がでてコンテナ側へのインストールを求められます。

f:id:HeRo:20190617083732p:plain
Intall in Dev Container

おお、これは面倒だと思ったのですが、インストールの手間を軽減する方法はあります。

次の様に.devcontainer.jsonextensionsに設定しておくと、Dev Container作成時にインストールしてくれます。

// See https://aka.ms/vscode-remote/devcontainer.json for format details.
{
    "dockerComposeFile": "docker-compose.yml",
    "service": "rails",
    "workspaceFolder": "/",
    "extensions": [
         "editorconfig.editorconfig",
         "rebornix.ruby"
     ]
}

ただしコンテナを作る時だけにインストールされる様なので、既存コンテナがある場合には次のいずれかを実行する必要があります。

  • 一旦コンテナを削除して、再度Dev Container環境を開く
  • Remote-Containers: Rebuild Containerを実行する

.devcontainer.jsonをリポジトリに入れておけば、VSCodeを使うプロジェクトメンバーで同じ拡張をインストールした状態を共有できます。
プロジェクトで使うフレームワークや言語に特化していたり、コーディング規約やコードフォーマットを守らせる拡張は上記でいいでしょう。

でも、好みが分かれる汎用的な拡張はインストールを強要するような共有はしたくはありません。例えば、私はBracket Pair Colorizer 2をとても便利に使っていますが、この手の拡張を使いたいかどうかは人それぞれでしょう。
プロジェクト単位ではなくユーザ単位で必ずDev Container環境にインストールする拡張を設定するにはsetting.jsonに次の様に設定を追加します。

{
   ・・・
    "remote.containers.defaultExtensions": [
        "coenraads.bracket-pair-colorizer-2"
    ]
   ・・・
}

するとDev Containerが作られるときにここで設定した拡張もインストールされるようになります。

これでチームの方針を共有しつつ、各メンバー独自の開発環境ができますね。

.gitディレクトリをコンテナに入れなきゃならない

Dev Container環境でファイルを編集していて、ファイルツリー状で変更が確認できないということに気づきました。
.gitをコンテナに入れる必要がないと思って、docker-compose.ymlvolumesの設定で/rails-pg/.gitを設定して空にしていたのですが、これが良くないようです6

この設定を削除して、.gitディレクトリもDev Containerに含まれるようにして再度環境を開き直すとGitの履歴や変更状態を確認できるようになりました。

まとめ

この拡張自体、まだPreview版なので、今後改善されて使いやすくなっていくと思いますが、その際に仕様が変わったりするかもしれませんし、思わぬ不具合があるかもしれません。
その点には注意が必要ですが、コンテナの外か内かを意識せず開発でき、快適になると思います。

参考

最後に

アクトインディではエンジニアを募集しています。


  1. コンテナ運用で使い捨てにするサーバが増えてSSHで中に入ってなにかするってことがあんまりないので。ゼロってわけでもないんですがね。

  2. ローカルマシン上で動いているDockerコンテナがリモート? って思うかもしれませんが、ローカルマシン上でネイティブに動作するOS以外の仮想環境やコンテナで動作しているOSには何らかの通信で接続しておりそういう意味でリモートなんですね。

  3. 私は Remote - SSH拡張もインストールしているのでそのメニューも含まれています。

  4. Remote-Containers: Create Container Configuration fileメニューを選択しても作成できます。

  5. なにが設定できるかはdevcontainer.json referenceに記載されています。

  6. コンテナの高速化ためのTipsとして設定していました。