🖋

VS Code Dev Containerこと始め

2021/10/18に公開

VSCode Remote Development (Container)

VSCode Remote Developmentのコンテナ部分に関して公式ドキュメントを翻訳して理解をします。
せっかくなので記事にしておきます。

この文章は VSCode公式ドキュメント から抜粋した内容です。

VSCode Remote Development は Remote {Containers, WSL, SSH} の3つをパックした拡張機能です。

  • 開発PCからシームレスにリモートPC(実行環境)に繋いで開発ができます。
  • 実行環境が同じにできるため、新規開発者が簡単に参加できます。
  • 開発PCと実行環境を分離できるので、SDKのバージョン管理が楽になります。

全体像

便利そうと思ったら、インストールしてみましょう。

翻訳

Dockerコンテナを実行環境にできるようになります。
プロジェクトディレクトリに置いた devcontainer.json ファイルでツールやランタイムを制御できます。
プロジェクトのファイルはマウントしてもいいしコンテナにコピーしてもいいし、コンテナ内のを利用できます。
VScodeの拡張機能はコンテナ内にインストールされます。
それにより、実行環境の機能(ツールやファイルシステム)が使用できたり、別コンテナに繋ぐだけで環境の切り替えがシームレスに行えて便利です。
もちろんVSCodeの補完やデバッグなどもローカル開発時と同じレベルで使えます。

注意事項
開発PCと実行環境でファイルの改行コードが違う場合は注意が必要です。
Gitの機能を使って改行コードを統一しておきましょう。

クイックスタート:既存のコンテナ編

既存のコンテナをフルタイムの開発環境と使用する方法は、

  1. コマンドパレットから Remote-Containers: Open Folder inContainer... を実行するか、
    左下にある緑色のクイックアクションステータスバーアイテムをクリックします。

    quick actions Status bar item

  2. 次に、ベースとなる開発コンテナをリストから選ぶか、選択したディレクトリにあるDockerfileやDocker Composeファイルを使用します。
    リストに表示されるコンテナは vscode-dev-containersリポジトリ のものです。

    注意事項*
    Alpine Linuxコンテナを使用する場合、 glibc に依存している一部の拡張機能が使用できません。

  3. 選択すると、VSCodeが設定ファイルをコンテナ内に作成します。(.devcontainer/devcontainer.json)

  4. そして、VSCodeはリロードされ開発コンテナをビルドし始めます。
    初回はコンテナのビルドに時間がかかります。2回目以降はキャッシュがあるので早いでしょう。

  5. ビルドが終わると、VSCodeは開発コンテナに接続した状態になります。

    Note
    公式ドキュメントにはマルチルートワークスペースやマルチコンテナ環境について記載があります。
    VSCode使いこなしてないので、マルチルートワークスペースを知らないので必要になったら思い出します。
    マルチコンテナは1つのVSCodeウィンドウで扱えないけど、Docker Composeのコンテナに1度で複数VSCodeを立ち上げて繋げることはできるみたいです。

クイックスタート:Gitリポジトリ編

