はじめに
dockerのコンテナを外部ネットワークに公開する方法のメモ
dockerのコンテナは基本的にはプライベートネットワーク(デフォルトで172.17.0.0/16)上に構築されるようで、コンテナから外部へのネットワーク接続は仮想ブリッジ(docker0)経由で通信することができますが、逆に外部からコンテナへの接続は(デフォルトでは)できないようです。
色々ググってみてそれらしい記事を参考に試してみるもうまくいかず。
※仮想ブリッジをNICと接続する方法とか試したんですが、動きませんでした・・・。
理由は調べた気がしますが、忘れましたw
dockerがNATの設定をおかしくさせてたような?
なので、ここは純粋にNICへセカンダリIPアドレスを割り振り、firewalldでDNATする方法で解決します。
ちなみに、DNATは Destination Network Address Translation の略だそうです。
環境
環境 | バージョン |
---|---|
OS | CentOS Linux release 7.2.1511 (Core) |
docker | 1.12.5 |
環境構築
まずはサービス公開用のブリッジを作成します。
これは最初に設定しておけば、以降は行う必要はありません。
ここでは、ネットワーク 172.18.0.0/16 で、ブリッジのIPアドレスは 172.18.0.1、ブリッジ名をdocker1、docker上のネットワーク名をserverとしました。
# docker network create --driver bridge --subnet 172.18.0.0/16 --gateway 172.18.0.1 --opt "com.docker.network.bridge.name"="docker1" server
firewalldのzone設定を行います。
これも最初に設定するものです。
ここではdocker1をtrustedゾーンに配置します。
ポート開けの設定が面倒なのでtrustedで横着してますw
# firewall-cmd --zone=trusted --change-interface=docker1
次にNICにセカンダリIPアドレスを割り振ります。
ここから、公開するコンテナごとに必要な設定になります。
ここでは、enp0s3インターフェイスに192.168.0.15を追加しました。
# nmcli connection modify enp0s3 +ipv4.addresses "192.168.0.15/24"
次にDNATを設定します。
セカンダリIPアドレス 192.168.0.15 から、例えば 172.18.0.2 にアドレス変換する場合は下記となります。
# firewall-cmd --permanent --direct --add-rule ipv4 nat PREROUTING_direct 0 -d 192.168.0.15 -j DNAT --to 172.18.0.2
# firewall-cmd --reload
※間違って--directの設定をしてしまった場合、/etc/firewalld/direct.xmlに設定が永続化されているため、ここをいじれば修正できます。
コンテナを作成します。
ネットワークに server を指定、IPアドレスに先ほどの 172.18.0.2 を指定します。
ここでは、nginxサービスをインストールするCentOS7コンテナを作成&起動してみます。
その他のオプションはお好みで。
# docker run --restart always --cap-add=SYS_ADMIN -d --net server --ip 172.18.0.2 --name nginx centos:7 /sbin/init
コンテナが起動するのでbashコマンドで接続します。
# docker exec -it nginx /bin/bash
接続出来たらnginxをインストールします。
# rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# yum -y install nginx
# systemctl enable nginx
# systemctl start nginx
外部ネットワークから http://192.168.0.15 が開けばOKです。
なお、nginxコンテナを再起動すると/var/log/nginxディレクトリが無くなっていてサービスの起動に失敗してしまいます。
対処方法ご存知の方、コメントください。
暫定対応
ひとまず、再起動がうまくいかないのは実用に耐えられないので、Data Volumeをマウントして強制的に/var/log/nginxを作っています。
# docker run --restart always --cap-add=SYS_ADMIN -d --net server --ip 172.18.0.2 --name nginx -v /var/log/nginx centos:7 /sbin/init