Mastodon hachyterm.io

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