docker固定ＩＰ

# やっぱりＩＰアドレスを固定したい
最初は特にＩＰを固定するなんて要らないじゃない？とうっすら思っていました。

## ローカルでのイメージ構築
運用するではなく、ローカルＰＣでdockerイメージを作ってる段階だと特に固定IPの必要性を感じていませんでした。
```boot2docker``` を使用し、コンテナ起動時にポートをマップできるのでポートごとにコンテナを指定すれば特にIPが何であろうとあまり問題にはなりません。

![IMG01.jpg](https://qiita-image-store.s3.amazonaws.com/0/12727/db339497-9778-838f-8f42-facdb2b46db4.jpeg)

この図のように ```contener1``` は ```http://boot2docker:8080/``` とアクセスすればいいし ```contener2``` は ```http://boot2docker:8081/``` とすればアクセスできたのでここではあまり必要性を感じていません。もしくは同時に起動する必要もないので入れ替わりで起動すれば 80 → 80ポートに割り当ててもいいぐらいですね。

## 実際に運用するとなると
実際に運用しようとして「あれ？」と思うようになります。
外に公開しているサーバーにあんまりポートをいくつも開けるのよくないんじゃない？ :fearful: 

![IMG02.jpg](https://qiita-image-store.s3.amazonaws.com/0/12727/d4d24b6f-cf23-004b-092f-fbcb8e55a1a5.jpeg)

```container1``` も ```container2``` 80番ポートが良い。
そしたら ```apache``` か ```nginx``` で同じ80ポートで受け付けて、それぞれのコンテナへ、でもコンテナは起動するたびに **IPが変わる** ので ```nginx``` 等の設定ファイルに書けない。
ローカルと同じようにポートを割り当てれば？
でもこれって・・・ ```http://domain1/``` でもアクセスできるけど、 ```http://VPS:8080/``` でもアクセスできてしまう．．．

## そして固定ＩＰへ
やっぱりＩＰを固定して、コンテナはポートを割り当てないのが良い。

![IMG03.jpg](https://qiita-image-store.s3.amazonaws.com/0/12727/bfacf096-7cb9-2233-c086-2d23815c2fa6.jpeg)

理想はこんな感じが良い。ただこれには起動時に変わってしまうコンテナのＩＰを調べて ```nginx``` の設定に反映させて再起動とか？ ```docker``` の ```--link``` などを使用して起動など試しましたが起動の順番とかどうもややこしくなる。
ここまできて **固定ＩＰが欲しい** と思うようになります。

どうせなら標準であってほしい、これだけググると設定の仕方が書かれた記事があるのに・・・

```docker run --ipv4addr=172.17.240.1 ...```

とかで設定できればいいのに・・・できないですね、はい・・・


## 実際の固定ＩＰ設定
ググるといろいろやり方があるのでいくつか試しました。
シンプルにしたいのが目的なので別ソフトを入れるようなものは最初からあきらめます。

通常 ```docker``` インストールすると ```docker0``` というイーサネットが作成され ```172.17.0.0/16``` コンテナ側は ```eth0```へ空いてる順番に小さい番号から割り当てられてるようです。

### 設定ファイルを作成して固定ＩＰ
固定ＩＰの設定ファイルを作成し、起動時にネットワーク再起動。
小さい数字のほうから割り当てられるので大きい値で ```172.17.240.1``` ぐらいから固定ＩＰを当てていきます。
```docker0``` 自体は ```172.17.42.1``` になっているのでそこまではＩＰが振られないということ？

```text:ifcfg-eth0
DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=none
IPADDR=172.17.240.1
PREFIX=16
GATEWAY=172.17.42.1
DEFROUTE=yes
IPV4_FAILURE_FATAL=yes
IPV6INIT=no
ARPCHECK=no
```

最初このファイルをイメージビルド時にコピーしてたのですがコンテナ実行時にＩＰを割り当てるようなのでビルド時の設定はすべて無視されました。

仕方ないのでコンテナ起動時にファイルをコピーしてネットワークを再起動。

```text:Dockerfile
FROM centos:6.6

WORKDIR /root/

COPY ifcfg-eth0 /root/

ENTRYPOINT \
        /bin/cp -f /root/ifcfg-eth0 /etc/sysconfig/network-scripts/ && \
        service network restart && \
        /bin/bash
```

そしてネットワーク関連の操作をするときは以下のように ```--privileged``` をつけないとネットワーク再起動時にエラーになってしまいます。

[DockerのMakefile](http://qiita.com/takara@github/items/a0a295d265ab5ff43ddc)テンプレートの以下の部分だけ差し替えます。

```text:Makefile
NAME=ipcentos
VERSION=1.0.0

start:
    docker run -itd \
        --privileged \
        --name $(NAME) \
        $(NAME):$(VERSION) bash
```

起動してＩＰの確認

```
$ make build
$ make start
$ make attach
root@abcdefghij01:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:05
          inet addr:172.17.240.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:5/64 Scope:Link
				:
				:
```

起動後ホスト側からＩＰの情報をとりますが実際と違う値、 ```docker``` 側の情報では ```172.17.0.5``` で割り当てたけど起動時にIPを変えられて正しく表示されない状態ですが ```ping ``` コマンドを叩くとちゃんと返ってくる。


```
$ docker inspect --format="{{ .NetworkSettings.IPAddress }}" ipcentos
172.17.0.5

$ ping 172.17.240.1
PING 172.17.240.1 (172.17.240.1) 56(84) bytes of data.
64 bytes from 172.17.240.1: icmp_seq=1 ttl=64 time=0.087 ms
64 bytes from 172.17.240.1: icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from 172.17.240.1: icmp_seq=3 ttl=64 time=0.054 ms
64 bytes from 172.17.240.1: icmp_seq=4 ttl=64 time=0.055 ms
```


### 設定ファイル無しで固定ＩＰ
設定ファイルの方法だと ```centos``` だと変更できるけど ```debian``` などに変わるとそれぞれの方法が違うようなので同じようにいかない。それではやり方が変わってしまうので別の方法を探す。

それで見つかったのが次の方法。起動時にＩＰを追加する。

ENTRYPOINTで先ほどコピー部分をやめて次のように書き直す。

```text:Dockerfile
				:
				:
ENTRYPOINT \
        ip addr add 172.17.240.1/16 dev eth0 && \
        /bin/bash
```

起動後確認。

すると ```172.17.0.8/16``` と ```172.17.240.1/16``` のＩＰが割り当てられている

```
$ make attach
# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:08
          inet addr:172.17.0.8  Bcast:0.0.0.0  Mask:255.255.0.0

				:
				:
# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN

				:
				:

19: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP

				:
				:

    inet 172.17.0.8/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet 172.17.240.1/16 scope global secondary eth0
       valid_lft forever preferred_lft forever

				:
				:
```

設定ファイルも要らないので自分にはこれが一番合っているかもしれない。
```debian``` でも同じようにできることを確認。
コマンド一つで固定ＩＰを追加できるのはいいですね。

設定ファイルがあってもなくても ```docker``` 側へは固定ＩＰ情報は伝わっていないですね。[^1]
設定ファイルがないほうは、```docker```側で当てたＩＰが残っていますね。[^2]

そのうち起動時のオプションが正式になりますよね・・・きっと・・・

## 参考サイト
- [(ヽ´ω`) < DockerのOperation not permittedとの戦争](http://www.tsugihagi.net/entry/2014/10/05/083120)
- [Docker単体でコンテナに固定IPを設定する](https://gist.github.com/hayajo/865559753d28e6502242)

[^1]: 自分で設定してるのでいいのですが
[^2]: これも使用されないだけで、消すとしてもＩＰを調べてとなると微妙ですね。