英文:
How to pass secrets to testContainers?
问题
以下是您要翻译的部分:
我有以下用于本地开发的Docker Compose文件:
version: '3.4'
networks:
mynetwork:
services:
samba:
image: instantlinux/samba-dc:latest
container_name: samba-dc
cap_add:
- CAP_SYS_ADMIN
hostname: my.org
environment:
DOMAIN_ACTION: provision
REALM: my.org
volumes:
- etc:/etc/samba
- lib:/var/lib/samba
ports:
- "53:53"
- "53:53/udp"
- "88:88"
- "88:88/udp"
- "389:389"
secrets:
- samba-admin-password
volumes:
etc:
lib:
secrets:
samba-admin-password:
file: secrets.yaml
现在我尝试使用testContainers来实施集成测试:
@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
....
init {
try {
val ldapContainer =
GenericContainer("instantlinux/samba-dc:latest")
.withEnv("DOMAIN_ACTION", "provision")
.withEnv("REALM", "my.company")
.withEnv("ADMIN_PASSWORD_SECRET", "samba-admin-password")
.withExposedPorts(53, 88, 389)
ldapContainer.start()
print("Containers has started")
} catch (e: Exception) {
e.printStackTrace()
}
}
但是当我尝试运行它时,我收到以下错误:
Container startup failed for image instantlinux/samba-dc:latest
....
rg.testcontainers.containers.GenericContainer expected the predicate to return <true> but it returned <false> for input of <InspectContainerResponse(args=[], config=ContainerConfig(attachStderr=false, attachStdin=false, attachStdout=false, cmd=null, domainName=, entrypoint=[/usr/local/bin/entrypoint.sh], env=[DOMAIN_ACTION=provision, ADMIN_PASSWORD_SECRET=samba-admin-password, REALM=my.company, PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, ALLOW_DNS_UPDATES=secure, BIND_INTERFACES_ONLY=yes, DOMAIN_LOGONS=yes, DOMAIN_MASTER=no, INTERFACES=lo eth0, LOG_LEVEL=1, MODEL=standard, NETBIOS_NAME=, SERVER_STRING=Samba Domain Controller, TZ=UTC, WINBIND_USE_DEFAULT_DOMAIN=yes, WORKGROUP=AD], exposedPorts=.....
...
17:01:51.548 [Test worker] ERROR tc.instantlinux/samba-dc:latest -- Log output from the failed container:
Set timezone
Cannot read secret $ADMIN_PASSWORD_SECRET in /run/secrets
看起来我必须以某种方式配置秘密,但我看不到如何做到。
更新1
-
秘密文件如下:
```yaml
kind: Secret
apiVersion: v1
metadata:
name: samba-admin-password
data:
ADMIN_PASSWORD_SECRET: superpassword
更新2
根据VonC的答案,我创建了以下示例:
@Testcontainers
@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("test")
class TestContainersBase {
@Test
fun test() {
val mapper = ObjectMapper(YAMLFactory())
val secretPathOnHost = "C:\\work\\MyApp\\docker\\secrets.yaml"
val secretsFile = File(secretPathOnHost)
val secretsData: Map<String, Any> = mapper.readValue(secretsFile, object: TypeReference<Map<String, Any>>() {})
// 从解析的数据中提取秘密
val adminPassword = (secretsData["data"] as Map<*, *>)!!["ADMIN_PASSWORD_SECRET"] as String?
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", adminPassword) // 将提取的秘密设置为环境变量
.withExposedPorts(53, 88, 389)
.withFileSystemBind(secretPathOnHost, secretPathInContainer, BindMode.READ_ONLY);
ldapContainer.start()
print("qwerty")
Thread.sleep(100000000)
}
}
在应用程序日志中,我看到:
2023-08-21T13:38:50.555+03:00 INFO 15136 --- [ Test worker] o.t.utility.ImageNameSubstitutor : Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor')
2023-08-21T13:38:51.739+03:00 INFO 15136 --- [ Test worker] o.t.d.DockerClientProviderStrategy : Loaded org.testcontainers.dockerclient.NpipeSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first
2023-08-21T13:38:52.779+03:00 INFO 15136 --- [ Test worker] o.t.d.DockerClientProviderStrategy : Found Docker environment with local Npipe socket (npipe:////./pipe/docker_engine)
2023-08-21T13:38:52.784+03:00 INFO 15136 --- [ Test worker] org.testcontainers.DockerClientFactory : Docker host IP address is localhost
2023-08-21T13:38:52.814+03:00 INFO 15136 --- [ Test worker] org.testcontainers.DockerClientFactory : Connected to docker:
Server Version: 20.10.21
API Version: 1.41
Operating System: Docker Desktop
Total Memory: 38292 MB
2023-08-21T13:38:52.889+03:00 INFO 15136 --- [ Test worker] tc.testcontainers/ryuk:0.4.0 : Creating container for image: testcontainers/ryuk:0.4.0
2023-08-21T13:38:53.928+03:00 INFO 15136 --- [ Test worker] o.t.utility.RegistryAuthLocator : Credential helper/store (docker-credential-desktop) does not have credentials for https://index.docker.io/v1/
2023-08-21T13:38:54.201+03:00 INFO 15136 --- [ Test
<details>
<summary>英文:</summary>
I have following docker-compose file for local development:
version: '3.4'
networks:
mynetwork:
services:
samba:
image: instantlinux/samba-dc:latest
container_name: samba-dc
cap_add:
- CAP_SYS_ADMIN
hostname: my.org
environment:
DOMAIN_ACTION: provision
REALM: my.org
volumes:
- etc:/etc/samba
- lib:/var/lib/samba
ports:
- "53:53"
- "53:53/udp"
- "88:88"
- "88:88/udp"
- "389:389"
secrets:
- samba-admin-password
volumes:
etc:
lib:
secrets:
samba-admin-password:
file: secrets.yaml
Now I try to implement integration tests using testContainers for that purpose:
@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
....
init {
try {
val ldapContainer =
GenericContainer("instantlinux/samba-dc:latest")
.withEnv("DOMAIN_ACTION", "provision")
.withEnv("REALM", "my.company")
.withEnv("ADMIN_PASSWORD_SECRET", "samba-admin-password")
.withExposedPorts(53, 88, 389)
ldapContainer.start()
print("Containers has started")
} catch (e: Exception) {
e.printStackTrace()
}
}
But when I try to run it I receive an error:
Container startup failed for image instantlinux/samba-dc:latest
....
rg.testcontainers.containers.GenericContainer expected the predicate to return <true> but it returned <false> for input of <InspectContainerResponse(args=[], config=ContainerConfig(attachStderr=false, attachStdin=false, attachStdout=false, cmd=null, domainName=, entrypoint=[/usr/local/bin/entrypoint.sh], env=[DOMAIN_ACTION=provision, ADMIN_PASSWORD_SECRET=samba-admin-password, REALM=my.company, PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, ALLOW_DNS_UPDATES=secure, BIND_INTERFACES_ONLY=yes, DOMAIN_LOGONS=yes, DOMAIN_MASTER=no, INTERFACES=lo eth0, LOG_LEVEL=1, MODEL=standard, NETBIOS_NAME=, SERVER_STRING=Samba Domain Controller, TZ=UTC, WINBIND_USE_DEFAULT_DOMAIN=yes, WORKGROUP=AD], exposedPorts=....
...
17:01:51.548 [Test worker] ERROR tc.instantlinux/samba-dc:latest -- Log output from the failed container:
Set timezone
Cannot read secret $ADMIN_PASSWORD_SECRET in /run/secrets
Looks like I have to configure secrets somehow but I don' see a way how to acheve it.
Update 1
-
Secret file looks like this:
kind: Secret
apiVersion: v1
metadata:
name: samba-admin-password
data:
ADMIN_PASSWORD_SECRET: superpassword
Update 2
-
Based on VonC answer I've created the example:
@Testcontainers
@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("test")
class TestContainersBase {
@Test
fun test() {
val mapper = ObjectMapper(YAMLFactory())
val secretPathOnHost = "C:\\work\\MyApp\\docker\\secrets.yaml"
val secretsFile = File(secretPathOnHost)
val secretsData: Map<String, Any> = mapper.readValue(secretsFile, object: TypeReference<Map<String, Any>>(){})
// Extract the secret from the parsed data
val adminPassword = (secretsData["data"] as Map<*,*>?)!!["ADMIN_PASSWORD_SECRET"] as String?
val secretPathInContainer = "/run/secrets/samba-admin-password";
// Create and start the container
val ldapContainer = GenericContainer("instantlinux/samba-dc:latest")
.withEnv("DOMAIN_ACTION", "provision")
.withEnv("REALM", "my.company")
.withEnv("ADMIN_PASSWORD_SECRET", adminPassword) // Set the extracted secret as an environment variable
.withExposedPorts(53, 88, 389)
.withFileSystemBind(secretPathOnHost, secretPathInContainer, BindMode.READ_ONLY);
ldapContainer.start()
print("qwerty")
Thread.sleep(100000000)
}
}
In app logs I see:
2023-08-21T13:38:50.555+03:00 INFO 15136 --- [ Test worker] o.t.utility.ImageNameSubstitutor : Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor')
2023-08-21T13:38:51.739+03:00 INFO 15136 --- [ Test worker] o.t.d.DockerClientProviderStrategy : Loaded org.testcontainers.dockerclient.NpipeSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first
2023-08-21T13:38:52.779+03:00 INFO 15136 --- [ Test worker] o.t.d.DockerClientProviderStrategy : Found Docker environment with local Npipe socket (npipe:////./pipe/docker_engine)
2023-08-21T13:38:52.784+03:00 INFO 15136 --- [ Test worker] org.testcontainers.DockerClientFactory : Docker host IP address is localhost
2023-08-21T13:38:52.814+03:00 INFO 15136 --- [ Test worker] org.testcontainers.DockerClientFactory : Connected to docker:
Server Version: 20.10.21
API Version: 1.41
Operating System: Docker Desktop
Total Memory: 38292 MB
2023-08-21T13:38:52.889+03:00 INFO 15136 --- [ Test worker] tc.testcontainers/ryuk:0.4.0 : Creating container for image: testcontainers/ryuk:0.4.0
2023-08-21T13:38:53.928+03:00 INFO 15136 --- [ Test worker] o.t.utility.RegistryAuthLocator : Credential helper/store (docker-credential-desktop) does not have credentials for https://index.docker.io/v1/
2023-08-21T13:38:54.201+03:00 INFO 15136 --- [ Test worker] tc.testcontainers/ryuk:0.4.0 : Container testcontainers/ryuk:0.4.0 is starting: b4a10e2647f83d6fc404644fb09edabf930e987e2c5d138eb3d1b9414b1400ac
2023-08-21T13:38:55.320+03:00 INFO 15136 --- [ Test worker] tc.testcontainers/ryuk:0.4.0 : Container testcontainers/ryuk:0.4.0 started in PT2.488268S
2023-08-21T13:38:55.330+03:00 INFO 15136 --- [ Test worker] o.t.utility.RyukResourceReaper : Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
2023-08-21T13:38:55.330+03:00 INFO 15136 --- [ Test worker] org.testcontainers.DockerClientFactory : Checking the system...
2023-08-21T13:38:55.332+03:00 INFO 15136 --- [ Test worker] org.testcontainers.DockerClientFactory : ?? Docker server version should be at least 1.6.0
2023-08-21T13:38:55.334+03:00 INFO 15136 --- [ Test worker] tc.instantlinux/samba-dc:latest : Creating container for image: instantlinux/samba-dc:latest
2023-08-21T13:38:56.834+03:00 INFO 15136 --- [ Test worker] tc.instantlinux/samba-dc:latest : Container instantlinux/samba-dc:latest is starting: 496246f47398809c3a7327b0c73a9b7d7fbe6440865b1cad4c124849f6069acb
2023-08-21T13:39:07.361+03:00 WARN 15136 --- [ntainers-wait-0] .c.w.i.InternalCommandPortListeningCheck : An exception while executing the internal check: Container.ExecResult(exitCode=137, stdout=, stderr=/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
/bin/sh: /bin/bash: not found
)
2023-08-21T13:39:07.367+03:00 INFO 15136 --- [ Test worker] tc.instantlinux/samba-dc:latest : Container instantlinux/samba-dc:latest started in PT12.0305603S
In docker desktop:
[![enter image description here][1]][1]
And the first container(based on ports I think that it is Samba) logs:
2023-08-21 13:38:58 Set timezone
2023-08-21 13:38:59 INFO 2023-08-21 10:38:59,067 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #2108: Looking up IPv4 addresses
2023-08-21 13:38:59 INFO 2023-08-21 10:38:59,068 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #2125: Looking up IPv6 addresses
2023-08-21 13:38:59 WARNING 2023-08-21 10:38:59,068 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #2132: No IPv6 address will be assigned
2023-08-21 13:38:59 INFO 2023-08-21 10:38:59,721 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #2274: Setting up share.ldb
2023-08-21 13:38:59 INFO 2023-08-21 10:38:59,874 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #2278: Setting up secrets.ldb
2023-08-21 13:38:59 INFO 2023-08-21 10:38:59,936 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #2283: Setting up the registry
2023-08-21 13:39:00 INFO 2023-08-21 10:39:00,304 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #2286: Setting up the privileges database
2023-08-21 13:39:00 INFO 2023-08-21 10:39:00,466 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #2289: Setting up idmap db
2023-08-21 13:39:00 INFO 2023-08-21 10:39:00,555 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #2296: Setting up SAM db
2023-08-21 13:39:00 INFO 2023-08-21 10:39:00,573 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #880: Setting up sam.ldb partitions and settings
2023-08-21 13:39:00 INFO 2023-08-21 10:39:00,574 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #892: Setting up sam.ldb rootDSE
2023-08-21 13:39:00 INFO 2023-08-21 10:39:00,591 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1305: Pre-loading the Samba 4 and AD schema
2023-08-21 13:39:00 Unable to determine the DomainSID, can not enforce uniqueness constraint on local domainSIDs
2023-08-21 13:39:00
2023-08-21 13:39:00 INFO 2023-08-21 10:39:00,638 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1383: Adding DomainDN: DC=my,DC=company
2023-08-21 13:39:00 INFO 2023-08-21 10:39:00,659 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1415: Adding configuration container
2023-08-21 13:39:00 INFO 2023-08-21 10:39:00,678 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1430: Setting up sam.ldb schema
2023-08-21 13:39:03 INFO 2023-08-21 10:39:03,229 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1448: Setting up sam.ldb configuration data
2023-08-21 13:39:03 INFO 2023-08-21 10:39:03,356 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1489: Setting up display specifiers
2023-08-21 13:39:05 INFO 2023-08-21 10:39:05,522 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1497: Modifying display specifiers and extended rights
2023-08-21 13:39:05 INFO 2023-08-21 10:39:05,569 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1504: Adding users container
2023-08-21 13:39:05 INFO 2023-08-21 10:39:05,570 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1510: Modifying users container
2023-08-21 13:39:05 INFO 2023-08-21 10:39:05,571 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1513: Adding computers container
2023-08-21 13:39:05 INFO 2023-08-21 10:39:05,572 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1519: Modifying computers container
2023-08-21 13:39:05 INFO 2023-08-21 10:39:05,574 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1523: Setting up sam.ldb data
2023-08-21 13:39:05 INFO 2023-08-21 10:39:05,728 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1553: Setting up well known security principals
2023-08-21 13:39:05 INFO 2023-08-21 10:39:05,770 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1567: Setting up sam.ldb users and groups
2023-08-21 13:39:05 INFO 2023-08-21 10:39:05,993 pid:18 /usr/lib/python3.10/site-packages/samba/provision/__init__.py #1575: Setting up self join
2023-08-21 13:39:06 Repacking database from v1 to v2 format (first record CN=Structural-Object-Class,CN=Schema,CN=Configuration,DC=my,DC=company)
2023-08-21 13:39:06 Repack: re-packed 10000 records so far
2023-08-21 13:39:06 Repacking database from v1 to v2 format (first record CN=nTDSSiteSettings-Display,CN=406,CN=DisplaySpecifiers,CN=Configuration,DC=my,DC=company)
2023-08-21 13:39:06 Repacking database from v1 to v2 format (first record CN=ObjectMoveTable,CN=FileLinks,CN=System,DC=my,DC=company)
2023-08-21 13:39:07 set_nt_acl_no_snum: fset_nt_acl returned NT_STATUS_ACCESS_DENIED.
2023-08-21 13:39:07 ERROR(runtime): uncaught exception - (3221225506, '{Access Denied} A process has requested access to an object but has not been granted those access rights.')
2023-08-21 13:39:07 File "/usr/lib/python3.10/site-packages/samba/netcmd/__init__.py", line 186, in _run
2023-08-21 13:39:07 return self.run(*args, **kwargs)
2023-08-21 13:39:07 File "/usr/lib/python3.10/site-packages/samba/netcmd/domain.py", line 493, in run
2023-08-21 13:39:07 result = provision(self.logger,
2023-08-21 13:39:07 File "/usr/lib/python3.10/site-packages/samba/provision/__init__.py", line 2325, in provision
2023-08-21 13:39:07 provision_fill(samdb, secrets_ldb, logger, names, paths,
2023-08-21 13:39:07 File "/usr/lib/python3.10/site-packages/samba/provision/__init__.py", line 1965, in provision_fill
2023-08-21 13:39:07 setsysvolacl(samdb, paths.netlogon, paths.sysvol, paths.root_uid,
2023-08-21 13:39:07 File "/usr/lib/python3.10/site-packages/samba/provision/__init__.py", line 1742, in setsysvolacl
2023-08-21 13:39:07 _setntacl(sysvol)
2023-08-21 13:39:07 File "/usr/lib/python3.10/site-packages/samba/provision/__init__.py", line 1736, in _setntacl
2023-08-21 13:39:07 return setntacl(
2023-08-21 13:39:07 File "/usr/lib/python3.10/site-packages/samba/ntacls.py", line 228, in setntacl
2023-08-21 13:39:07 smbd.set_nt_acl(
**docker ps**
PS C:\work\myApp\docker> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5541e9f96005 testcontainers/ryuk:0.4.0 "/bin/ryuk" 24 seconds ago Up 23 seconds 0.0.0.0:64762->8080/tcp testcontainers-ryuk-6d02415f-7042-4de8-bf0d-a1be71ea5172
PS C:\work\myApp\docker>
[1]: https://i.stack.imgur.com/2WJiX.png
</details>
# 答案1
**得分**: 3
[Testcontainers](https://testcontainers.com/) 看起来不直接支持 Docker Compose 的 secrets。唯一关于 secret 的概念是在使用 [HashiCorp Vault Module](https://java.testcontainers.org/modules/vault/) 时的 `.withSecretInVault()`。
在你的情况下,你可以尝试使用卷来模拟一个 secret:这是一个解决方法,将你的 secrets 绑定挂载到容器中的期望路径。
```java
val secretPathOnHost = "/path/to/your/secrets.yaml";
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")
.withExposedPorts(53, 88, 389)
.withFileSystemBind(secretPathOnHost, secretPathInContainer, BindMode.READ_ONLY);
ldapContainer.start();
请将 /path/to/your/secrets.yaml
替换为主机上 secrets.yaml
文件的绝对路径。
注意:通过卷来模拟 secrets 意味着该 secret 在你的主机系统上以明文文件的形式可用,所以确保正确管理其权限和访问。这对于本地开发和测试可能没问题,但在类似于生产的环境中可能不太理想。
而且... 永远不要将 secrets 或 secret 路径提交到源代码控制中。
由于 secret 文件如下:
kind: Secret
apiVersion: v1
metadata:
name: samba-admin-password
data:
ADMIN_PASSWORD_SECRET: superpassword
鉴于这种格式,类似于 Kubernetes secret,你需要在测试设置中解析该文件,然后将 secret 设置为容器的环境变量。
使用 testcontainers
和 Jackson 库进行 YAML 解析:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.io.File;
import java.util.Map;
// ...
// 加载并解析 secrets.yaml 文件
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
File secretsFile = new File("/path/to/your/secrets.yaml");
Map<String, Object> secretsData = mapper.readValue(secretsFile, Map.class);
// 从解析的数据中提取 secret
String adminPassword = (String) ((Map) secretsData.get("data")).get("ADMIN_PASSWORD_SECRET");
// 创建并启动容器
val ldapContainer = GenericContainer("instantlinux/samba-dc:latest")
.withEnv("DOMAIN_ACTION", "provision")
.withEnv("REALM", "my.company")
.withEnv("ADMIN_PASSWORD_SECRET", adminPassword) // 将提取的 secret 设置为环境变量
.withExposedPorts(53, 88, 389);
ldapContainer.start();
这种方法涉及将 secret 读入你的 Java 应用程序,然后将其作为环境变量传递给容器。
从 OP 提供的示例中,看起来是在 Spring Boot 应用程序中使用 Testcontainers 启动的 Samba 容器。容器似乎启动正确,因为你可以看到 Samba 的初始化日志。
主要问题是 samba 容器在启动后立即关闭(应用程序在 Thread sleep 中挂起)。看起来根本原因可能在于 samba 日志中找到:
2023-08-21 13:39:07 ERROR(runtime): uncaught exception - (3221225506, '{Access Denied} A process has requested access to an object but has not been granted those access rights.')
由于你正在使用 Docker,请记住 Samba 容器将有自己的用户系统。如果你挂载了卷,可能需要调整用户或组 ID 以与主机系统匹配。
在容器的入口点中添加 id -a
和 ls -alrth /path/to/your/secrets.yaml
命令,以查看你在容器内是谁,以及你如何看待挂载的文件系统。
检查任何挂载到容器内的卷的所有权和权限。容器内部的 UID 和 GID 可能与外部不同,导致权限问题。
如果在 Docker 容器内运行 Samba,请确保根据需要提供所有必要的权限,使用 --cap-add
。
检查你的 Samba 配置 (smb.conf
)。确保所定义的共享和路径具有正确的权限。还要检查是否有任何 valid users
、read list
或 write list
指令,并确保列出的用户具有适当的权限。
如果你运行的系统启用了 SELinux,这可能会导致权限问题。你可以将 SELinux 临时设置为宽松模式,以查看是否解决了问题:
sudo setenforce 0
如果这解决了问题,你需要创建适当的 SELinux 策略或调整与 Samba 相关的文件和目录的上下文。
英文:
Testcontainers does not seem to support Docker Compose's secrets directly. The only notion of secret is when using a HashiCorp Vault Module .withSecretInVault()
.
In your case, you can try and use a volume to emulate a secret: it is a workaround, a volume to bind-mount your secrets into the container at the expected path.
val secretPathOnHost = "/path/to/your/secrets.yaml";
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")
.withExposedPorts(53, 88, 389)
.withFileSystemBind(secretPathOnHost, secretPathInContainer, BindMode.READ_ONLY);
ldapContainer.start();
Do replace /path/to/your/secrets.yaml
with the absolute path to your secrets.yaml
file on the host machine.
Note: Emulating secrets as volumes means the secret is available as a plaintext file on your host system, so make sure you manage its permissions and access properly. That might be fine for local development and testing, but might not be ideal for production-like environments.
And... never commit secrets or secret paths to source control.
Since the secret file is:
kind: Secret
apiVersion: v1
metadata:
name: samba-admin-password
data:
ADMIN_PASSWORD_SECRET: superpassword
Given this format, which is similar to a Kubernetes secret, you will need to parse the file in your test setup and then set the secret as an environment variable to the container.
Using testcontainers
and the Jackson library for YAML parsing:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.io.File;
import java.util.Map;
// ...
// Load and parse the secrets.yaml file
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
File secretsFile = new File("/path/to/your/secrets.yaml");
Map<String, Object> secretsData = mapper.readValue(secretsFile, Map.class);
// Extract the secret from the parsed data
String adminPassword = (String) ((Map) secretsData.get("data")).get("ADMIN_PASSWORD_SECRET");
// Create and start the container
val ldapContainer = GenericContainer("instantlinux/samba-dc:latest")
.withEnv("DOMAIN_ACTION", "provision")
.withEnv("REALM", "my.company")
.withEnv("ADMIN_PASSWORD_SECRET", adminPassword) // Set the extracted secret as an environment variable
.withExposedPorts(53, 88, 389);
ldapContainer.start();
That method involves reading the secret into your Java application, which you then pass as an environment variable to the container.
From the example provided by the OP, it looks like a Samba container using Testcontainers in a Spring Boot application. The container seems to be starting correctly as you can see the initialization logs of Samba.
> The main problem that samba container shutdown immediately after start(application is hanging on in Thread sleep). Looks like root cause could be find in samba logs:
>
> 2023-08-21 13:39:07 ERROR(runtime): uncaught exception - (3221225506, '{Access Denied} A process has requested access to an object but has not been granted those access rights.')
Since you are using Docker, remember that the Samba container will have its own user system. You may need to adjust the user or group IDs to match your host system if you are mounting volumes.
Add in your container entry point the id -a
and ls -alrth /path/to/your/secrets.yaml
commands to see who you are inside the container, and how you see the mounted file system.
Check the ownership and permissions of any volumes you have mounted into the container. The UID and GID inside the container might differ from those outside, leading to permission issues.
If you are running Samba inside a Docker container, ensure that you have provided all necessary capabilities using --cap-add
if needed.
Review your Samba configuration (smb.conf
). Ensure that the shares and paths defined have the correct permissions.
Also, check for any valid users
, read list
, or write list
directives and ensure that the users listed have the appropriate permissions.
And if you are running a system with SELinux enabled, this can cause permission issues. You can temporarily set SELinux to permissive mode to see if it resolves the issue:
sudo setenforce 0
If this resolves the issue, you will need to create the appropriate SELinux policies or adjust the context for the Samba-related files and directories.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论