はじめに
コンテナを構築した後、アプリケーションを追加したりして、
「新たなポートを使って外部からコンテナにアクセスしたい!」 「でもコンテナを作り直したくない!」
となった時、コンテナを止めずにポートフォワード設定を追加する方法を書きます。 また、誤って設定してしまった時の設定削除方法も最後の方に記載しています。
Dockerのポートフォワードの設定
Dockerのポートフォワードの設定は、コンテナ起動時などに-pオプションを使って設定できますが、裏ではiptablesで実現されています。
そのため、今回のように稼働しているコンテナのポートを追加する時もiptablesのNATとFilteringの設定を編集します。
1. まずはコンテナのIPアドレスを確認する
設定を追加したいコンテナ名をhogeとすると、
$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' hoge
で確認できます。 普通は、 172.17.0.2 のようなIPアドレスになっています。
2. NAT設定
まずはNAT設定からです。
コンテナが稼働しているホストマシンのポートを--dport
で指定し、コンテナのIPアドレスとポートを --to-destination
で指定します。この時のIPアドレスは 上記1 で確認したアドレスになります。
下記の例は、ホストマシンの8001番ポートにアクセスした時に、コンテナ 172.17.0.2 の 8888 ポートに接続されるようにしたい時のコマンドです。8888はpython Jupyterのデフォルトポートです。
$ sudo iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 8001 -j DNAT --to-destination 172.17.0.2:8888
イメージ図:
図のように、ユーザがブラウザでJupyterに接続しようと「http://ホストマシンIPアドレス:8001」のURLにアクセスすると、リクエストはホストマシンに届いた後に、コンテナhogeの8888ポートにフォワードされ、Jupyterのプロセスへと到達する形になります。
3. Filtering設定
次はFilteringの設定です。
コンテナのIPアドレスを -d
で指定し、ホストマシンのポートを --dport
で指定します。
$ sudo iptables -A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8001 -j ACCEPT
2.のNATの設定だけでなく、Filteringの設定もしないと外部からのアクセスができませんので、忘れずに設定が必要です。
4. 設定できたか確認
最後に想定通りに設定されたかを確認します。
以下のコマンドでiptablesの現在の設定をファイルに保存できます。
$ sudo iptables-save > iptables.txt
保存したら、中身を表示して、想定通りのNATとFirtering設定になっているかどうかを確認してください。
もし想定と異なる設定をしてしまっていた場合は次の5.を確認ください。
5. 誤って設定した時の削除方法
NAT設定の削除方法
まずは間違っている設定の行番号を確認します。
$ sudo iptables -t nat -L --line-numbers
そして確認した行番号を指定して下記の削除コマンドを実行します。(X に行番号を入れます)
$ sudo iptables -t nat -D DOCKER X
Filtering設定の削除方法
こちらも同じく間違っている設定の行番号を確認します。
$ sudo iptables -L --line-numbers
確認した行番号を指定して下記の削除コマンドを実行します。(X に行番号を入れます)
$ sudo iptables -D DOCKER X
これで設定が削除されていますので、$ sudo iptables-save > iptables.txt
で設定を確認してみてください。
6. シェルスクリプトにして楽に設定できるようにしました
1〜4の手順をシェル化!
引数で ホストマシンのポート、コンテナ名、コンテナのポート の順で指定するようになっています。
#!/bin/bash if [ $# -ne 3 ]; then echo "引数は右記のように指定してください:host port, container name, container port" exit 1 fi host_port=$1 container=$2 container_port=$3 ip=`sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${container}` if [ $? -gt 0 ]; then echo 'cannot get IP address of ${container}' exit 1 fi echo 'IP Address is '${ip} echo 'host port = '${host_port}', container port = '${container_port} read -p 'ok? (yes/no): ' yn case ${yn} in yes) ;; no) echo 'abort.' ; exit ;; *) echo 'should yes or no' ; exit ;; esac # NAT sudo iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport ${host_port} -j DNAT --to-destination ${ip}:${container_port} if [ $? -gt 0 ]; then echo 'NAT設定でエラー発生' exit 1 fi # Filtering sudo iptables -A DOCKER -d ${ip}/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport ${container_port} -j ACCEPT if [ $? -gt 0 ]; then echo 'Filtering設定でエラー発生' exit 1 fi # save sudo iptables-save > iptables.txt echo 'iptables.txtに現在のiptablesの設定を保存'
参考文献
- 作者: Adrian Mouat,Sky株式会社玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/08/17
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Docker実践ガイド 第2版 (impress top gear)
- 作者: 古賀政純
- 出版社/メーカー: インプレス
- 発売日: 2019/02/18
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る