Container losing volume (/etc/hosts) when file is edited

To sum up, when I start a container with a volume between my source hosts (/etc/hosts) file and container’s one it’s working fine!
After I use the “sed” command, suddenly the volume stop working…
Ex:
docker run -it -v /etc/hosts:/etc/hosts my-image /bin/bash
sudo sed -i ‘4i’“test123” “/etc/hosts” (executed in the source side)

My machine statistics:
Linux #58~14.04.1-Ubuntu x86_64 x86_64 x86_64 GNU/Linux
Kernel: 3.19.0-51-generic

Does anyone know why it’s happening and if it’s a bug?
Thanks

Docker have a problem with replaced files. In this scenario, sed will replace the whole file with a new one with the modified content. If you use ‘ex’ command (which is the vi) to replace the file content it will work. I will open an issue to see why Docker can’t keep watching the FileDescriptor (FD) for changes and update the FD in cases like this one

1 Like

(answered this on GitHub, but let me post this here as well)

Yes, this is expected, and not something docker can account for; this is a limitation in the way mount works. Basically, when bind-mounting a file, mount keeps track of the inode of the mounted file. Some tools don’t update a file, but write to a temp-file, and replace the existing file. The bind-mount is still using the inode of the original file though, which may have been deleted in the process.

We do have some mention of this in the documentation, but that refers to trying to edit a bind-mounted file from inside the container, which is the same problem actually, but with different effect;

https://docs.docker.com/engine/userguide/containers/dockervolumes/#mount-a-host-file-as-a-data-volume

Note: Many tools used to edit files including vi and sed --in-place may result in an inode change. Since Docker v1.1.0, this will produce an error such as “sed: cannot rename ./sedKdJ9Dy: Device or resource busy”. In the case where you want to edit the mounted file, it is often easiest to instead mount the parent directory.

The solution is the same; if possible, put the file you want to mount in a directory, and mount the directory instead of a single file. In the example discussed in the linked forum post (bind-mounting /etc/hosts), this may not be possible. Perhaps not using the --in-place option would resolve it though.

Is there a reason you want to edit the /etc/hosts file for the container? If you want to add custom host entries to /etc/hosts, I’d recommend using the --add-host option on docker run, for example

docker run -t --rm --add-host foobar:192.168.1.5 alpine sh -c "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
192.168.1.5	foobar
172.17.0.4	f8bb57c2869d
1 Like