无法使用数据文件.coverage: 无法打开数据库文件

问题描述 投票:0回答:2

推送到 GitHub 时出现奇怪的权限问题。我有一个测试作业,它运行覆盖范围的测试,然后在每次推送和拉取请求时将结果推送到 codecov。但是,这种情况仅适用于 root 用户。

如果使用

digitalshop
用户运行,则会抛出错误:

Couldn't use data file '/digital-shop-app/.coverage': unable to open database file

我的问题是:如何在 docker 容器中运行覆盖,这样它就不会抛出此错误?我的猜测是这是因为权限。

docker-compose.yml:

version: '3.9'

services:
  test:
    build: .
    command: >
      sh -c "
        python manage.py wait_for_db &&
        coverage run --source='.' manage.py test mainapp.tests &&
        coverage report &&
        coverage xml
      "
    volumes: 
      - ./digital-shop-app:/digital-shop-app
    env_file: .env
    depends_on: 
      - db

  db:
    image: postgres:13-alpine
    environment:
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASS}

Dockerfile:

FROM python:3.9-alpine3.13

ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt /requirements.txt
COPY ./digital-shop-app /digital-shop-app
COPY ./scripts /scripts

WORKDIR /digital-shop-app

RUN python -m venv /py && \
    /py/bin/pip install --upgrade pip && \
    apk add --no-cache bash && \
    apk add --update --no-cache postgresql-client && \
    apk add --update --no-cache --virtual .tmp-deps \
        build-base jpeg-dev postgresql-dev musl-dev linux-headers \
        zlib-dev libffi-dev openssl-dev python3-dev cargo && \
    apk add --update --no-cache libjpeg && \
    /py/bin/pip install -r /requirements.txt && \
    apk del .tmp-deps && \
    adduser --disabled-password --no-create-home digitalshop && \
    chown -R digitalshop:digitalshop /py/lib/python3.9/site-packages && \
    chmod -R +x /scripts

ENV PATH="/scripts:/py/bin:/py/lib:$PATH"

USER digitalshop

CMD ["run.sh"]
python dockerfile code-coverage alpine-linux
2个回答
1
投票

所以我最终创建了另一个名为

Dockerfile.test
的 Dockerfile,并放置了几乎相同的配置(除了非管理员用户创建之外)。这是最终的变体:

不建议以 root 用户身份运行代码,因此请阅读更新部分

Dockerfile.测试:

FROM python:3.9-alpine3.13

ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt /requirements.txt
COPY ./digital-shop-app /digital-shop-app

WORKDIR /digital-shop-app

RUN python -m venv /py && \
    /py/bin/pip install --upgrade pip && \
    apk add --no-cache bash curl gnupg coreutils && \
    apk add --update --no-cache postgresql-client libjpeg && \
    apk add --update --no-cache --virtual .tmp-deps \
        build-base jpeg-dev postgresql-dev musl-dev linux-headers \
        zlib-dev libffi-dev openssl-dev python3-dev cargo && \
    /py/bin/pip install -r /requirements.txt && \
    apk del .tmp-deps

ENV PATH="/py/bin:/py/lib:$PATH"

docker-compose.yml:

version: '3.9'

services:
  test:
    build:
      context: .
      dockerfile: Dockerfile.test
    command: >
      sh -c "
        python manage.py wait_for_db &&
        coverage run --source='.' manage.py test mainapp.tests &&
        coverage report &&
        coverage xml
      "
    volumes: 
      - ./digital-shop-app:/digital-shop-app
    env_file: .env
    depends_on: 
      - db

我不知道这是否是一个好的做法。如果没有,请告诉如何正确地做。

更新:

感谢@β.εηοιτ.βε给了我思考。

经过一些本地调试,我发现覆盖范围需要用户拥有

.coverage
文件所在的目录。因此,我在项目文件夹中创建了名为
/cov
的子目录,并将
digitalshop
用户设置为其所有者,包括其中的所有内容。最后,我通过设置环境变量
.coverage
来指定
COVERAGE_FILE=/digital-shop-app/cov/.coverage
文件的路径,其中
digital-shop-app
是项目根文件夹。并且还在
coverage.xml
中指定了与
docker-compose.yml
报告相同的路径。这是代码:

