LoginSignup
7
7

More than 3 years have passed since last update.

VSCode Remote Containers で --privileged と /sbin/init を渡したコンテナで開発する方法

Last updated at Posted at 2020-11-15

はじめに

VSCode Remote Containers を使って開発する場合、Dockerfile を書いて「Reopen in Container」とすると Docker コンテナが起動しますが、この時 VSCode が docker run を実行します。
このため、何も気にせず公式の手順などを参考に起動すれば、--privileged オプションを付加できず、ENTRYPOINT に /sbin/init も渡せないため、コンテナで systemctl を実行できません。
※実行すると「Failed to get D-Bus connection: Operation not permitted」と表示されエラーとなります。
※このあたりの仕組みについては、既に「CentOS 7のDockerコンテナ内でsystemdを使ってサービスを起動する」などの記事で語られているため、本記事では割愛します。

本記事では、題記の通り、VSCode Remote Containers で使うコンテナで、docker run--privileged/sbin/init を渡すための調査経緯と、実現した方法を紹介します。

0. 序章: 調査編

まずは正攻法で行けないかと調査してみると、設定ファイルの devcontainer.json には「runArgs」というパラメータがあり、ここで docker run する時のパラメータを追加できることが分かりました。
参考: devcontainer.json reference

しかし、この方法では --privileged を追加できても、--entrypoint を上書きできませんでした。
VSCode Remote Containers で 「Reopen in Container」 して docker コンテナを起動すると、docker run の引数に --entrypoint /bin/sh <各自のDocker Image> -c echo Container started ; trap "exit 0" 15; while sleep 1 & wait $!; do :; done が付加されてしまい、devcontainer.json に書いたパラメータではこれを上書きできない仕様となっているようです。

起動時にどんなコマンドが流れているかは、起動中に表示される以下ポップアップのリンクを押すことで見えるログから把握できます。
image.png

また、次のリンク先で解説されているように、Dockerfile に書いた ENTRYPOINT と CMD よりも、引数で指定された --entrypoint が優先されるため、Dockerfile に書いても上書きできません。
VSCode が必ず docker run に引数で --entrypoint を付加するためこれが最優先されてしまいます。
参考: Dockerfileによるビルド

1. 実現手順

そこで、以下の手順を辿ることにしました。

(1) まずは手順通り 「Reopen in Container」 を実行

この手順により Docker イメージがビルドされ、コンテナが起動します。
この時、先ほどのポップアップのリンクからログを開き、ログの中から以下のコマンドを探してコピーします。

docker run -a STDOUT -a STDERR --mount type=bind,source=<各自の環境のパス>,target=<各自の環境のパス>,consistency=cached -l vsch.quality=stable -l vsch.remote.devPort=0 -l vsch.local.folder=<各自の環境のパス> --entrypoint /bin/sh <各自のDocker Image> -c echo Container started ; trap "exit 0" 15; while sleep 1 & wait $!; do :; done

(2) VSCode でコンテナとの接続を解除

(1) で起動したコンテナは --privileged されていませんので、VSCode で一旦接続を解除します。

(3) コピーしたコマンドを一部変更

コピーしたコマンドに --privileged を追記し、--entrypoint を書き換えます。

docker run -a STDOUT -a STDERR --mount type=bind,source=<各自の環境のパス>,target=<各自の環境のパス>,consistency=cached -l vsch.quality=stable -l vsch.remote.devPort=0 -l vsch.local.folder=<各自の環境のパス> --privileged --entrypoint /sbin/init <各自のDocker Image>

(4) 上記コマンドをローカルのターミナルで実行

実行すると (3) のオプション通りに docker コンテナが起動します。
docker ps で起動状態を確認できます。

(5) VSCodeで「Attach to Running Container」を実行

次に、(4) で起動したコンテナを VSCode にアタッチします。
まず、以下画像のように「Attach to Running Container」を選びます。

image.png

次に起動中のコンテナを選ぶ画面で、コンテナを選ぶだけです。
image.png

ここまでで、VSCode からコンテナに接続して、開発環境を開けます。

2. 動作確認

VSCode でコンテナのターミナルを開いて systemctl を打ってみます。

bash-4.2# systemctl
  UNIT                          LOAD   ACTIVE     SUB       DESCRIPTION
  dev-vda1.device               loaded activating tentative /dev/vda1
  -.mount                       loaded active     mounted   /
  dev-hugepages.mount           loaded active     mounted   Huge Pages File System
  dev-mqueue.mount              loaded active     mounted   POSIX Message Queue File Syste
  etc-hostname.mount            loaded active     mounted   /etc/hostname
  etc-hosts.mount               loaded active     mounted   /etc/hosts
(以下長いので略)

このようにエラーが解消され、打てるようになっています。

最後に

このように、起動したコンテナに VSCode から接続する手順を踏むことで、VSCode Remote Containers でも systemctl が実行できるようになります。
今回、少々面倒ですが docker build までは VSCode で実行して、各種オプションが含まれる docker run コマンドを VSCode のログから発掘する方が早いと判断しました。
(もっと良い方法があるのかもしれませんが、もし見つかったら追記します)

なお --privileged はその名の通り特権という意味なので、ご利用は計画的に、とすべきです。

参考文献

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7