Problem
I want to start a MySQLContainer from a junit test with mvn clean verify
. But for some reason it can't chown the container folder for my host user.
Here is a screenshot that illustrates the problem:
org.testcontainers.containers.ContainerLaunchException: Container startup failed for image mysql:8.0.33 at com.xyzcorp.StudentServiceCopyTest.testMySQL8(StudentServiceCopyTest.java:61) Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception at com.xyzcorp.StudentServiceCopyTest.testMySQL8(StudentServiceCopyTest.java:61) Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container at com.xyzcorp.StudentServiceCopyTest.testMySQL8(StudentServiceCopyTest.java:61) Caused by: com.github.dockerjava.api.exception.InternalServerErrorException: Status 500: {"cause":"error during bulk transfer for copier.request{Request:\"PUT\", Root:\"/\", preservedRoot:\"/home/jvanmont/.local/share/containers/storage/overlay/297e95cb55db40d82aa6e025772f7e05a009d64f5563ac3421e34592209e8627/merged\", rootPrefix:\"/home/jvanmont/.local/share/containers/storage/overlay/297e95cb55db40d82aa6e025772f7e05a009d64f5563ac3421e34592209e8627/merged\", Directory:\"/\", preservedDirectory:\"/home/jvanmont/.local/share/containers/storage/overlay/297e95cb55db40d82aa6e025772f7e05a009d64f5563ac3421e34592209e8627/merged\", Globs:[]string{}, preservedGlobs:[]string{}, StatOptions:copier.StatOptions{CheckForArchives:false, Excludes:[]string(nil)}, GetOptions:copier.GetOptions{UIDMap:[]idtools.IDMap(nil), GIDMap:[]idtools.IDMap(nil), Excludes:[]string(nil), ExpandArchives:false, ChownDirs:(*idtools.IDPair)(nil), ChmodDirs:(*fs.FileMode)(nil), ChownFiles:(*idtools.IDPair)(nil), ChmodFiles:(*fs.FileMode)(nil), StripSetuidBit:false, StripSetgidBit:false, StripStickyBit:false, StripXattrs:false, KeepDirectoryNames:false, Rename:map[string]string(nil), NoDerefSymlinks:false, IgnoreUnreadable:false, NoCrossDevice:false}, PutOptions:copier.PutOptions{UIDMap:[]idtools.IDMap(nil), GIDMap:[]idtools.IDMap(nil), DefaultDirOwner:(*idtools.IDPair)(nil), DefaultDirMode:(*fs.FileMode)(nil), ChownDirs:(*idtools.IDPair)(nil), ChmodDirs:(*fs.FileMode)(nil), ChownFiles:(*idtools.IDPair)(nil), ChmodFiles:(*fs.FileMode)(nil), StripSetuidBit:false, StripSetgidBit:false, StripStickyBit:false, StripXattrs:false, IgnoreXattrErrors:false, IgnoreDevices:false, NoOverwriteDirNonDir:false, NoOverwriteNonDirDir:false, Rename:map[string]string(nil)}, MkdirOptions:copier.MkdirOptions{UIDMap:[]idtools.IDMap(nil), GIDMap:[]idtools.IDMap(nil), ChownNew:(*idtools.IDPair)(nil), ChmodNew:(*fs.FileMode)(nil)}, RemoveOptions:copier.RemoveOptions{All:false}}: copier: put: error setting ownership of \"/etc/mysql/conf.d\" to 1980042590:1980042590: lchown /etc/mysql/conf.d: invalid argument","message":"error during bulk transfer for copier.request{Request:\"PUT\", Root:\"/\", preservedRoot:\"/home/jvanmont/.local/share/containers/storage/overlay/297e95cb55db40d82aa6e025772f7e05a009d64f5563ac3421e34592209e8627/merged\", rootPrefix:\"/home/jvanmont/.local/share/containers/storage/overlay/297e95cb55db40d82aa6e025772f7e05a009d64f5563ac3421e34592209e8627/merged\", Directory:\"/\", preservedDirectory:\"/home/jvanmont/.local/share/containers/storage/overlay/297e95cb55db40d82aa6e025772f7e05a009d64f5563ac3421e34592209e8627/merged\", Globs:[]string{}, preservedGlobs:[]string{}, StatOptions:copier.StatOptions{CheckForArchives:false, Excludes:[]string(nil)}, GetOptions:copier.GetOptions{UIDMap:[]idtools.IDMap(nil), GIDMap:[]idtools.IDMap(nil), Excludes:[]string(nil), ExpandArchives:false, ChownDirs:(*idtools.IDPair)(nil), ChmodDirs:(*fs.FileMode)(nil), ChownFiles:(*idtools.IDPair)(nil), ChmodFiles:(*fs.FileMode)(nil), StripSetuidBit:false, StripSetgidBit:false, StripStickyBit:false, StripXattrs:false, KeepDirectoryNames:false, Rename:map[string]string(nil), NoDerefSymlinks:false, IgnoreUnreadable:false, NoCrossDevice:false}, PutOptions:copier.PutOptions{UIDMap:[]idtools.IDMap(nil), GIDMap:[]idtools.IDMap(nil), DefaultDirOwner:(*idtools.IDPair)(nil), DefaultDirMode:(*fs.FileMode)(nil), ChownDirs:(*idtools.IDPair)(nil), ChmodDirs:(*fs.FileMode)(nil), ChownFiles:(*idtools.IDPair)(nil), ChmodFiles:(*fs.FileMode)(nil), StripSetuidBit:false, StripSetgidBit:false, StripStickyBit:false, StripXattrs:false, IgnoreXattrErrors:false, IgnoreDevices:false, NoOverwriteDirNonDir:false, NoOverwriteNonDirDir:false, Rename:map[string]string(nil)}, MkdirOptions:copier.MkdirOptions{UIDMap:[]idtools.IDMap(nil), GIDMap:[]idtools.IDMap(nil), ChownNew:(*idtools.IDPair)(nil), ChmodNew:(*fs.FileMode)(nil)}, RemoveOptions:copier.RemoveOptions{All:false}}: copier: put: error setting ownership of \"/etc/mysql/conf.d\" to 1980042590:1980042590: lchown /etc/mysql/conf.d: invalid argument","response":500}
What I've tried
This is the most simplified version of my code that I've been able to get, which still produces the problem I described above.
@Test
public void testMySQL8() throws SQLException {
assumeFalse(SystemUtils.IS_OS_WINDOWS);
MySQLContainer container = new MySQLContainer<>("mysql:8.0.33")
.withCreateContainerCmdModifier(cmd -> cmd.withUser("0:0").withCmd("--user 0:0"))
/*.withCopyFileToContainer(MountableFile.forClasspathResource(
"db/testMySQL.cnf"), "/home")
* .withUsername("jvanmont")
.withInitScript("db/init_mysql.sql").withPrivilegedMode(true).withUsername("test")
.withCommand("mysqld --default-authentication-plugin=mysql_native_password")*/;
container.start();
try {
ResultSet resultSet = performQuery(container, "SELECT VERSION()");
resultSet.next();
String resultSetString = resultSet.getString(1);
System.out.println("mySQL version: " + resultSetString);
assertTrue("The database version can be set using a container rule parameter",
"8.0.33".equals(resultSetString));
} finally {
container.stop();
}
}
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.18.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.18.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<version>1.18.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
bash-4.4$ podman -v
podman version 4.2.0
Java 17
mvn -v 3.8.8
bash-4.4$ uname -a
Linux hbidev** 4.18.0-425.19.2.el8_7.x86_64 #1 SMP Tue Apr 4 22:38:11 UTC 2023
x86_64 x86_64 x86_64 GNU/Linux
My Research
I can run the code with sudo. I can run the container with podman run ...
No success: Podman is running rootless with host-user. Podman socket is owned by hos-user. I tried also with SELinux permissive mode.
What I tried from inside the testcontainer code -> I tried passing root user 0:0 when starting the container. I tried to start the container in privileged mode.
I turned on testcontainer DEBUG:
Cmd: org.testcontainers.shaded.com.github.dockerjava.core.command.CopyArchiveToContainerCmdImpl@62ce72ff[cp ,-a=false ,<null>, ,d430a1a20b47ebd457358549a57bb762ea59bf7a9831110390bc2a7dafcc3ad8,:,/]
Following is my podman id-mapping:
bash-4.4$ podman info | grep id
idlePercent: 98.81
hostname: hbidev**
idMappings:
gidmap:
- container_id: 0
host_id: 1980042590
- container_id: 1
host_id: 100000
uidmap:
- container_id: 0
host_id: 1980042590
- container_id: 1
host_id: 100000
- bridge
Question
Why testcontainer tries to chown the conf.d folder? Why are all folders inside the container owned by root/nobody?
How can start the container as root from a testcontainer so it doesn't have to chown the folders inside the container for my host-user.