You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在GitLab Runner的Docker-in-Docker环境中实现Pytest与容器间的共享内存通信

在GitLab Runner的Docker-in-Docker环境中实现Pytest与容器间的共享内存通信

我太懂你这种本地跑通的逻辑到CI环境就卡壳的痛苦了!其实你遇到的核心问题是:你的Pytest容器和DIND服务里启动的测试容器,根本不在同一个Docker环境里——Pytest跑在GitLab Runner直接启动的容器里,而测试容器跑在DIND服务容器的独立Docker daemon中,两者默认完全隔离,自然没法共享IPC或者内存。下面给你两个最可行的解决方案,帮你彻底解决问题:

方案一:让Pytest直接在DIND容器内运行(最省心,无需修改Runner配置)

这个方案直接消除了Docker环境隔离的问题,让Pytest和测试容器处于同一个Docker daemon下,你本地的代码几乎不用改就能跑通。

调整GitLab CI配置

把原来的job镜像换成dind镜像,同时修改DOCKER_HOST为本地套接字,这样Pytest里的Docker SDK直接调用本地的Docker daemon(也就是DIND本身的daemon):

unittest:
  image: name: docker:27.0.2-dind
  pull_policy: if-not-present
  tags:
    - general-runner-dind
  variables:
    DOCKER_HOST: unix:///var/run/docker.sock  # 直接使用本地Docker daemon
    DOCKER_TLS_CERTDIR: ""
    FF_NETWORK_PER_BUILD: "true"
  before_script:
    - apk update && apk upgrade && apk add --no-cache python3 python3-dev py3-pip curl
    - curl -LsSf https://astral.sh/uv/0.6.17/install.sh | sh
    - source $HOME/.local/bin/env
  script:
    - cd /path/to/project
    - uv sync --frozen
    - uv run --no-sync pytest

复用你原来的代码逻辑

现在Pytest和测试容器在同一个Docker环境里,你可以直接用两种方式实现共享内存:

  1. 挂载/dev/shm:和本地逻辑完全一致,直接绑定/dev/shm挂载即可,因为两者共享同一个DIND容器的内存空间。
  2. 共享IPC命名空间:现在可以正常获取当前容器ID了,你可以用CI_CONTAINER_ID这个GitLab内置环境变量直接拿到Pytest所在容器的ID,不用自己解析cgroup:
import os
from multiprocessing import shared_memory
import docker

shm_name = "test_shm"
shm = shared_memory.SharedMemory(create=True, name=shm_name, size=int(1e6))

cid = os.getenv("CI_CONTAINER_ID")
client = docker.from_env()

if cid:
    # 在CI环境,共享Pytest容器的IPC命名空间
    client.containers.run(
        image="alpine",
        name="my_container",
        detach=True,
        remove=True,
        command="tail -f /dev/null",
        ipc_mode=f"container:{cid}",
        environment={"SHM_NAME": shm_name}
    )
else:
    # 本地环境,挂载/dev/shm
    shm_mount = docker.types.Mount(source="/dev/shm", target="/dev/shm", type="bind")
    client.containers.run(
        image="alpine",
        name="my_container",
        detach=True,
        remove=True,
        command="tail -f /dev/null",
        mounts=[shm_mount],
        environment={"SHM_NAME": shm_name}
    )

方案二:跨Docker环境共享主机内存(需修改Runner配置)

如果你必须保持Pytest在单独的容器里,那得让两个Docker环境共享主机的/dev/shm,这样Pytest容器和DIND里的测试容器都能访问同一块共享内存。

步骤1:修改GitLab Runner配置

在Runner的config.toml文件中,给Runner添加/dev/shm的挂载权限:

[[runners]]
  name = "general-runner-dind"
  url = "https://your-gitlab-instance.com/"
  token = "your-runner-token"
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "docker:latest"
    privileged = true  # DIND需要特权模式
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/dev/shm:/dev/shm", "/cache"]  # 添加/dev/shm挂载
    shm_size = 0

步骤2:调整CI配置,让Pytest和DIND容器都挂载主机/dev/shm

unittest:
  image: name: docker:27.0.2
  pull_policy: if-not-present
  tags:
    - general-runner-dind
  services:
    - name: docker:27.0.2-dind
      alias: docker-service
      command: [dockerd-entrypoint.sh, --tls=0]
      volumes:
        - /dev/shm:/dev/shm  # DIND容器挂载主机/dev/shm
  variables:
    DOCKER_HOST: tcp://docker-service:2375
    DOCKER_TLS_CERTDIR: ""
    FF_NETWORK_PER_BUILD: "true"
  volumes:
    - /dev/shm:/dev/shm  # Pytest容器挂载主机/dev/shm
  before_script:
    - apk update && apk upgrade && apk add --no-cache python3 python3-dev py3-pip curl
    - curl -LsSf https://astral.sh/uv/0.6.17/install.sh | sh
    - source $HOME/.local/bin/env
  script:
    - cd /path/to/project
    - uv sync --frozen
    - uv run --no-sync pytest

复用本地挂载逻辑

现在Pytest和测试容器都挂载了主机的/dev/shm,你本地的挂载代码可以直接复用,不需要任何修改——测试容器绑定的/dev/shm就是主机的内存区域,和Pytest容器的/dev/shm完全一致,共享内存自然能互通。

为什么你之前的思路没成功?

你之前尝试的两种方法都因为Docker环境隔离失败:

  1. 获取Pytest容器ID:Pytest容器属于Runner的Docker daemon,而测试容器属于DIND的Docker daemon,两者不在同一个实例下,就算拿到ID也没法共享IPC。
  2. IPC锚点容器:锚点容器属于DIND的Docker daemon,Pytest容器属于Runner的Docker daemon,两者IPC命名空间完全隔离,自然没法访问彼此的共享内存。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 06:44:33