docker-compose.yml(向

-o
命令添加
coverage xml
标志):

version: '3.9'

services:
  test:
    build:
      context: .
    command: >
      sh -c "
        python manage.py wait_for_db &&
        coverage run --source='.' manage.py test mainapp.tests &&
        coverage xml -o /digital-shop-app/cov/coverage.xml
      "
    env_file: .env
    depends_on: 
      - db

  db:
    image: postgres:13-alpine
    environment:
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASS}

Dockerfile:

FROM python:3.9-alpine3.13

ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt /requirements.txt
COPY ./digital-shop-app /digital-shop-app
COPY ./scripts /scripts

WORKDIR /digital-shop-app

RUN python -m venv /py && \
    /py/bin/pip install --upgrade pip && \
    apk add --no-cache bash && \
    apk add --update --no-cache postgresql-client && \
    apk add --update --no-cache --virtual .tmp-deps \
        build-base jpeg-dev postgresql-dev musl-dev linux-headers \
        zlib-dev libffi-dev openssl-dev python3-dev cargo && \
    apk add --update --no-cache libjpeg && \
    /py/bin/pip install -r /requirements.txt && \
    apk del .tmp-deps && \
    adduser --disabled-password --no-create-home digitalshop && \
    chown -R digitalshop:digitalshop /py/lib/python3.9/site-packages && \
    chmod -R +x /scripts && \
    # New code here
    mkdir -p /digital-shop-app/cov && \
    chown -R digitalshop:digitalshop /digital-shop-app/cov

ENV PATH="/scripts:/py/bin:/py/lib:$PATH"

USER digitalshop

CMD ["run.sh"]

0
投票

问题

在 GitHub Actions 中 github 托管的

ubuntu-latest
图像中使用 docker-compose 运行覆盖范围的 pytest 时,我遇到了同样的错误。这是 Docker 主机文件系统所有者匹配问题的一个实例。

简而言之,主机(github操作运行器)上的用户和容器(运行我的pytest套件的容器)上的用户具有不同的UID。挂载的目录

app
由主机上的用户拥有。当容器中的用户尝试写入
app/.coverage
时,权限会被拒绝(因为该用户不是所有者)。

修复

就我而言,我通过将 docker 镜像的默认用户的 UID 与 github actions runner 用户的 UID 进行匹配来解决了这个问题,

1001
。我将其添加到我的
Dockerfile
中以实现此目的:

# Make the default user have the same UID as the github actions "runner" user.
# This to avoid permission issues when mounting volumes.
USER root
RUN usermod --uid 1001 <image_default_user>
USER <image_default_user>

所有相关文件

app/test_utils/docker-compose.yml

version: "3.9"

services:
  app:
    build:
      context: ../
      dockerfile: ./test_utils/Dockerfile
    container_name: app
    volumes:
      - ..:/app

app/test_utils/Dockerfile

FROM <my base image>

# Make the default user have the same UID as the github actions "runner" user.
# This to avoid permission issues when mounting volumes, see
USER root
RUN usermod --uid 1001 <image_default_user>
USER <image_default_user>

COPY . /app
WORKDIR /app

RUN pip3 install -r requirements.txt -r requirements_test.txt

app/.github/unittests.yml

name: Run unit tests, Report coverage

on:
  pull_request:
    paths:
      - app/*
      - .github/workflows/unittests.yml

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checks out the repo
        uses: actions/checkout@v2

      - name: Build docker image
        run: docker-compose -f test_utils/docker-compose.yml build

      - name: Run unit tests & produce coverage report
        # Adapted from the docker example in
        # https://github.com/MishaKav/pytest-coverage-comment?tab=readme-ov-file#example-usage
        run: |
          docker-compose \
            -f test_utils/docker-compose.yml \
            run app \
            pytest \
              --cov-report=term-missing:skip-covered \
              --junitxml=/app/pytest.xml \
              --cov=/app \
              /app \
            | tee pytest-coverage.txt

      - name: Pytest coverage comment
        uses: MishaKav/pytest-coverage-comment@main
        with:
          pytest-coverage-path: pytest-coverage.txt
          junitxml-path: pytest.xml

© www.soinside.com 2019 - 2024. All rights reserved.