DevContainer(Docker Compose)をTailnet(Tailscale)に接続するには
公式のDockerで使用するガイドを参考に DevContainer をTailnetに接続できるようにしました。
これにより、Tailnet内の他のデバイスから、DevContainerで起動したサービスへ接続できるようになります。
なお、DevContainerからTailnet内の別のデバイスに接続したい場合は、通常ホストのIPアドレスを共有するので、ホスト側でTailnetに接続していれば、その権限で接続できるため、特別な対応は不要です。
本記事は、Tailnet内の他のデバイスから、DevContainer(Dockerコンテナ)に直接アクセスさせたい場合の話です。
たとえばローカル環境で開発中のサービスに、スマートフォンから接続して動作確認したい場合などに活用できます。
手順
サーバや他のデバイスへのTailscaleのセットアップは完了しているものとします。
- コンテナで利用する ACL tag を作成する
- AuthKeyを取得する
- .devcontainer/docker-compose.yml を変更する
- DevContainerを起動
- DevContainerで起動したサービスへの接続をACLで許可する
Tailscale ではデバイスの所有者は ユーザー( yourname@xxxx.xxx
) か タグ のどちらかで、両方を設定することはできません。(ユーザーが管理者として設定されているデバイスに対してタグを設定すると、デバイスの管理者はユーザーからタグに変化します。)
タグを使用することで、そのデバイスは特定のユーザーに関連付けずにTailnetで管理できます。
今回 Tailnet に container
タグを使用して接続することにします。
ACL tag を作成する
1. コンテナで利用するタグを使用するには、まず Admin console > Access controls で、 タグ所有者("tagOwners:"
)を追記します。
タグ所有者を記載することで、そのタグをデバイスにタグを付与することができるのは誰(どのユーザー)か?を指定できます。
今回は TailnetのAdminが container
タグをデバイスに付与できるようにします。
"tagOwners": {
"tag:container": ["autogroup:admin"],
},
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まで接続できます。
3. .devcontainer/docker-compose.yml を変更する
公式のDockerイメージがあるので、 そちらを Compose に追加します。
tailscale-app
が Tailnet に接続する際に、2で取得した AuthKey を使用します。これにより、DevContainer は tag:container
の管理下のデバイスとして、自動的に Tailnet に参加できます。
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
TS_AUTHKEY=2で取得したAuthKey
/.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
管理下であること - 有効期限が無期限であること
を確認できます。
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