GitHub PRレビューや別ブランチの作業で分離されたリポジトリが欲しくなることがあるでしょう。
そんな時にコンテナ内でクローンすると便利です。

  1. コマンドパレットから Remote-Containers: Clone Repository in Container Volume... を実行します。

  2. 入力ボックスにGit URI、GitHub branch URL、GitHub PR URLを入力します。
    (例えば、 microsoft/vscode-remote-try-node

    input url

  3. 入力したリポジトリに .devcontainer/devcontainer.json がない場合は、既存のコンテナ編のようにベースコンテナを聞かれます。

  4. そして、VSCodeはリロードされ開発コンテナをビルドし始めます。
    初回はコンテナのビルドに時間がかかります。2回目以降はキャッシュがあるので早いでしょう。

  5. ビルドが終わると、VSCodeはソースを取得した開発コンテナに接続した状態になります。

    git status

devcontainer.jsonファイル

VSCodeのコンテナ設定はdevcontainer.jsonファイルに記載します。(デバッグ設定で使うlaunch.jsonみたいなもんらしい)
指定した拡張機能をコンテナ起動時にインストールしたり、post-createコマンドで準備したりできる。
devcontainer.jsonはローカルのプロジェクトルートに .devcontainer.json を置くか、 .devcontainer/devcontainer.json と1階層ディレクトリを掘って配置します。

記載内容の例(nodeコンテナ起動して、eslint拡張機能をインストール)

{
  "image": "mcr.microsoft.com/vscode/devcontainers/typescript-node:0-12",
  "forwardPorts": [3000],
  "extensions": ["dbaeumer.vscode-eslint"]
}

Inspecting volumes

使用しているボリュームをvscodeを使わずに調査をしたい時があると思います。
Remote-Containers:Inspect Volume in Container... コマンドで確認ができます。
もし、 Docker extension をインストールしてるなら、Volumes欄での右クリックから確認できます。

拡張機能の管理

VSCodeの拡張機能は次の2つのうちどちらかで実行されます。

  • クライアントである開発PCのUI側
    • テーマやスニペットみたいなの
  • リモートである実行環境のコンテナ側
    • そうじゃないほとんどのもの

これにより開発PC側の拡張機能は汚染されずに、コンテナ接続時にシームレスに拡張機能を切り替えられます。

拡張機能インストール時にローカル側かコンテナ側かに振り分けれらます。

local extension

container extension

振り分けがうまくできない場合は指定も可能です。(拡張機能開発者が未対応の場合ローカル側にならなかったり)
VSCodeの設定に

"remote.extensionKind": {
    "ms-azuretools.vscode-docker": [ "ui" ],
    "msjsdiag.debugger-for-chrome": [ "workspace" ]
}

のように指定します。 ui がローカル側で、 workspace がコンテナ側を強制します。
(無理矢理の対応のため正しく動かないこともあります。)

拡張機能の指定はdevcontainer.jsonに直接書くこともできますが、拡張機能リスト右クリックの Add to devcontainer.json から追加も可能です。

add extension

もし、どのコンテナでも常にインストールしたい拡張機能がある場合はVSCodeの設定の remote.containers.defaultExtensions で指定できます。
GitLensResource Monitorを指定する例。

"remote.containers.defaultExtensions": [
    "eamodio.gitlens",
    "mutantdino.resourcemonitor"
]

ポート開放

コンテナのポートをホストのポートに紐づけるには、2つの方法があります。

コンテナ起動時から常に転送したい場合は devcontainer.jsonforwardPorts を記載します。
3000番ポートと3001番ポートを転送する例。

"forwardPorts": [3000, 3001]

この設定後VSCodeウィンドウのリロードや再起動すると適用されます。

もう1つの方法は一時的に転送したい場合に使用します。
Forward a Port コマンドで指定できます。
Remote ExplorerのForwarded Ports欄で後から確認できます。
VSCode設定で remote.restoreForwardedPorts=trueにすると、設定を記憶することも可能です。

devcontainer.jsonに appPortを書くとポート公開もできます。(転送forwardと公開publish何が違うんだろう?)

"appPort": [ 3000, "8921:5000" ]

また、ポートマッピングはdevcontainer.jsonだけでなく docker-compose.yml での指定も有効です。

ports:
  - "3000"
  - "8921:5000"

ポート公開の適用はコンテナのリビルドが必要です。
Remote-Containers: Rebuild Containerコマンドで実行できます。

コンテナ内作業

コンテナ内のディレクトリを開くとVSCodeから開いたターミナルウィンドウ(Terminal > New Terminal)はローカルではなくコンテナ内で実行されます。
そのターミナル内では code CLIでファイルやディレクトリを開くことができます。

terminal

デバッグは launch.json で起動すると、アプリケーションはコンテナ内で実行され、デバッガがアタッチされます。
詳しくはdebuggingドキュメントを参照。

コンテナ設定

VSCodeのローカル設定は開発コンテナに接続しているときも利用されます。しかしローカルとコンテナで一部の設定を変更したい時があります。
Preferences.Open Remote Settings コマンドか、設定エディタのリモートタブでコンテナ固有の設定を行うことができます。

devcontainer.json にデフォルトのコンテナ設定を記載することもできます。例えばJavaホームの設定。

"settings": {
    "java.home": "/docker-java-home"
}

Git認証情報の共有

コンテナ起動時にローカルの .gitconfig ファイルをコピーしてくれます。

credential helper利用

リポジトリにHTTPS接続する場合、ローカルでcredential helper 設定が終わっていると自動的にコンテナ内でも利用できます。

SSH Key利用

ローカルでSSH agentが起動していると、コンテナ内へ自動的に転送されます。

GPG Keys共有

自分のコミットにGPG署名をしたい場合は、ローカルの鍵をコンテナと共有することができます。
GPG署名に関してはGitHubドキュメントを参照。

ローカルでGPGを設定するにはWindwosだと Gpg4win、macOSだと GPG Tools、Linuxだと gnupg2を利用します。
そして、コンテナに(Linuxだから)gnupg2をインストールします。例えば

RUN apt-get update && apt-get install gnupg2 -y

このように。
すると、次回コンテナ起動時にGPG keysが共有されています。

コンテナの管理

VSCodeでディレクトリを開いた時にdevcontainer.jsonに記載のコンテナを自動で起動しますが、通常はVSCode終了時にコンテナを自動でシャットダウンします。
終了時のシャットダウンしないようにするには devcontainer.jsonshutdownAction: noneを設定します。

未使用コンテナを整理する場合は Cleaning out unused containers and imagesを参照。

ドットファイルリポジトリ

実行環境コンテナにはいろんなアプリケーションがあるため、ドットファイルをどこかに保存しておくとコンテナにコピーできて便利です。
一般的な方法はドットファイルをGitHubリポジトリに保存し、ユーティリティーを使用してそれを適用することです。
この方法を使用するにはVSCode設定の Dotfiles: * に設定します。

dotfiles

settings.json に直接書く場合

{
  "dotfiles.repository": "your-github-id/your-dotfiles-repo",
  "dotfiles.targetPath": "~/dotfiles",
  "dotfiles.installCommand": "~/dotfiles/install.sh"
}

この設定以降のコンテナ作成時にドットファイルリポジトリが利用されます。

高度なコンテナ設定

See the Advanced Container Configuration article for information on the following topics:

制限事項(2021-05-30現在)

  • Windowsコンテナイメージはまだ未サポート
  • リモートDockerホストは使えるけど、追加設定が必要
  • マルチルートのワークスペースにあるすべてのルート/フォルダーは、下位レベルに設定ファイルがあるかどうかにかかわらず、同じコンテナで開かれます。
  • Linux用の非公式なUbuntu Docker snapパッケージはサポートされていません。お使いのディストリビューションの公式Dockerインストール手順に従ってください。
  • DWindowsのDocker Toolboxは未サポート。
  • ISSHを使用してGitリポジトリをクローンし、SSHキーにパスフレーズが設定されている場合、VS Codeのプルおよび同期機能をリモートで実行するとハングアップすることがあります。この問題を回避するには、パスフレーズのない SSH キーを使用するか、HTTPS を使用してクローンを作成するか、コマンドラインから git push を実行してください。
  • Lローカルのプロキシ設定がコンテナ内で再利用されないため、適切なプロキシ情報が設定されていないと、拡張機能が動作しないことがあります(例えば、グローバルな HTTP_PROXY や HTTPS_PROXY 環境変数に適切なプロキシ情報を設定するなど)。

devcontainer.json reference

VSCode Remote Developmentのコンテナ部分に関して公式ドキュメントを翻訳して理解をします。
せっかくなので記事にしておきます。

この文章は VSCode公式ドキュメント から抜粋した内容です。

devcontainer.json properties

devcontainer.json は接続先コンテナの設定を記載します。

Property Type 説明
Dockerfile or image
image string Required イメージ使用時。 作成コンテナのレジストリ内イメージ名 (DockerHub, Github Container Registry, Azure Container Registry)
build.dockerfile / dockerFile string Required when Dockerfile使用時. Dockerfile の場所。 devcontainer.json からの相対パス。vscode-dev-containers repository に多数のサンプルあり。
build.context / context string Dockerビルドする場所を、 devcontainer.json からの相対パスで指定。 省略時は ".".
build.args Object Docker image build arguments Dockerビルド時の引数をname-valueペアで指定。環境変数や pre-defined variables が使用できます. 省略時は設定されません。 例: "build": { "args": { "MYARG": "MYVALUE", "MYARGFROMENVVAR": "${localEnv:VARIABLE_NAME}" } }
build.target string Docker image build target Dockerビルド時のターゲットを指定。省略時は設定されません。例: "build": { "target": "development" }
appPort integer,
string,
array
新しい forwardPorts property の使用を推奨。コンテナからローカルに 公開 するポートを指定。forwardPorts と違い、localhost だけでなく全てのインターフェイス (0.0.0.0) をリッスンする必要があります。省略時は []
containerEnv object コンテナで上書きする環境変数をname-valueペアで指定。環境変数や pre-defined variables が使用できます。例: "containerEnv": { "MY_VARIABLE": "${localEnv:MY_VARIABLE}" }
適用するにはコンテナの再構築が必要。
remoteEnv object コンテナ全体は変えずに、VSCode(またはターミナルなどのサブプロセス)だけで上書きする環境変数をname-valueペアで指定。環境変数や pre-defined variables が使用できます。ターミナルで有効にならない時は Terminal > Integrated: Inherit Env の設定を確認してください。例:"remoteEnv": { "PATH": "${containerEnv:PATH}:/some/other/path", "MY_VARIABLE": "${localEnv:MY_VARIABLE}" }
適用するにはVSCode ウィンドウのリロードが必要。
containerUser string コンテナ内のユーザーを指定。省略時は root かイメージ作成時に使用されたDockerfileの最後の USERです。Linuxでは、指定されたユーザーの UID/GID がローカルユーザーの UID/GID と同じに更新され、ボリュームバインド時のパーミッション問題を回避します。 (updateRemoteUserUID で無効にした場合を除く。)
適用するにはコンテナの再構築が必要。
remoteUser string VSCodeがコンテナ内で実行するユーザーを指定。(ターミナル、タスク、デバッグなどのサブプロセス)。省略時は containerUserと同じ。Linuxじは, containerUser と同様にUID/GIDを制御します。
適用するにはVSCodeウィンドウのリロードが必要。ただしUID/GIDの更新はコンテナの再構築が必要。
updateRemoteUserUID boolean trueならLinuxでは, containerUserremoteUser が指定されると、ユーザーの UID/GID がローカルユーザーの UID/GID と同じに更新され、ボリュームバインド時のパーミッション問題を回避します。falseにするとこの動作を行いません。 省略時は true
適用するにはコンテナの再構築が必要。
mounts array コンテナの作成時に追加するマウントポイントの配列です。各値は、 Docker CLI --mount flagと同じ値を受け入れる文字列です。環境変数やpre-defined variables が使用できます。 例: "mounts": ["source=${localWorkspaceFolder}/app-scripts,target=/usr/local/share/app-scripts,type=bind,consistency=cached"]

⚠️ Codespacesは、Dockerソケットを除いて「bind」マウントを無視します。
workspaceMount string コンテナの作成時にワークスペースのデフォルトのローカルマウントポイントをオーバーライドします。Docker CLI --mount flagと同じ値をサポートします。主に リモートコンテナの設定ディスクパフォーマンスの向上に役立ちます。環境変数やpre-defined variables が使用できます。 例:
"workspaceMount": "source=${localWorkspaceFolder}/sub-folder,target=/workspace,type=bind,consistency=cached"

⚠️ コードスペースではまだサポートされていません。また、コンテナボリュームでクローンリポジトリを使用する場合もサポートされていません。
workspaceFolder string VS Code がコンテナに接続するときに開くデフォルトのパスを設定します。通常、workspaceMountと組み合わせて使用します。省略時はソースコードの自動マウント場所。

⚠️ CodespacesでDocker Composeを使用する場合と、Container VolumeでClone Repositoryを使用する場合のみサポートされます。
runArgs array コンテナ実行時のDocker CLI arguments を指定。省略時は[]。例えば, C++などのptraceベースのデバッガがコンテナ内で動作させるには: "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ]
overrideCommand boolean コンテナの起動時に、コンテナのデフォルトコマンドの代わりに、/bin/sh -c "while sleep 1000; do :; done" を実行するかどうかを指示します。省略時は true。 これはデフォルトのコマンドが終了するとコンテナがシャットダウンしてしまうのを防ぐためです。
shutdownAction enum ウィンドウが閉じられたとき、またはシャットダウンされたときに、VS Code がコンテナを停止するかどうかを示します。値は nonestopContainer (default).

⚠️ Codespaces には適用されません。
Docker Compose
dockerComposeFile string,
array
Required. Docker Compose使用時。 devcontainer.json からの相対パスを指定。arrayを使用するとDocker Compose 設定を拡張する 際に便利です。その場合順序は大事です。.env ファイルは通常プロジェクトルートのが使われますが、env_file を利用すると別の場所を指定できます。
service string Required. VSCodeが接続するDocker Composeファイル内のサービス名を指定。
runServices array VSCodeが起動すべきDocker Composeファイル内のサービスリストを指定。通常これらは切断時にシャットダウンされますが、"shutdownAction""none" にすると起動したままになります。省略時は全サービスです。
workspaceFolder string コンテナ接続時に最初に開く場所を指定。 (多くの場合コンテナ内でソースコードがあるボリュームマウントへのパストなるでしょう。)省略時は "/"
remoteEnv object Dockerfile or imageの場合と同じ。
remoteUser string Dockerfile or imageの場合と同じ。
shutdownAction enum ウィンドウが閉じられたとき、またはシャットダウンされたときに、VS Code がコンテナを停止するかどうかを示します。値は nonestopCompose (default).

⚠️ DCodespacesでは適用されません。
General
name string コンテナの表示名を指定。
extensions array コンテナ作成時にインストールするVSCode拡張機能を指定。省略時は []
settings object デフォルトの settings.json に追加する値を指定。
forwardPorts array コンテナからローカルに転送するポートを指定。
portsAttributes object 転送する特定ポートのプロパティを指定。ポート番号、範囲、正規表現が使用できる。
otherPortsAttributes object portsAttributes で指定されていないポートのプロパティを指定。
postCreateCommand string,
array
コンテナ作成後にコンテナ内で実行されるコマンドを指定。コマンドは workspaceFolder で実行されます。文字列に&&を使うと複数コマンドを実行できます。例: "yarn install""apt-get update && apt-get install -y curl"。 配列版だと ["yarn", "install"] となりこちらはシェルを経由せずに直接実行されます。ソースコードがマウントされた後に起動するので、ソースツリーのシェルスクリプトを実行することもできます。例: bash scripts/install-dev-tools.sh。省略時は何もしない。
postStartCommand string,
array
コンテナ起動時にコンテナ内で実行されるコマンドを指定。postCreateCommand と同様ですが、作成時ではなく起動時に毎回実行されます。省略時は何もしない。
postAttachCommand string,
array
postCreateCommandpostStartCommand と同様で、アタッチ時にコンテナ内で実行されるコマンドを指定。省略時は何もしません。
initializeCommand string,
array
コンテナ作成前に ローカルで実行されるコマンドを指定。ローカルの workspaceFolder で実行されます。Windows/macOS/Linux のパス変換に対応しています。

⚠️ コマンドはソースコードがどこにあっても実行されます。Codespacesではローカルではなくクラウド上で実行されます。
userEnvProbe enum デバッグ中やタスク実行中にデフォルトで使用するユーザー環境変数の「プローブ」にVS Codeが使用するシェルの種類を示します: none (default), interactiveShell, loginShell, or loginInteractiveShellが指定できます。 Interactive shells には通常 /etc/bash.bashrc.bashrc に設定された変数が含まれ、login shells には通常これらの "rc" ファイルと /etc/profile.profile に設定された変数が含まれます。省略時は none。none以外だと起動が遅くなる可能性があります。
devPort integer S Code Serverがコンテナ内で使用する特定のポートを強制的に指定することができます。省略時はランダムな利用可能なポートが設定されています。

Formatting string vs. array properties

postCreateCommand, postStartCommand, postAttachCommand, and initializeCommand は配列指定と文字列指定ができます。runArgs は配列指定飲みできます。
配列指定はシェルを使わずに直接OSにコマンドを流します。文字列指定はシェル経由です。

runArgs はコマンドラインで使うときはスペースを含む引数はシングルクォートで囲みますが、アプリケーションにはシングルクォートが除去されたものが渡されます。
そのため、 devcontainer.json の記載はシングルクォートはない状態で指定します。

Variables in devcontainer.json

devcontainer.json 内では ${variableName} の形でいくつか変数が参照できます。

Variable Properties 説明
${localEnv:VARIABLE_NAME} Any ローカル の環境変数 (VARIABLE_NAMEの部分)。未設定の環境変数は空白になります。例えばLinux / macOSではローカルのホームディレクトリ、Windowsではユーザーフォルダに変数を設定するには: "remoteEnv": { "LOCAL_USER_PATH": "${localEnv:HOME}${localEnv:USERPROFILE}" } (未指定は空白になるルールを使用)

⚠️ Codespacesではホストはクラウドになります。
${containerEnv:VARIABLE_NAME} remoteEnv コンテナ の環境変数(VARIABLE_NAMEの部分)。例:
"remoteEnv": { "PATH": "${containerEnv:PATH}:/some/other/path" }
${localWorkspaceFolder} Any VS Codeで開いたローカルディレクトリ(.devcontainer/devcontainer.json を含む)のパス。コンテナボリュームでClone Repositoryを使用する場合は未対応です。
${containerWorkspaceFolder} Any コンテナのワークスペースファイルがあるディレクトリ
${localWorkspaceFolderBasename} Any ${localWorkspaceFolder}パスのディレクトリ名。コンテナボリュームでClone Repositoryを使用する場合は未対応です。
${containerWorkspaceFolderBasename} Any ${containerWorkspaceFolder}パスのディレクトリ名。

Attached container configuration reference

Attached container configuration filesdevcontainer.json に似ていて、その一部をサポートしています。

Property Type 説明
workspaceFolder string VS Code がコンテナに接続する際に開くべきデフォルトのパスを設定します(これは多くの場合、コンテナ内でソースコードを見つけることができるボリュームマウントへのパスです)。デフォルトでは設定されていません(空のウィンドウが開かれます)。
extensions array コンテナの作成時に、コンテナ内にインストールされるべきエクステンションを指定するエクステンションIDの配列です。デフォルトでは[]が設定されます。
settings object デフォルトの settings.json の値を、コンテナ/マシン固有の設定ファイルに追加します。
forwardPorts array コンテナ内からローカルマシンにフォワードされるべきポートのリストです。
remoteEnv object コンテナ全体ではなく、VS Code(またはターミナルなどのサブプロセス)の環境変数を設定または上書きする名前と値のペアのセット。環境変数やpre-defined variables が使用できます。例: "remoteEnv": { "PATH": "${containerEnv:PATH}:/some/other/path" }
remoteUser string S Code がコンテナ内で(ターミナル、タスク、デバッギングなどのサブプロセスと一緒に)実行されるユーザをオーバーライドする。デフォルトでは、コンテナ全体が実行されているユーザー(多くの場合、root)になります。
postAttachCommand string,
array
VS Code がコンテナにアタッチされた後に実行されるコマンド文字列またはコマンド引数のリストです。複数のコマンドを実行するには、文字列の中で && を使用します。例えば、"yarn install""apt-get update && apt-get install -y curl" などです。配列構文 ["yarn", "install"] を使用すると、シェルを使用せずにコマンド(ここでは yarn )を直接起動します。デフォルトでは設定されていません。

Variables in attached container configuration files

attached container configuration files内で ${variableName} の形で変数が使用できます。

Variable Properties Description
${containerEnv:VAR_NAME} remoteEnv コンテナ内の環境変数 (この場合, VAR_NAME) を参照。例: "remoteEnv": { "PATH": "${containerEnv:PATH}:/some/other/path" }

devcontainer.jsonのマイルール(2021年版)

ここにはVSCodeのdevcontainer.jsonについてのマイルールをまとめています。

プロジェクトディレクトリ構成

proj/my-proj  ...<プロジェクトルートからマウントし、コンテナ内での作業ディレクトリ>
├── .devcontainer/
│   ├── build/  ...<ビルドに使用する環境のコンテナ>
│   │   ├── Dockerfile
│   │   └── library-scripts/
│   │       ├── common-debian.sh
│   │       └── docker-debian.sh
│   ├── devcontainer.json  ...<今回注目する設定>
│   └── docker-compose.override.yml  ...<VSCode時に上書きする設定>
├── deploy/
│   ├── docker-compose.yml  ...<通常の開発環境構築用>
│   └── web/ or db/ or etc/  ...<各種コンテナ>
│       └── Dockerfile
├── doc/  ...<ドキュメント配置>
└── src/  ...<ソース配置>
  • devcontainer.json.devcontainer/ ディレクトリに置く。
  • docker-compose.yml を使用し、コンテナの設定はできるだけcomposeに任せる。
    • VSCode時に上書きする設定を .devcontainer/docker-compose.override.yml に書く。
    • 相対パス基準はオリジナルの deploy/docker-compose.yml のディレクトリとなるので注意。
  • doc/,src/ などはプロジェクトルートからマウントされるため、コンテナ内からもアクセス可能。

devcontainer.json

// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.177.0/containers/docker-from-docker-compose
{
  "name": "my-proj",
  "dockerComposeFile": [
    "../deploy/docker-compose.yml",
    "docker-compose.override.yml"
  ],
  "service": "build",
  "workspaceFolder": "/workspace",

  // Use this environment variable if you need to bind mount your local source code into a new container.
  "remoteEnv": {
    "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
  },

  // Set *default* container specific settings.json values on container create.
  "settings": {},

  // Add the IDs of extensions you want installed when the container is created.
  "extensions": [],

  // Use 'forwardPorts' to make a list of ports inside the container available locally.
  // "forwardPorts": [],

  // Use 'postCreateCommand' to run commands after the container is created.
  // "postCreateCommand": "docker --version",

  // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
  "remoteUser": "vscode"
}

docker-compose.override.yaml

#: Remote Container拡張で使うComposeファイル
version: "3"

# Base path expects ../deploy/
services:
  build:
    build:
      context: ../.devcontainer/build
      dockerfile: Dockerfile
      args:
        # On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
        USER_UID: 1000
        USER_GID: 1000

    init: true
    volumes:
      # Forwards the local Docker socket to the container.
      - /var/run/docker.sock:/var/run/docker-host.sock
      # 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"

    # Uncomment the next four lines if you will use a ptrace-based debuggers like C++, Go, and Rust.
    cap_add:
      - SYS_PTRACE
    security_opt:
      - seccomp:unconfined

    # Uncomment the next line to use a non-root user for all processes.
    # user: vscode

    # Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
    # (Adding the "ports" property to this file will not forward from a Codespace.)

build/Dockerfile

本当は1から自分で書けるようになりたいけど、なんかうまくいかないから
公式のリスト のものを使用しています。
C言語はよく使うので、基本的にcppをベースに使います。

下記はこのサイトのビルドとFTPアップロードで使っているものです。

# Note: You can use any Debian/Ubuntu based image you want.
ARG VARIANT=debian-11
FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-${VARIANT}

# Setting the ENTRYPOINT to docker-init.sh will configure non-root access
# to the Docker socket. The script will also execute CMD as needed.
# ENTRYPOINT [ "/usr/local/share/docker-init.sh" ]
# CMD [ "sleep", "infinity" ]

# [Optional] Uncomment this section to install additional OS packages.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
    && apt-get -y install --no-install-recommends ncftp

ENV HUGO_VERSION=0.88.1
RUN curl -L https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.tar.gz | tar -zx -C /usr/local/bin/

Discussion