🌐

DevContainer(Docker Compose)をTailnet(Tailscale)に接続するには

2024/02/25に公開

公式のDockerで使用するガイドを参考に DevContainer をTailnetに接続できるようにしました。

これにより、Tailnet内の他のデバイスから、DevContainerで起動したサービスへ接続できるようになります。

なお、DevContainerからTailnet内の別のデバイスに接続したい場合は、通常ホストのIPアドレスを共有するので、ホスト側でTailnetに接続していれば、その権限で接続できるため、特別な対応は不要です。
本記事は、Tailnet内の他のデバイスから、DevContainer(Dockerコンテナ)に直接アクセスさせたい場合の話です。
たとえばローカル環境で開発中のサービスに、スマートフォンから接続して動作確認したい場合などに活用できます。

手順

サーバや他のデバイスへのTailscaleのセットアップは完了しているものとします。

  1. コンテナで利用する ACL tag を作成する
  2. AuthKeyを取得する
  3. .devcontainer/docker-compose.yml を変更する
  4. DevContainerを起動
  5. DevContainerで起動したサービスへの接続をACLで許可する

Tailscale ではデバイスの所有者は ユーザー( yourname@xxxx.xxx ) か タグ のどちらかで、両方を設定することはできません。(ユーザーが管理者として設定されているデバイスに対してタグを設定すると、デバイスの管理者はユーザーからタグに変化します。)

タグを使用することで、そのデバイスは特定のユーザーに関連付けずにTailnetで管理できます。
今回 Tailnet に container タグを使用して接続することにします。

1. コンテナで利用する ACL tag を作成する

タグを使用するには、まず Admin console > Access controls で、 タグ所有者("tagOwners:")を追記します。

タグ所有者を記載することで、そのタグをデバイスにタグを付与することができるのは誰(どのユーザー)か?を指定できます。

今回は TailnetのAdminが container タグをデバイスに付与できるようにします。

"tagOwners": {
	"tag:container": ["autogroup:admin"],
},

https://tailscale.com/kb/1068/acl-tags

2. AuthKeyを取得する

タグが作成出来たら、そのタグを使ってTailnetにデバイスを接続するための認証キーを作成します。
Admin console > Settings > Keys で、『Generate auth key...』をクリックし、以下のように入力し、『Generate key』をクリックします。
生成できた AuthKey は控えておきます。

項目 備考
Reusable Yes どちらでもいい。Yes にすると複数のデバイスで利用できる。例えばデスクトップとラップトップでそれぞれ起動するとか。
Expiration 1 day いつまでこのキーを使ってデバイスを登録できるか。登録済みのデバイスは再接続にAuthKeyは使用しないので、すぐに登録する、かつ Ephemeral No なら短いほうがいい。Ephemeral Yes なら、切断の度に登録しなおす必要があるので、短すぎると使いにくい。
Tags Yes tag:container ACLで自身が所有者として設定されているタグのみ指定可能

AuthKeyと「キー」

Tailnetにデバイスを登録すると、デバイスの「キー」の有効期限が6ヵ月に設定されます。
この「キー」はAuthKeyとは関係なく、期限というのもAuthKeyの期限とは関係ありません。
AuthKeyの期限を超過しても、登録済みのデバイスなら、Key expiryまで接続できます。

Key expiry

3. .devcontainer/docker-compose.yml を変更する

公式のDockerイメージがあるので、 そちらを Compose に追加します。

tailscale-app が Tailnet に接続する際に、2で取得した AuthKey を使用します。これにより、DevContainer は tag:container の管理下のデバイスとして、自動的に Tailnet に参加できます。

.devcontainer/docker-compose.yml
version: '3'

services:
  app:
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile
    volumes:
      - ../..:/workspaces:cached
    # Overrides default command so things don't shut down after the process ends.
    command: sleep infinity
# ここから下を追加
    depends_on:
      - tailscale-app
    network_mode: service:tailscale-app

  tailscale-app:
    image: tailscale/tailscale:latest
    hostname: tailscale-app
    env_file: .env.tailscale-app
    environment:
      - TS_STATE_DIR=/var/lib/tailscale
    volumes:
      - tailscale-data:/var/lib/tailscale
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - net_admin
      - sys_module
    restart: unless-stopped

volumes:
  tailscale-data:
    driver: local
.devcontainer/.env.tailscale-app
TS_AUTHKEY=2で取得したAuthKey
.gitignore
/.devcontainer/.env*
!/.devcontainer/.env*.sample

network_mode: service:tailscale-app

network_mode: を使用すると、サービスのネットワークモードを指定できます。network_mode: service:tailscale-app に設定すると、app サービスは tailscale-app サービスのネットワーク名前空間を共有します。これにより、app サービスは tailscale-app サービスの IP アドレスを使用できるので、Tailnetの他のデバイスと通信することができます。

TS_STATE_DIR

Tailnetへの参加状態が格納されるディレクトリで、コンテナの再起動・再構築後も保持する必要があるので、永続化ボリュームを指定します。

4. DevContainerを起動

指定したキーを使ってTailnetに接続できました。

  • tag:container 管理下であること
  • 有効期限が無期限であること

を確認できます。

Machines

5. DevContainerで起動したサービスへの接続をACLで許可する

Tailnet上の他のデバイスから、4で起動したサービスへの接続を許可します。

Tailnet上のすべてのデバイスからの接続を許可する

	"acls": [
		{
			"action": "accept",
			"src":    ["*"],
			"dst":    ["tag:container:*"],  // tag:container のすべてのポートを許可
		},
	],

特定のユーザーのデバイスからのみ許可する

	"acls": [
		{
			"action": "accept",
			"src":    ["yourname@xxxx.xxx"],
			"dst":    ["tag:container:*"],
		},
	],

特定のタグを割り当てたデバイスからのみ許可する

	"acls": [
		{
			"action": "accept",
			"src":    ["tag:my-group"],
			"dst":    ["tag:container:*"],
		},
	],

接続可能なTCPポート番号を指定する

	"acls": [
		{
			"action": "accept",
			"src":    ["*"],
			"dst":    ["tag:container:3000"],  // tcp 3000
		},
	],

まとめ

公式の手順に従って、かんたんにコンテナ環境をTailnetに接続できることがわかりました。
Tailnetに接続できることで、ネットワーク的に離れていても、安全に接続させることができます。

タケユー・ウェブ株式会社

Discussion