Dockerコンテナでパッケージインストール時にエラーとなった際にやったこと

# 環境
- Arch Linux
- Docker 20.10.5

# 何があったか
GASの勉強のためにDockerでclaspを導入した環境を構築しようとしたら、何度やっても`npm`インストールでエラーになる。。

```
$ docker-compose up -d --build
Building gas
Sending build context to Docker daemon  4.608kB
〜 中略 〜
Step 3/3 : RUN npm i @google/clasp -g
 ---> Running in 8821bf6923b3
npm ERR! code EAI_AGAIN
npm ERR! errno EAI_AGAIN
npm ERR! request to https://registry.npmjs.org/@google%2fclasp failed, reason: getaddrinfo EAI_AGAIN registry.npmjs.org

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2021-03-11T14_04_40_662Z-debug.log
The command '/bin/sh -c npm i @google/clasp -g' returned a non-zero code: 1
ERROR: Service 'gas' failed to build
$
```

色々調べる中で試しにUbuntuのコンテナから`apt`コマンドを叩いてみたら、リポジトリにアクセスできないことが判明。
どうやらコンテナからインターネットにアクセスできない状態にあったみたい。

```
$ docker container run -it --rm ubuntu:20.04
root@46600d291397:/# apt update
Err:1 http://archive.ubuntu.com/ubuntu focal InRelease                   
  Temporary failure resolving 'archive.ubuntu.com'
Err:2 http://security.ubuntu.com/ubuntu focal-security InRelease         
  Temporary failure resolving 'security.ubuntu.com'
Err:3 http://archive.ubuntu.com/ubuntu focal-updates InRelease           
  Temporary failure resolving 'archive.ubuntu.com'
Err:4 http://archive.ubuntu.com/ubuntu focal-backports InRelease
  Temporary failure resolving 'archive.ubuntu.com'
Reading package lists... Done        
Building dependency tree       
Reading state information... Done
All packages are up to date.
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/focal/InRelease  Temporary failure resolving 'archive.ubuntu.com'
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/focal-updates/InRelease  Temporary failure resolving 'archive.ubuntu.com'
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/focal-backports/InRelease  Temporary failure resolving 'archive.ubuntu.com'
W: Failed to fetch http://security.ubuntu.com/ubuntu/dists/focal-security/InRelease  Temporary failure resolving 'security.ubuntu.com'
W: Some index files failed to download. They have been ignored, or old ones used instead.
root@46600d291397:/# 
```

# 原因
ホストOS側のファイアウォール設定が原因だった。

# 調べたこと/やったこと
## DNS
npmのエラーメッセージ `reason: getaddrinfo EAI_AGAIN registry.npmjs.org` でググると、コンテナのDNS設定が怪しい！という情報がいっぱい出てきた。
デフォルトではホストOSの`/etc/resolv.conf`設定がコンテナに反映されるらしい。

```
$ cat /etc/resolv.conf
nameserver 192.168.1.100
$
$ docker container run -it --rm ubuntu:20.04
root@58673efbfcd1:/# cat /etc/resolv.conf
nameserver 192.168.1.100
root@58673efbfcd1:/# 
```

コンテナ内のDNS参照先を変更するには、コンテナ起動時に`--dns`オプションで指定するやり方と、

