2017年5月13日土曜日

起動中のコンテナに対してホストのポートをバインドする方法

環境

  • CentOS 7.3.1611
  • docker 17.05

概要

例えば以下のような感じで起動してしまった場合に

  • docker run -d --name test nginx

80/tcp で動作するのはコンテナ内のみになるので localhost に curl などできません
普通はこの場合コンテナを削除して再生成するのですが、データを永続している場合などはデータが来てしまうので削除したくありません (本当はちゃんと永続して削除できるようにしておくのが正解ですが、、、)

そんな場合は起動中のコンテナに対してホストのポートにコンテナのポートをバインドする方法を紹介します

docker commit を使う

一旦別のイメージを作成して、そこから別のコンテナを起動する方法です

  • docker commit test new_nginx
  • docker run -d --name new_test -p 8080:80 new_nginx

で新しくコンテナを起動したら古いコンテナを削除します

  • docker stop test
  • docker rm test

一応動作していた状態のコンテナからホストにポートをバインドしたコンテナを新たに生成することができます

(失敗例) iptables を使う

失敗したんですが、載せておきます
docker run で -p オプションを指定すると iptables のルールにいろいろと追加されます
それと同じルールを追加できればアクセスできるのではと思いやってみました
動作中のコンテナの IP は 172.17.0.2 とします

まず iptables -nL で表示される

Chain DOCKER (3 references)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.2           tcp dpt:80

を追加します

  • iptables -A DOCKER -p tcp -d 172.17.0.2 --dport 80 -j ACCEPT

次に iptables -t nat -nL で表示される

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0
MASQUERADE  all  --  172.19.0.0/16        0.0.0.0/0
MASQUERADE  all  --  172.18.0.0/16        0.0.0.0/0
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:80

Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.0.2:80
  • iptables -t nat -A POSTROUTING -p tcp -d 172.17.0.2 --dport 80 -s 172.17.0.2 -j MASQUERADE
  • iptables -t nat -A DOCKER -p tcp -d 0.0.0.0/0 --dport 8080 -s 0.0.0.0/0 -j DNAT --to-destination 172.17.0.2:80

で追加はできます
これで 8080 ポートにアクセスしてみようとしたのですが、そもそも 8080 ポートが LISTEN していないのでダメでした (当然と言えば当然)
試しに -p ポートで正しく動作しているときに 8080 ポートが何のプロセスで動作しているか確認したところ docker-pr というプロセスが 8080 で動作していました
なので、iptables を使う場合は同じようにプロセスもどうにかして起動させる必要があると思います

最後に

起動中のコンテナのポートをホストにバインドする方法を紹介しました
結果的には新しいコンテナを作ることで解決しましたが、本当は起動中のコンテナでやりたいところです
いろいろ調べてみたのですが、現状その方法はないかなと思います

確かにコンテナの概念的にも作り直せばいいだけなので、既存のコンテナの設定を変更できる必要はないのですがまぁできたら便利かなとも思います

0 件のコメント:

コメントを投稿