Device or resource busy
Dockerでprom/blackbox-exporter - Docker Image
をベースにしたイメージを作ろうとしたときに/etc/resolv.confを上書きしようとしたらDevice or resource busyというエラーが出て上書きできなかった。
FROM prom/blackbox-exporter:v0.24.0
COPY entrypoint.sh /app/entrypoint.sh
COPY resolv.conf /app/resolv.conf
ENTRYPOINT ["/app/entrypoint.sh"]
cp /app/resolv.conf /etc/resolv.conf
...
Dockerfileで/app/resolv.confに置いたファイルを/etc/resolv.confにコピーしようとしている。
コンテナを立ち上げるとDockerのログに以下のメッセージが出てコピーに失敗する。
cp: can't create '/etc/resolv.conf': File exists
sed -i も失敗する
直接書き換える方法としてsed -iを使ってみたが、これも失敗した。
sed -i 's/^nameserver/#nameserver/' /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
...
以下のエラーメッセージが出た。
sed: can't move '/etc/resolv.confxsK8Gs' to '/etc/resolv.conf': Device or resource busy
sed -i一時ファイルに書き込んでから元のファイルにリネームするため、/etc/resolv.confを上書きしようとしてcpのときと同様のエラーが発生する。
/etc/resolv.confを調べる
dfコマンドを確認すると/etc/resolv.confがマウントされているのがわかる。
$ df
...
/dev/vda1             61202244  11577640  46483280  20% /etc/resolv.conf
/dev/vda1             61202244  11577640  46483280  20% /etc/hostname
/dev/vda1             61202244  11577640  46483280  20% /etc/hosts
hostnameやhostsも同じデバイスにマウントされている。
これが原因で/etc/resolv.confを上書きできないと考えられる。
リダイレクトによる変更は成功する
リダイレクトによる変更は成功する。
$ echo "nameserver 8.8.8.8" >> /etc/resolv.conf
$ tail -1 /etc/resolv.conf
nameserver 8.8.8.8
>>とすれば追記となるが、>とすれば上書きとなる。
無理やりの解決策
リダイレクトでは成功するので以下のように書き換える。
conf=$(sed "s/^nameserver/#nameserver/" /etc/resolv.conf)
echo "$conf" > /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
...
sedは一度結果を変数に格納してからリダイレクトで上書きする。
追記は>>で行う。
これでコンテナ起動時に実行され、/etc/resolv.confは以下のように修正される。
$ cat /etc/resolv.conf
#nameserver 127.0.0.11
options ndots:0
nameserver 8.8.8.8
\第一線のプログラマーの行動原理を学べる!/

