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

GitLab CI/CD下无根Podman环境中实现DinD以支持Testcontainers

在无根Podman的GitLab Runner上用Testcontainers做C#集成测试的解决方案

核心思路

不需要依赖DinD(Docker-in-Docker),直接利用无根Podman的用户级socket让Testcontainers对接Podman服务。Testcontainers原生支持Podman驱动,只要让CI作业能访问Podman的socket,同时配置环境变量适配即可。

具体实现步骤

1. 配置GitLab Runner的Podman执行器

确保Runner使用podman执行器,并挂载Podman的用户socket到作业容器中。修改Runner的config.toml配置文件:

[[runners]]
  name = "Podman Runner"
  executor = "podman"
  [runners.podman]
    image = "mcr.microsoft.com/dotnet/sdk:8.0"
    volumes = ["/run/user/1000/podman/podman.sock:/var/run/docker.sock", "/cache"]
    # 替换1000为Podman运行的实际用户ID
  • 把Podman的socket映射为/var/run/docker.sock,因为Testcontainers默认会查找这个路径,Podman兼容Docker的API。
  • 确保Runner运行的用户ID和Podman的用户ID一致,避免权限冲突。

2. GitLab CI YAML配置

不需要启动额外的Podman服务,直接在测试作业中配置环境变量并挂载socket:

stages:
  - integration-test

integration-test:
  stage: integration-test
  image: mcr.microsoft.com/dotnet/sdk:8.0
  before_script:
    # 安装Podman客户端(如果镜像未预装)
    - apt-get update && apt-get install -y --no-install-recommends podman
  variables:
    # 告诉Testcontainers使用挂载的socket
    TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE: /var/run/docker.sock
    # 无根Podman不支持Ryuk(容器清理工具),临时禁用
    TESTCONTAINERS_RYUK_DISABLE: "true"
    # 指定Docker主机为Podman的socket路径
    DOCKER_HOST: unix:///var/run/docker.sock
  script:
    - dotnet restore
    - dotnet test --filter Category=Integration --verbosity normal
  volumes:
    - /run/user/1000/podman/podman.sock:/var/run/docker.sock

3. C# Testcontainers代码适配

使用v3.x及以上版本的Testcontainers NuGet包(已原生支持Podman),代码无需额外修改即可自动适配:

using Testcontainers.PostgreSql;

public class DatabaseIntegrationTests
{
    private readonly PostgreSqlContainer _dbContainer = new PostgreSqlBuilder()
        .WithImage("postgres:15-alpine")
        .WithPassword("Test123!")
        .Build();

    [OneTimeSetUp]
    public async Task Setup()
    {
        await _dbContainer.StartAsync();
        // 用_dbContainer.GetConnectionString()初始化数据库上下文
    }

    [OneTimeTearDown]
    public async Task TearDown()
    {
        await _dbContainer.StopAsync();
    }

    [Test]
    public async Task TestDatabaseConnection()
    {
        // 编写集成测试逻辑
    }
}

如果需要显式指定Podman驱动,可添加配置:

var container = new ContainerBuilder()
    .WithImage("rabbitmq:3-management")
    .WithDriver(DriverPodman)
    .Build();

4. 权限问题排查与解决

  • socket权限冲突:如果作业提示无法访问socket,检查Podman用户ID和Runner用户ID是否一致。在Runner主机执行id -u获取Podman用户ID,替换配置中的1000。
  • 无根Podman依赖:确保管理员已启用系统user.namespaces功能,临时启用可执行sysctl kernel.unprivileged_userns_clone=1,永久生效需写入/etc/sysctl.conf。
  • 安全权限原则:不要直接给socket设置chmod 666,优先用同用户ID的方式保证权限安全。

5. 验证步骤

在CI作业的before_script中添加podman info命令,确认能正常连接到Podman服务:

- podman info

如果输出包含Podman版本和配置信息,说明socket挂载成功。

内容的提问来源于stack exchange,提问作者Foitn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 11:20:57