abc123
abc123

Reputation: 143

Docker: non-root user does not have writing permissions when using volumes

I have the following Dockerfile:

...

RUN groupadd -r myuser&&  useradd -r -g myuser myuser

RUN mkdir /data && chmod a+rwx /data

USER myuser

...

Running the image with docker run works fine (I mean the user myuser has writing rights in the /data directory).

If I run the image with docker run -v /host/path:/data, the user myuser cannot write in the /data directory.

Question: How to give the user myuser permission to write in the /data directory in the second case?


The reason is the fact that the /host/path directory is own by root and the user myuser does not have permission to write in such directories.

Upvotes: 3

Views: 8151

Answers (2)

David Maze
David Maze

Reputation: 160073

You can run the container as the user ID matching the host user ID owning the directory. Often this is the current user:

 docker run -u $(id -u) -v /host/path:/container/path ...

For this to work, your image needs to do a couple of things:

  • The data needs to be kept somewhere completely separate from the application code. A top-level /data directory as you show is a good choice.
  • The application proper should be owned by root, and world-readable but not world-writeable; do not RUN chown ... the application, just COPY it in and run its build sequence as root.
  • The image should create a non-root user, but it does not need to match any particular host user.
  • The image needs to create the data directory, but it should be completely empty.
  • The image startup (often an entrypoint wrapper script) needs to be able to populate the data directory if it is totally empty at startup time.
FROM some-base-image

# Do all of the initial setup and build as root
WORKDIR /app
COPY . .
RUN ...

# Create some non-root user that owns the data directory by default
RUN useradd -r myuser          # no specific user ID
RUN mkdir /data && chown myuser /data
# VOLUME ["/data"]             # optional, the only place VOLUME makes sense at all

# Specify how to run the container
USER myuser                    # not earlier than this
EXPOSE ...                     # optional but good practice
ENTRYPOINT ["/entrypoint.sh"]  # knows how to seed /data, then `exec "$@"`
CMD my_app ...                 # a complete command line

Upvotes: 5

anemyte
anemyte

Reputation: 20306

When you use a bind mount (-v /host/path:/container/path) it just mounts the source on the target 'as is'. No ownership or permission change happens, it is just one file replacing the other. So if /host/path belongs to root and others cannot write in it, the container user will not be able to write there too.

You can change permissions\ownership at the host or think of another way, depending on the circumstances. Some containers (like postgres for example) start as root to enforce the correct permissions. After that the main process starts as another user.

Upvotes: 1

Related Questions