0

I have a Docker image that contains two configuration files and merges them using sed depending on the passed environment variables in the entrypoint script. To simplify this merge step, you can assume something like

if [ -n $MERGE ]; then
    sed -i s/a/b/ /config.json
fi

The person who wrote this entrypoint script didn't consider the main use-case where config.json is mounted into the container. In that case, this script produces the error message

sed: cannot rename ./sedahi0e3: Device or resource busy

because sed writes its changes into a tempfile and overwrites the original file. As I said, this is a simplification of my actual problem, so most workarounds for this won't work. I just want to know if it's somehow possible to mount config.json into the container and allow it to be overwritten, deleted or shadowed. It's not so important, what happens with the original file on the host file system. In the best case, it's not modified, but I could accept it to be deleted or modified. If it's not possible, I have to modify the script in a complex and error-prone way, that could break some edge cases of configuration, I don't know about.

Can I mount a file into a Docker container in a way, that it can be overwritten, deleted or shadowed inside the container? The image is based on Alpine Linux. The host is either Debian or RHEL.

To reproduce the problem, you can create a file config.json. Start an Alpine container with

docker run -v $PWD/config.json:/config.json -it --rm alpine sh

copy the file

cp /config.json /config2.json

and try to overwrite the mounted file with the copy

mv /config2.json /config.json

That's similar to what the sed merge in the entrypoint script does and produces the same error.

1 Answer 1

1

If the file is mounted rw (default) you can replace the contents (this will modify the file on the host):

$ cat config.json 
{
  "key": "value1"
}

$ docker run -v "$(pwd)/config.json:/config.json" --rm -it alpine sh
/ # cp /config.json /config2.json
/ # vi config2.json 
/ # cat config2.json >config.json
/ # cat config.json
{
  "key": "value2"
}
/ # exit

$ cat config.json 
{
  "key": "value2"
}

Another option is consider is making the file inside the image a symlink that can point to the location of the bind mount. Then you're changing the symlink to a file inside the container filesystem rather than trying to replace a bind mount.

A common technique for more complicated images is to have a /config.d/ directory in the container consisting of multiple configurations that are merged together by the application, and in those cases you don't modify the bind mount, but perhaps create a higher priority config that overrides any settings you need to change.

Anything that tries to change the inode of the bind mount will not work. That includes mv and sed -i.

5
  • As I said in the question, I'm not looking for workarounds. I'm asking if it's possible to mv a file over a bind mount in order to use sed -i.
    – jabaa
    Commented May 8, 2022 at 21:14
  • 1
    I'm answering the question of whether it can be overwritten. mv doesn't work because it doesn't overwrite the file, it replaces the inode with a new file, which doesn't work with a bind mount.
    – BMitch
    Commented May 8, 2022 at 22:34
  • I made it pretty clear that the actual problem is sed -i and I need a way to overwrite with mv. This is a the workaround I explicitly don't ask for. Is it possible to overwrite a mounted file with mv or sed -i. Can you make the example at the end of my question work?
    – jabaa
    Commented May 8, 2022 at 23:45
  • 1
    sed -i will not work with a bind mount, as you've already shown.
    – BMitch
    Commented May 9, 2022 at 0:00
  • Your last comment is an answer to my question.
    – jabaa
    Commented May 9, 2022 at 10:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .