在 GitHub 运行器中的 python 子进程中运行 docker 命令

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

我正在我的 GitHub 运行器中以 CI 方式运行功能测试。 为了正确执行我的测试,我正在构建一个 docker 映像并运行它(一个稍作修改的 mysql 容器)。因为我是从 Dockerfile 构建容器(不仅仅是从注册表中提取它),所以我不使用 GitHub

service
container
功能 (https://docs.github.com/en/actions/use-cases -and-examples/using-containerized-services/about-service-containers).

相反,我在 GH 工作流程中专门做了一些步骤来构建容器并像这样运行它

  - name: build docker container
    run: |
      cd tests/functional/olbp/mocked_data/
      docker build --no-cache -f my_service.Dockerfile -t my_service_test:latest .
  - name: run container
    run: docker run --name my_service -d -p 127.0.0.1:3306:3306 my_service_test --sql_mode="NO_ENGINE_SUBSTITUTION"
  - name: wait for MySQL to start
    run: |
      until mysqladmin ping -h 127.0.0.1 --silent; do
      echo 'Waiting for MySQL to start...'
      sleep 1
      done

最后我用 python 调用我的功能测试(pytest)

  - name: run the functional tests
    run: python -m pytest tests/functional -vv -s --log-cli-level=DEBUG

这工作正常,我的测试可以明显地与 mysql 容器交互。

然而,在这种情况下我很难与 Docker 进行交互。我想生成我的测试的 mysqldump 部分。所以我在测试中写了这个:

dck_exc_output = subprocess.run(
    [
        "docker",
        "exec",
        "my_service",
        "mysqldump",
        "--skip-triggers",
        "--skip-extended-insert",
        "--compact",
        "--no-create-info",
        "-uroot",
        "-psupersecret",
        "my_db",
        "my_table",
        ">",
        live_data_dump,
    ],
    capture_output=True,
    shell=True,
)

logging.debug(dck_exc_output)

从我的计算机执行时它工作正常,但每当我尝试在 GH Runner 中执行它时(这个 docker 命令甚至是简单的 docker 版本)。我最终得到这个输出:

DEBUG    root:my_test.py:246 CompletedProcess(args=['docker', 'version'], returncode=0, stdout=b'', stderr=b'
Usage:  docker [OPTIONS] COMMAND

...
')

我已经确认我在子进程和 GH 运行程序命令之间具有相同的用户、相同的权限和相同的环境变量。
我不明白为什么我会收到这个输出。 docker 可执行文件似乎已找到(因为我收到帮助页面,就好像我执行了错误的命令一样),但它不会像我在本地运行测试时那样执行。

python docker subprocess github-actions pytest
1个回答
0
投票

您的 Python 代码中有错误。您尝试在

subprocess.run()
的参数中使用 shell i/o 重定向,但是 (a) 您没有设置
shell=True
并且 (b) 您传递的是参数列表而不是字符串。

如果您想使用 shell i/o 重定向(如

somecommand > somefile
),您只能将单个字符串作为参数传递给
subprocess.run
,并且必须设置
shell=True
:

subprocess.run(
f'docker exec my_service mysqldump --skip-triggers --skip-extended-insert --compact --no-create-info -uroot -psupersecret my_db my_table > {live_data_dump}',
shell=True
)

如果您不设置

shell=True
,那么您的命令不会由 shell 执行,并且像
>
这样的内容会按字面意思传递给正在执行的命令。

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