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
\第一線のプログラマーの行動原理を学べる!/