Lately I've been using Docker container as clean, easily portable and easily removable build environments. In those cases the image contains the needed build tools and the project is mounted to a volume inside the container. The artifacts are then built inside the container but are placed inside the volume. However a small problem arises, the artifacts (and whatever other files are created, like cache) are owned by the default user, root
, making editing or removing said files less straightforward.
The trivial solution
The trivial solution is to run the container with the correct user id, like so
uid="$(id -u)" gid="$(id -g)" docker run -v "$PWD:/volume" --user "$uid:$gid" buildimage make
I personally find it a tiresome after the 3rd time I had to sudo chown the project because I forgot to specify the uid and gid and it's a (low) barrier of entry for new users.
A better solution
The solution I've come up with is this small script that sets the uid and gid values to those of the owner and group for the volume and then execute the commands.
#!/bin/sh set -eu [ "$(id -u)" = "0" ] || { echo "Not running as root, continuing as the current user."; eval exec "$@"; } command -v stat > /dev/null || { echo "Can't find stat, exiting."; exit 1; } command -v gosu > /dev/null || { echo "Can't find gosu, exiting."; exit 1; } uid="$(stat . -c '%u')" gid="$(stat . -c '%g')" eval exec gosu "$uid:$gid" "$@"
The script is also available for download. The only dependency is gosu. You can download and check it to your VCS and incorporate it into your Dockerfile, or download it via the ADD
directive, like so:
FROM buildpack-deps RUN curl -fsSL https://github.com/tianon/gosu/releases/download/1.10/gosu-amd64 -o gosu-amd64 && \ install -o root -g root -m 755 gosu-amd64 /usr/local/bin/gosu && \ rm gosu-amd64 && \ curl -fsSL https://www.shore.co.il/blog/static/runas -o runas && \ install -o root -g root -m 755 runas /entrypoint && \ rm runas ENTRYPOINT [ "/entrypoint" ] VOLUME /volume WORKDIR /volume ENV HOME /volume
Setting the home directory to the mounted volume will result in some files (like package managers cache) to be created there, which you may or may not want. And then finally, to build run
docker run -v "$PWD:/volume" buildimage make