AWS EC2 上で docker イメージをビルドしようとして、ハマったので覚え書き。
現象
docker イメージのビルドで以下のエラーになった。
内容は fluentd のイメージにプラグインの gem を追加するというもの。
$ docker build . --no-cache
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM fluent/fluentd:v1.11.4-2.0
v1.11.4-2.0: Pulling from fluent/fluentd
df20fa9351a1: Pull complete
5bbb4150a5a0: Pull complete
0a2f393cb307: Pull complete
b1dea35b5d99: Pull complete
65de893ed157: Pull complete
Digest: sha256:0c6ae6c72902cbc3a4f60bc15069cb89fd72b57391bff150960a6f911361d6c9
Status: Downloaded newer image for fluent/fluentd:v1.11.4-2.0
---> 7bcbcb847e0d
Step 2/4 : USER root
---> Running in 79fb5c74b17f
Removing intermediate container 79fb5c74b17f
---> 03af9cdb324e
Step 3/4 : RUN gem install fluent-plugin-cloudwatch-logs
---> Running in 1bcf43a8efb2
ERROR: Could not find a valid gem 'fluent-plugin-cloudwatch-logs' (>= 0), here is why:
Unable to download data from https://rubygems.org/ - no such name (https://rubygems.org/specs.4.8.gz)
ERROR: Service 'fluentd' failed to build : The command '/bin/sh -c gem install fluent-plugin-cloudwatch-logs' returned a non-zero code: 2
rubygems.org に接続できないというもので、調べてみるとプロキシの設定が必要などの情報が出てくる。
が、ホスト上では接続できているので関係はなさそう。
サイトへの直接アクセスもできず、名前解決もできていない。
で、分かったのはネットワークインターフェースの eth0 がないこと。
$ docker build . --no-cache
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM fluent/fluentd:v1.11.4-2.0
---> 7bcbcb847e0d
Step 2/3 : USER root
---> Running in c80c0a20cd21
Removing intermediate container c80c0a20cd21
---> 16f2ba30695a
Step 3/3 : RUN ifconfig
---> Running in 1d9cb7d5e2ec
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Removing intermediate container 1d9cb7d5e2ec
---> de98e34f64e7
Successfully built de98e34f64e7
ホスト側で見てみると docker0 がなく、docker network でデフォルトの bridge がいないことが分かった。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
2d9ce67d06f5 host host local
9a455bcae53c none null local
確認
ホストの OS は Amazon Linux 2 (EKS-Optimized) ですが、別のサーバでは問題なくビルドできていたので、比べてみるとバージョンが違っている。
- amazon-eks-node-1.11-v20190220 → ビルドできている環境
- amazon-eks-node-1.17-v20201002 → ビルド失敗する環境
それぞれの docker のバージョンを見てみると、以下の違いがあった。
# ビルドできている環境
$ docker version
Client:
Version: 18.06.1-ce
API version: 1.38
Go version: go1.10.3
Git commit: e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
Built: Mon Jan 28 21:03:38 2019
OS/Arch: linux/amd64
Experimental: false
:
# ビルド失敗する環境
$ docker version
Client:
Version: 19.03.6-ce
API version: 1.40
Go version: go1.13.4
Git commit: 369ce74
Built: Fri May 29 04:01:26 2020
OS/Arch: linux/amd64
Experimental: false
:
なお、ビルドできている方ではデフォルトの bridge ネットワークが存在している。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
2f3fd9d451c6 bridge bridge local
cd2fe4f72dff host host local
f56d76b46acb none null local
この bridge の有無が docker build のエラー原因かは情報を見つけられなかったのですが、デフォルト bridge の有無の方向で調べてみると /etc/docker/daemon.json という設定ファイルが出てきたので上記のサーバで比較してみた。
ビルドできている環境
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "10"
},
"live-restore": true,
"max-concurrent-downloads": 10,
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Soft": 2048,
"Hard": 8192
}
}
}
ビルド失敗する環境
{
"bridge": "none",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "10"
},
"live-restore": true,
"max-concurrent-downloads": 10
}
bridge: none という設定が関係しそう。
対処
/etc/docker/daemon.json ファイルの bridge: none の設定を削除して docker サービスを再起動してみる。
$ sudo service docker restart
上記のコマンドでサービス再起動をしてもすぐ解決しなかった。
その後、stop、start と別にしたり、systemctl コマンドで操作したりしてるうちにデフォルト bridge ができた。
どうも、稼働中のコンテナがいたり、docker-compose で作られるネットワークがいるとダメなようで、すべてのコンテナを停止して、後から作られたネットワークも削除してから docker サービスを再起動したら設定が反映された。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c4433dcfbe9b bridge bridge local
2d9ce67d06f5 host host local
9a455bcae53c none null local
先ほどの docker build を試してみると、eth0 もできてる。
$ docker build . --no-cached
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM fluent/fluentd:v1.11.4-2.0
---> 7bcbcb847e0d
Step 2/3 : USER root
---> Using cache
---> 15b06f798b72
Step 3/3 : RUN ifconfig
---> Running in 713f15663040
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:180 (180.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Removing intermediate container 713f15663040
---> 6d99f256433b
Successfully built 6d99f256433b
元の fluentd のビルドを試してみると、gem のダウンロードもできて、問題なくビルドができるようになった。
$ docker build . --no-cached
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM fluent/fluentd:v1.11.4-2.0
---> 7bcbcb847e0d
Step 2/4 : USER root
---> Using cache
---> a733f7c02648
Step 3/4 : RUN gem install fluent-plugin-cloudwatch-logs
---> Running in 1d43a2226fb4
Successfully installed jmespath-1.4.0
Successfully installed aws-partitions-1.391.0
Successfully installed aws-eventstream-1.1.0
Successfully installed aws-sigv4-1.2.2
Successfully installed aws-sdk-core-3.109.2
Successfully installed aws-sdk-cloudwatchlogs-1.38.0
Successfully installed fluent-plugin-cloudwatch-logs-0.11.1
7 gems installed
Removing intermediate container 1d43a2226fb4
---> f7242c21bd02
Step 4/4 : USER fluent
---> Running in 7baaad7e3b2d
Removing intermediate container 7baaad7e3b2d
---> c39b2ddf48d9
Successfully built c39b2ddf48d9
ビルドエラーは解消できたのでひとまずは完了ですが、なぜ新しいバージョンの docker、OS 環境で bridge が無効化されているのかが分からない。
デフォルトの bridge は作るべきではないという情報も見かけたのだけど、なぜダメで、bridge を作らないのであればどうすべきかというはっきりとした情報が見つけられなかった。
あるいは EKS-Optimized なイメージなので、通常はランタイムのみの利用で docker build の実行を想定していないのかもしれない。