Run Docker-compose as Root User: Python Coverage Permission Denied

08/08/20191 Min Read — In DevOps, Docker, Python

I'm learning test-driven development with the course Microservices with Docker, Flask, and React.

It's been a lot of fun. I've also learned more about using Docker and docker-compose.

The course uses Coverage.py for measuring Python code coverage.

However, Coverage.py and Docker don't play well with each other if you run the Docker container as a normal (non-root) user.

PermissionError: [Errno 13] Permission denied: 'usr/src/app/.coverage'

Here is the Dockerfile:

# base image
FROM python:3.7.2-slim
# install dependencies
RUN apt-get update && \
apt-get -y install netcat && \
apt-get clean
# set working directory
WORKDIR /usr/src/app
# add and install requirements
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install --upgrade pip && pip install -r requirements.txt
# add entrypoint.sh
COPY ./entrypoint.sh /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh
# add app
COPY . /usr/src/app
# add user
RUN addgroup --system user && adduser --system --group user
RUN chown -R user:user /usr/src/app && chmod -R 755 /usr/src/app
USER user
# run server
CMD ["/usr/src/app/entrypoint.sh"]

As you can see, I add a normal user to the docker container, give them permission to the directory and run all following commands as non-root user.

Let's say I run this command:

docker-compose exec users python manage.py coverage

My docker-compose config doesn't specify a user. My Dockerfile (see above) switches to a non-root user.

Thus, my docker-compose commands run as non-root user.

docker-compose run --rm users -sh -c "id -u -n"
> user

According to my research, it is more secure to run applications inside of the container as non-root user.

“docker-compose up” as root user or non-root user?:

The important detail is to run applications inside of your container as a non-root user. It's the equivalent of systemd running as root and launching a program as a non-root user.

But now the permissions for Coverage.py don't work.

This seems to be a common problem: Test coverage in a docker container.

Trying to give permissions to the non-root user via chmod +x doesn't work.

So, I need to run docker-compose as root user for Coverage.py.

I could add a user to docker-compose.yml like so:

version: '3.7'
services:
users:
user: root
build:
context: ./services/users
dockerfile: Dockerfile
(...rest of docker-compose file)

But I don't want to run all commands as root.

Instead it's possible to add a flag to the docker-compose CLI command:

docker-compose run -u root --rm users sh -c "id -u -n"
>root

To run Coverage.py as root user:

docker-compose run -u root --rm users sh -c "python manage.py cov"

Further Reading