Dockerコンテナ内の名前解決への /etc/hosts の影響


# 結論
- コンテナ内の `/etc/hosts` のみがコンテナ内での名前解決に影響する
    - コンテナの外（ホスト）の `/etc/hosts` は無関係
- curl や ping は `/etc/hosts` の設定が反映されるが、 nslookup や dig は `/etc/hosts` を見ない
- コンテナ内の `/etc/hosts` への設定は docker の機能で可能
    - docker-compose の `extra_hosts` 設定
    - docker の `--add-host` パラメータ

# 環境

- Windows 10 Home
- docker-machine 0.14.0

## docker
```bash
$ docker --version
Docker version 18.03.0-ce, build 0520e24302
```

## docker-compose
```bash
$ docker-compose --version
docker-compose version 1.20.1, build 5d8c71b2
```

## docker-machine
```bash
$ docker-machine --version
docker-machine.exe version 0.14.0, build 89b8332
```

## docker-machine 内の docker 
```bash
$ docker-machine ssh default docker --version
Docker version 18.09.0, build 4d60db4
```

## コンテナ
`centos:7.6`

### `docker-compose.yml`

```yaml
version: '3'

services:
  centos:
    image: centos:7.6.1810
    tty: true
```

### 準備
nslookup コマンドを使えるようにするため `bind-utils` をインストール

```bash
yum install -y bind-utils
```

# 検証

以下のパターンを確認する

1. 初期状態
1. コンテナ内の `/etc/hosts` を変更する場合
1. docker-machine 内の `/etc/hosts` を変更する場合
1. ホストの `/etc/hosts` を変更する場合
1. コンテナ作成時に `extra_hosts` オプションを指定する場合

## 初期状態
結果: **`aaa.example.com` は名前解決できない（存在しないため）**


### nslookup
```
[root@d327ebe36ed9 /]# nslookup aaa.example.com
Server:         127.0.0.11
Address:        127.0.0.11#53

** server can't find aaa.example.com: NXDOMAIN
```

### ping
```bash

[root@d327ebe36ed9 /]# ping aaa.example.com
ping: aaa.example.com: Name or service not known
```

### curl
```
[root@d327ebe36ed9 /]# curl -v aaa.example.com
* Could not resolve host: aaa.example.com; Unknown error
* Closing connection 0
curl: (6) Could not resolve host: aaa.example.com; Unknown error
```

## コンテナ内の `/etc/hosts` を変更する場合
結果: **nslookup では名前解決できないが、 pingやcurlなどでは名前解決されている**

### `/etc/hosts` を変更
`aaa.example.com` -> `127.2.3.4` に名前解決されるように設定

```bash
[root@d327ebe36ed9 /]# echo "127.2.3.4 aaa.example.com" | tee -a /etc/hosts
127.2.3.4 aaa.example.com
```

```bash
[root@d327ebe36ed9 /]# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.19.0.2      d327ebe36ed9

127.2.3.4 aaa.example.com
```

### 動作確認
#### ping: 名前解決されてる
```bash
[root@d327ebe36ed9 /]# ping aaa.example.com
PING aaa.example.com (127.2.3.4) 56(84) bytes of data.
64 bytes from aaa.example.com (127.2.3.4): icmp_seq=1 ttl=64 time=0.027 ms
64 bytes from aaa.example.com (127.2.3.4): icmp_seq=2 ttl=64 time=0.040 ms
64 bytes from aaa.example.com (127.2.3.4): icmp_seq=3 ttl=64 time=0.042 ms
64 bytes from aaa.example.com (127.2.3.4): icmp_seq=4 ttl=64 time=0.043 ms
^C
--- aaa.example.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3067ms
rtt min/avg/max/mdev = 0.027/0.038/0.043/0.006 ms
```

#### curl: 名前解決されてる
ただし、名前解決されたIPでWebサーバーは動いていないのでcurl自体は失敗する

```bash
[root@d327ebe36ed9 /]# curl -v aaa.example.com
* About to connect() to aaa.example.com port 80 (#0)
*   Trying 127.2.3.4...
* Connection refused
* Failed connect to aaa.example.com:80; Connection refused
* Closing connection 0
curl: (7) Failed connect to aaa.example.com:80; Connection refused
```

#### nslookup: 名前解決されてない
nslookupは そもそも `/etc/hosts` を見ない

