如何在TestContainers中为instantlinux/samba-dc容器传递密钥并解决启动权限问题?
如何在TestContainers中为instantlinux/samba-dc容器传递密钥并解决启动权限问题?
看起来你在把本地的Samba DC Docker Compose配置迁移到TestContainers时遇到了两个核心问题:密钥读取失败,以及容器启动时的权限和健康检查报错。我来帮你一步步梳理解决方法:
一、先解决密钥传递的核心问题
你的原Docker Compose用了Docker Secrets,但TestContainers默认不会自动处理Kubernetes格式的Secret文件,而且容器本身其实支持更简单的密码传递方式:
方式1:直接用环境变量传递明文密码(测试环境推荐)
这个Samba DC镜像支持直接通过ADMIN_PASSWORD环境变量设置管理员密码,不需要绕secret文件,这样在测试环境里更省心:
val ldapContainer = GenericContainer("instantlinux/samba-dc:latest") .withEnv("DOMAIN_ACTION", "provision") .withEnv("REALM", "my.company") .withEnv("ADMIN_PASSWORD", "superpassword") // 直接设置明文密码 // 其他配置...
方式2:正确挂载本地密钥文件(如果坚持用secret文件)
如果一定要用secret文件,注意两个关键点:
- 容器期望
/run/secrets/samba-admin-password文件里直接是明文密码,而不是你现在用的Kubernetes Secret格式(base64编码的yaml)。你需要创建一个纯文本文件,比如admin-password.txt,里面只写superpassword。 - 用TestContainers的文件挂载功能把这个文件映射到容器的指定路径:
val secretPathOnHost = "C:\\work\\MyApp\\docker\\admin-password.txt" val secretPathInContainer = "/run/secrets/samba-admin-password" val ldapContainer = GenericContainer("instantlinux/samba-dc:latest") .withEnv("DOMAIN_ACTION", "provision") .withEnv("REALM", "my.company") .withEnv("ADMIN_PASSWORD_SECRET", "samba-admin-password") // 告诉容器读取这个secret .withFileSystemBind(secretPathOnHost, secretPathInContainer, BindMode.READ_ONLY) // 其他配置...
二、解决容器启动的权限和健康检查问题
从你的日志来看,还有两个关键问题需要处理:
1. 添加必要的系统权限
Samba DC需要CAP_SYS_ADMIN权限才能正常初始化(原Docker Compose里也加了这个),你需要在TestContainers里添加这个能力:
.withCreateContainerCmdModifier { cmd -> cmd.hostConfig!!.withCapAdd("CAP_SYS_ADMIN") }
2. 修复健康检查的bash缺失问题
这个容器的基础镜像没有安装bash,但TestContainers默认用bash执行健康检查命令,导致报错/bin/sh: /bin/bash: not found。你需要自定义健康检查,用sh来执行:
.withHealthCheck( HealthCheck.newInstance() .withTestCommand("sh -c \"nc -z localhost 389 || exit 1\"") .withInterval(Duration.ofSeconds(5)) .withTimeout(Duration.ofSeconds(10)) .withRetries(5) )
三、完整的可运行代码示例
把上面的配置整合起来,最终的TestContainers代码应该是这样的:
@Testcontainers @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles("test") class TestContainersBase { @Test fun testSambaContainer() { val ldapContainer = GenericContainer("instantlinux/samba-dc:latest") // 基础环境配置 .withEnv("DOMAIN_ACTION", "provision") .withEnv("REALM", "my.company") .withEnv("ADMIN_PASSWORD", "superpassword") // 直接用环境变量传密码 // 暴露必要端口 .withExposedPorts(53, 88, 389) // 添加Samba需要的系统权限 .withCreateContainerCmdModifier { cmd -> cmd.hostConfig!!.withCapAdd("CAP_SYS_ADMIN") } // 自定义健康检查,避免bash缺失问题 .withHealthCheck( HealthCheck.newInstance() .withTestCommand("sh -c \"nc -z localhost 389 || exit 1\"") .withInterval(Duration.ofSeconds(5)) .withTimeout(Duration.ofSeconds(10)) .withRetries(5) ) ldapContainer.start() println("Samba DC容器启动成功!") // 这里可以添加你的测试逻辑 Thread.sleep(10000) ldapContainer.stop() } }
四、额外注意事项
- 如果你的测试需要持久化Samba的数据,可以添加临时卷绑定:
.withFileSystemBind("本地路径", "/var/lib/samba", BindMode.READ_WRITE),不过测试环境一般用容器临时卷就足够了。 - 日志里的
Unable to determine the DomainSID警告可以忽略,这是容器初始化过程中的正常信息,不影响功能。 - 确保你的Docker Desktop已经开启了必要的权限(比如文件共享,如果你用Windows的话)。
备注:内容来源于stack exchange,提问作者gstackoverflow
相关产品推荐
相关产品推荐

