Docker を使って隔離 network を利用する
こんにちは、疑り深いホシイです。
複数の機能を組み合わせてシステムを構築するとき、それぞれの機能同士の通信は必要だがその他の通信は禁止したいということはよくあります。たとえば…
- 開発中のプログラムで、想定している以外の通信が無いことを確認したい
- 公開されているソフトウェア (OSS や container image 等) をちょっと試してみたいが、その素性が完全には確認できていないので、外部との通信を遮断した環境で実行してみたい
特に後者のような用途では、実行環境ごと隔離できると何かと便利です。今回は Docker を使ってやってみたいと思います。
Docker の実行 option を使用する
docker run
するときに、--net=none
をつけるだけで、container は network から隔離されます。
参考: None network driver
❯ docker run -it --rm --entrypoint=ash --net=none alpine
/ # ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN qlen 1000
link/tunnel6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
単に実行するだけでよければ、これがかんたん便利です。
ただこれだと、host からも接続ができなくなるので web app などの動作確認はすこし不便です。
Docker Compose で隔離した network を使用する
システム内に複数の機能があり、それぞれは通信可能にしたいといった場合は単純にはいきません。こういったものに備え、Docker Compose を使用して、テンプレをつくっておくと便利そうです。
以下の compose.yaml
で、nginx の container をふたつ起動し、お互いは専用の network で通信可能であるものの、片方の nginx container は専用 network 以外 からは隔離されている状態をつくります。これで、host からもブラウザ等で確認ができるようになります。
version: '3.8'
services:
# 外との通信が可能な container
nginx_e:
image: nginx
ports:
- "127.0.0.1:8080:80" # host 側から接続できるようにする
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro # nginx_i への proxy 設定
networks:
- net_e
- net_i
# 内部通信専用 container
nginx_i:
image: nginx
# ports:
# - "127.0.0.1:8081:80" # 接続できないので書いても意味はない
networks:
- net_i
networks:
net_i:
name: net_i
internal: true
net_e:
name: net_e
一段目の nginx には単に reverse proxy させるため、以下の設定を mount させておきます。
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://nginx_i/;
}
}
設定のキモは networks
下の internal: true
で、document Networks top-level elements > Internal には以下のように書かれています。隔離した network をつくるためのものです。
By default, Compose provides external connectivity to networks. internal, when set to true, allows you to create an externally isolated network.
また、記事の趣旨とはじゃっかん離れますが、 ports
は 127.0.0.1:8080:80
のように IP address つきで指定しています。IP address を省略して 8080:80
などとしても接続可能になりますが、この場合 0.0.0.0:8080:80
という意味になり、host とおなじ network にいる他の端末からも接続可能になります。安全ではない network を使うノマド族の皆様はご注意ください。(参考)
上記のふたつの file を用意して、(いつもどおり) 以下のようにして実行します。
docker compose up
network 構成はこのようになっています。
一段目の nginx には host から http://127.0.0.1:8080 で接続でき、reverse proxy により二段目の nginx に request が行きます。host から二段目の nginx に直接接続できないことも確認できると思います。また、docker exec
して二段目の nginx container の shell に入れば、internet 含む外部 network にも出ていけないことが確認できると思います。
これでテンプレとしては機能しそうです!あとは、二段目の nginx
image を検証したいものに差し替えれば、いつでも好きな container image を安全に検証できそうです。
まとめ
今回は、隔離環境を用意することを目的に Docker network を使って便利テンプレをつくってみました。仮想化ツールが熟成して、様々なタスクがかんたんに実現できることがうれしい限りです。かたや、仮想化環境のネットワークは複雑になりがちなので、考慮漏れなどの穴がないように注意していきたいですね。