- [Container networking - Docker Documentation](https://docs.docker.com/config/containers/container-networking/)

```
$ docker container run -it --rm --dns 8.8.8.8 ubuntu:20.04
root@fe87f1509fdf:/# cat /etc/resolv.conf
nameserver 8.8.8.8
root@fe87f1509fdf:/# 
```

ホストOS側でデーモン設定ファイル(/etc/docker/daemon.json)を編集するやり方があるみたい。

- [デーモン設定ファイル - Docker-docs-ja](https://docs.docker.jp/engine/reference/commandline/dockerd.html#daemon-configuration-file)

```
$ sudo vim /etc/docker/daemon.json
```

```:/etc/docker/daemon.json
{
    "dns": ["8.8.8.8", "8.8.4.4"]
}
```

```
$ sudo systemctl restart docker
$ docker container run -it --rm ubuntu:20.04
root@c42a4279a14f:/# cat /etc/resolv.conf 
nameserver 8.8.8.8
nameserver 8.8.4.4
root@c42a4279a14f:/# 
```

ただ、今回の場合はファイアウォール設定が原因だったため、この対応では事象を解決できなかった。。

## ファイアウォール
色々調べ回っているときに、[Dockerコンテナからインターネットに繋がらないときに確認すること - Qiita](https://qiita.com/yangniao23/items/a9213bf402c1f120562b) に行き当たる。
iptablesとfirewalldの設定を確認するように、との項目を見て、嫌な予感が。。
試しにホストOS側でnftablesを停止してみたら、`apt`コマンドでリポジトリにアクセスできた！

その後こちらの記事 [Docker と nftables - eagletmt's blog](https://eagletmt.hateblo.jp/entry/2017/05/09/025510) にもたどり着き、nftablesを使っている環境では色々と支障があることがわかった。。
最終的にはArchWikiにもきちんと記載があることに気付く。

- [Docker#docker0 ブリッジが IP を取得できない / コンテナからインターネットにアクセスできない - ArchWiki](https://wiki.archlinux.jp/index.php/Docker#docker0_.E3.83.96.E3.83.AA.E3.83.83.E3.82.B8.E3.81.8C_IP_.E3.82.92.E5.8F.96.E5.BE.97.E3.81.A7.E3.81.8D.E3.81.AA.E3.81.84_.2F_.E3.82.B3.E3.83.B3.E3.83.86.E3.83.8A.E3.81.8B.E3.82.89.E3.82.A4.E3.83.B3.E3.82.BF.E3.83.BC.E3.83.8D.E3.83.83.E3.83.88.E3.81.AB.E3.82.A2.E3.82.AF.E3.82.BB.E3.82.B9.E3.81.A7.E3.81.8D.E3.81.AA.E3.81.84)
- [nftables#Working with Docker - ArchWiki](https://wiki.archlinux.org/index.php/nftables#Working_with_Docker)

## 対応
nftablesからiptablesに変更する記事なども散見されるけれど、今回はnftablesの設定を変更することにした。
[ArchWiki](https://wiki.archlinux.org/index.php/nftables#Working_with_Docker)を参考に修正。

>The factual accuracy of this article or section is disputed.
Reason: This section is not correct. The default docker forward policy is accept. This might end in an insecure forward chain...

とあるのは気にかかるが、個人の環境だから目を瞑ることにする。。

```
$ sudo pacman -S iptables-nft
$ sudo cp -p /etc/nftables.conf{,.org}
$ sudo vim /etc/nftables.conf
```

```:/etc/nftables.conf
#!/usr/bin/nft -f
# ipv4/ipv6 Simple & Safe Firewall
# you can find examples in /usr/share/nftables/

table inet filter {
  chain input {
    type filter hook input priority 0;

    # allow established/related connections
    ct state {established, related} accept

    # early drop of invalid connections
    ct state invalid drop

    # allow from loopback
    iifname lo accept

    # allow icmp
    ip protocol icmp accept
    meta l4proto ipv6-icmp accept

    # allow ssh
    tcp dport ssh accept

    # everything else
    reject with icmpx type port-unreachable
  }
  chain forward {
    type filter hook forward priority 0;
    mark 1 accept  # Docker
    drop
  }
  chain output {
    type filter hook output priority 0;
  }

}

# Docker
table ip filter {
  chain DOCKER-USER {
    mark set 1
  }
}

# vim:set ts=2 sw=2 et:
```

```
$ sudo systemctl restart nftables
$ sudo systemctl restart docker
$ docker container run -it --rm ubuntu:20.04
root@f554e294f10c:/# apt update
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [109 kB]  
Get:2 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]            
Get:3 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages [659 kB]
Get:4 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:5 http://security.ubuntu.com/ubuntu focal-security/multiverse amd64 Packages [21.6 kB]
Get:6 http://security.ubuntu.com/ubuntu focal-security/universe amd64 Packages [681 kB]
Get:7 http://archive.ubuntu.com/ubuntu focal-backports InRelease [101 kB]    
Get:8 http://security.ubuntu.com/ubuntu focal-security/restricted amd64 Packages [178 kB]
Get:9 http://archive.ubuntu.com/ubuntu focal/universe amd64 Packages [11.3 MB]
Get:10 http://archive.ubuntu.com/ubuntu focal/main amd64 Packages [1275 kB]                                                               
Get:11 http://archive.ubuntu.com/ubuntu focal/restricted amd64 Packages [33.4 kB]                                                         
Get:12 http://archive.ubuntu.com/ubuntu focal/multiverse amd64 Packages [177 kB]                                                          
Get:13 http://archive.ubuntu.com/ubuntu focal-updates/restricted amd64 Packages [210 kB]                                                  
Get:14 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages [1066 kB]                                                       
Get:15 http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 Packages [938 kB]                                                    
Get:16 http://archive.ubuntu.com/ubuntu focal-updates/multiverse amd64 Packages [29.6 kB]                                                 
Get:17 http://archive.ubuntu.com/ubuntu focal-backports/universe amd64 Packages [4301 B]                                                  
Fetched 17.2 MB in 9s (1961 kB/s)                                                                                                         
Reading package lists... Done
Building dependency tree       
Reading state information... Done
11 packages can be upgraded. Run 'apt list --upgradable' to see them.
root@f554e294f10c:/#
```

Dockerコンテナからインターネットにアクセスできるようになった。

## あとがき
`nftables`よくわからん。。もっと理解したい。。
あと、Podmanも試してみようかなという気になりました。
RHEL/CentOSの場合は以下が参考になりそうです。

- [centOS8でDockerコンテナから名前解決ができない話をnftコマンドで解決する - Qiita](https://qiita.com/DaichiSasak1/items/11687a3c613c8811350c)
- [CentOS8にDockerをインストール。名前解決できなかったのが解消した。 - Qiita](https://qiita.com/bashaway/items/4001c0ad5a6f21957986)