Dockerfile / docker-compose を使った VsCode Remote Container での開発環境構築【備忘録】

VsCode の Remote Contaier で Dockerfile や docker-compose を使い開発環境を構築する際の備忘録です。

## Dockerfile を使う場合

任意の Dokcerfile を作成。
VS code上の 左下の `><` のマークをクリックし、`Open Folder in Container `を選択。
Dockerfileのあるフォルダを選択し Open。
画面上部で、コンテナの作成方法を尋ねられるので、 `From 'Dockerfile'`を選択。
コンテナが作成され、Dockerfile を配置した作業フォルダがコンテナにマウント（デフォルトでは `/workspace`）される。
 `.devcontainer`フォルダと `.devcontainer.json`が作成され、コンテナやコンテナ内の VsCode の設定が可能。
(`.devcontainer`内に Dockerfile を含めてGit管理するのが一般的？)

```:ディレクトリ構成例
project_dir
  |__ .devcontainer
  | |__ .devcontainer.json
  |__ Dockerfile
  |
  |__ src_dir
```

`.devcontainer.json`にて開発コンテナの設定が可能。コンテナ内に導入する VsCode の拡張機能を指定できる。
詳しくは [公式リファレンス](https://code.visualstudio.com/docs/remote/devcontainerjson-reference) を参照。

コンテナ上でアプリ実行等でポートが開放されると、ホスト <-> コンテナ間のポート開放を自動で行ってくれるのでとても便利。



## docker-composeを使う場合

docker-compose を用いて複数コンテナを立ち上げることも可能。
アプリケーションとDBなどを一度に立ち上げたいときに便利。



```:ディレクトリ構成例
project_dir
  |__ .devcontainer
  | |__ .devcontainer.json
  |
  |__ app
  | |__ Dockerfile
  |
  |__ db
  | |__ Dockerfile
  |
  |__ docker-comopse.yml
```
コンテナ作成方式は Dockerfile の場合と概ね同じで、`docker-compose.yml`を作成しておく。(コンテナ作成は `From docker-comopse.yml`を選択)
数コンテナ立ち上がる場合、アタッチするコンテナを選択するダイアログが出るので、ターゲットのコンテナを選択。

### docker-compose を使う際の注意



#### ポートマッピング
Dockerfile の場合はコンテナのポート開放を検知してくれていたが、docker-comopse を利用する場合は `docker-compose.yml`内でポートの設定を明示的にしてあげる必要がある。

#### コンテナ起動維持コマンド
起動したコンテナが終了してしまう場合は `docker-compose.yml` の `command` にて下記コマンドを指定する。

```yml:docker-compose.yml（抜粋）
command: bin/sh -c "while sleep 1000; do :; done"
```
（Dockerfile 利用時は、デフォルトコマンドを上記コマンドに上書きしているらしい）

#### ボリュームマウント
デフォルトだと、open したディレクトリ全体を各コンテナがマウントしてしまうため、明示的にソースディレクトリごとにマウントすると良い。
その時、cached マウントを明示的にしてするとパフォーマンス向上が見込める。
（これもデフォルトは cached マウントだが、docker-compose 利用時には明示的に指定する必要がある。）

```yml:docker-compose.yml(抜粋)
volumes:
      - ./app:/workspace/app:cached
```

#### .devcontainer.json の設定

Dokcerfile と docker-compose で `.devcontainer.json` の書き方が異なるので注意。
詳しくは [公式リファレンス](https://code.visualstudio.com/docs/remote/devcontainerjson-reference) を参照。





### 複数コンテナについてアタッチを切り替える or 2窓で開く

例えばバックエンドとフロントエンドが別れており、それぞれで開発を行う場合などに、アタッチするコンテナを切り替える or 2画面で開きたい場合の方法。
下記のようなディレクトリ構成にし、それぞれに`.devcontainer.json` を配置する。
`"service"` プロパティに、それぞれが稼働するコンテナを指定する。

```:ディレクトリ構成例
project_dir
  |__ .devcontainer
  | |__ .devcontainer.json
  |
  |__ backend
  | |__ .devcontainer.json # "service" にバックエンドのコンテナを指定
  | |__ ・・・
  |
  |__ frontend
  | |__ .devcontainer.json # "service" にフロントのコンテナを指定
  | |__ ・・・
  |
  |__ docker-comopse.yml
```

`Open Folder in Container` で `backend` or `frontend`ディレクトリを指定。
コンテナにアタッチしている状態で再び `Open Folder in Container`を選択し、もう一方を選択すると切り替わる。
もしくは新規に VsCode のウィンドウを開き、同様にもう一方を選択すれば、2窓で作業可能。



### docker-compose.yml の上書き

`.devcontainer.json`の`dockerComposeFile`は複数指定でき、重複する項目は上書きされる。（`dockerComposeFile`で上位に指定したものが優先。）
これによりコンテナごとに設定を変えることができる。
（あまり用途を思いついていないが、例えば CI 環境用の `docker-compose.yml` を流用 & 開発用に一部変更したい場合に使う？）


  ```:ディレクトリ構成例
  project_dir
    |__ .devcontainer
    | |__ .devcontainer.json
    |
    |__ backend
    | |__ .devcontainer.json 
    | |__ docker-comopse.yml # コンテナごとに上書き
    | |__ ・・・
    |
    |__ frontend
    | |__ .devcontainer.json
    | |__ docker-comopse.yml # コンテナごとに上書き
    | |__ ・・・
    |
    |__ docker-comopse.yml
  ```

  ```json:../backend/.devcontainer.json(抜粋)
    "dockerComposeFile": [
      "../docker-compose.yml",
      "../.devcontainer/docker-compose.yml"
    ]
    "service": "backend",
  ```
(frontend 側の `.devcontainer.json`も同様に指定。)