[dns - Why is my /etc/hosts file not queried when nslookup tries to resolve an address? - Ask Ubuntu](https://askubuntu.com/questions/627906/why-is-my-etc-hosts-file-not-queried-when-nslookup-tries-to-resolve-an-address)

```bash
[root@d327ebe36ed9 /]# nslookup aaa.example.com
Server:         127.0.0.11
Address:        127.0.0.11#53

** server can't find aaa.example.com: NXDOMAIN
```

## docker-machine 内の `/etc/hosts` を変更する場合
結果: **`aaa.example.com` は名前解決できない（ping, curlでも不可）**

### `/etc/hosts` を変更
`aaa.example.com` -> `127.2.3.4` に名前解決されるように設定

`/etc/hosts` の変更には root 権限が必要なため、 `sudo` が必要

```bash
docker@default:~$ echo "127.2.3.4 aaa.example.com" | tee -a /etc/hosts
tee: /etc/hosts: Permission denied
127.2.3.4 aaa.example.com
```
```bash
docker@default:~$ echo "127.2.3.4 aaa.example.com" | sudo tee -a /etc/hosts
127.2.3.4 aaa.example.com
```

```bash
docker@default:~$ cat /etc/hosts
127.0.0.1 default localhost localhost.local

# The following lines are desirable for IPv6 capable hosts
# (added automatically by netbase upgrade)

::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

127.2.3.4 aaa.example.com
```

### 動作確認（コンテナ内）
#### ping: 名前解決されてない
```bash
[root@d327ebe36ed9 /]# ping aaa.example.com
ping: aaa.example.com: Name or service not known
```

#### curl: 名前解決されてない
```bash
[root@d327ebe36ed9 /]# curl -v aaa.example.com
* Could not resolve host: aaa.example.com; Unknown error
* Closing connection 0
curl: (6) Could not resolve host: aaa.example.com; Unknown error
```

#### nslookup: 名前解決されてない
```bash
[root@d327ebe36ed9 /]# nslookup aaa.example.com
Server:         127.0.0.11
Address:        127.0.0.11#53

** server can't find aaa.example.com: NXDOMAIN
```



## ホストの `/etc/hosts` を変更する場合
結果: **`aaa.example.com` は名前解決できない（ping, curlでも不可）**

### /etc/hosts を変更
`aaa.example.com` -> `127.2.3.4` に名前解決されるように設定

Windowsの場合は `C:\Windows\System32\drivers\etc\hosts` に `127.2.3.4 aaa.example.com` を追記

```
# localhost name resolution is handled within DNS itself.
# 127.0.0.1       localhost
# ::1             localhost


127.2.3.4 aaa.example.com
```

### 動作確認（コンテナ内）
#### ping: 名前解決されてない
```bash
[root@d327ebe36ed9 /]# ping aaa.example.com
ping: aaa.example.com: Name or service not known
```

#### curl: 名前解決されてない
```bash
[root@d327ebe36ed9 /]# curl -v aaa.example.com
* Could not resolve host: aaa.example.com; Unknown error
* Closing connection 0
curl: (6) Could not resolve host: aaa.example.com; Unknown error
```

#### nslookup: 名前解決されてない
```bash
[root@d327ebe36ed9 /]# nslookup aaa.example.com
Server:         127.0.0.11
Address:        127.0.0.11#53

** server can't find aaa.example.com: NXDOMAIN
```


## コンテナ作成時に `extra_hosts` オプションを指定する場合
結果: **nslookup では名前解決できないが、 pingやcurlなどでは名前解決されている**

### `extra_hosts` オプションとは
[Compose ファイル・リファレンス — Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/compose/compose-file.html#extra-hosts)

> ホスト名を割り当てます。これは docker クライアントで ` --add-host ` パラメータを使うのと同じものです。
> 
> ```yaml
> extra_hosts:
>  - "somehost:162.242.195.82"
>  - "otherhost:50.31.209.229"
> ```

### `docker-compose.yml` を変更

```yaml
version: '3'

services:
  centos:
    image: centos:7.6.1810
    extra_hosts:
      - "aaa.example.com:127.2.3.4"
    tty: true
```

### コンテナ内 `/etc/hosts` に自動で追記される

```bash
[root@7c139c5eed5b /]# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.2.3.4       aaa.example.com
172.20.0.2      7c139c5eed5b
```


### 動作確認（コンテナ内）
「コンテナ内の `/etc/hosts` を変更する場合」 と同じ結果のため省略

> nslookup では名前解決できないが、 pingやcurlなどでは名前解決されている



# 結論
- コンテナ内の `/etc/hosts` のみがコンテナ内での名前解決に影響する
    - コンテナの外（ホスト）の `/etc/hosts` は無関係
- curl や ping は `/etc/hosts` の設定が反映されるが、 nslookup や dig は `/etc/hosts` を見ない
- コンテナ内の `/etc/hosts` への設定は docker の機能で可能
    - docker-compose の `extra_hosts` 設定
    - docker の `--add-host` パラメータ