I'm very interested in using testcontainers in my project.
However, I'm having a hard time setting it up to work with Informix.
Note that I can start an informix container using Docker-for-Mac and it will build and start.
Not sure it can work with testcontainers though. I wish it would.
Here's what I have so far
Test class
package com.example.demo;
import com.github.dockerjava.api.command.CreateContainerCmd;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import org.testcontainers.containers.wait.strategy.WaitAllStrategy;
import java.time.Duration;
import static org.junit.Assert.assertEquals;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
private static GenericContainer informix;
@BeforeClass
public static void init() {
informix = new GenericContainer("ibmcom/informix-innovator-c")
.withExposedPorts(9088)
.withEnv("LICENSE", "accept")
.withPrivilegedMode(true)
.withCreateContainerCmdModifier(command -> ((CreateContainerCmd)command).withTty(Boolean.TRUE))
.waitingFor(new WaitAllStrategy().withStrategy(new LogMessageWaitStrategy().withRegEx(".*listener on port.*\n"))
.withStrategy(new HostPortWaitStrategy())
.withStartupTimeout(Duration.ofMinutes(2)));
informix.start();
}
@AfterClass
public static void destroy(){
informix.close();
}
@Test
public void testDemo() {
int foo = 1;
assertEquals(foo, 1);
}
}
The container starts up and then hangs forever, and test is never entered
Here's the output:
...
00:32:27 Updating Low Memory Manager to version 11
00:32:27 Installing patch to Low Memory Manager code. version(11.01)
00:32:27 Installing patch to upgrade ph_task code. version(13.08)
00:32:27 SCHAPI: Started 2 dbWorker threads.
00:32:27 Checkpoint Completed: duration was 0 seconds.
00:32:27 Sat Jul 6 - loguniq 3, logpos 0xa2e080, timestamp: 0x32abd Interval: 6
00:32:27 Maximum server connections 1
00:32:27 Checkpoint Statistics - Avg. Txn Block Time 0.000, # Txns blocked 1, Plog used 178, Llog used 4831
starting mongo listener on port 27017
starting rest listener on port 27018
starting mqtt listener on port 27883
17:34:05.472 [main] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536,false,com.github.dockerjava.core.exec.InspectContainerCmdExec@3fabf088
17:34:05.472 [main] DEBUG com.github.dockerjava.core.exec.InspectContainerCmdExec - GET: OkHttpWebTarget(okHttpClient=org.testcontainers.shaded.okhttp3.OkHttpClient@70925b45, baseUrl=http://docker.socket/, path=[/containers/b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536/json], queryParams={})
17:34:05.482 [main] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536,<null>,com.github.dockerjava.core.exec.KillContainerCmdExec@5cbf9e9f
17:34:06.186 [main] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536,false,com.github.dockerjava.core.exec.InspectContainerCmdExec@18e8473e
17:34:06.187 [main] DEBUG com.github.dockerjava.core.exec.InspectContainerCmdExec - GET: OkHttpWebTarget(okHttpClient=org.testcontainers.shaded.okhttp3.OkHttpClient@70925b45, baseUrl=http://docker.socket/, path=[/containers/b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536/json], queryParams={})
17:34:06.194 [main] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536,true,true,com.github.dockerjava.core.exec.RemoveContainerCmdExec@6f6a7463
17:34:06.297 [main] DEBUG org.testcontainers.utility.ResourceReaper - Removed container and associated volume(s): ibmcom/informix-innovator-c:latest
17:34:06.298 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - After test class: context [DefaultTestContext@624ea235 testClass = DemoApplicationTests, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@3932c79a testClass = DemoApplicationTests, locations = '{}', classes = '{class com.example.demo.DemoApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@3e2e18f2, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@703580bf, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@5c30a9b0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@3c407114], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]], class annotated with @DirtiesContext [false] with mode [null].
org.testcontainers.containers.ContainerLaunchException: Container startup failed
at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:217)
at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:199)
at com.example.demo.DemoApplicationTests.init(DemoApplicationTests.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:83)
at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:210)
... 20 more
Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:277)
at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:212)
at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:76)
... 21 more
Caused by: org.rnorth.ducttape.TimeoutException: java.util.concurrent.TimeoutException
at org.rnorth.ducttape.timeouts.Timeouts.callFuture(Timeouts.java:70)
at org.rnorth.ducttape.timeouts.Timeouts.doWithTimeout(Timeouts.java:60)
at org.testcontainers.containers.wait.strategy.WaitAllStrategy.waitUntilReady(WaitAllStrategy.java:53)
at org.testcontainers.containers.GenericContainer.waitUntilContainerStarted(GenericContainer.java:582)
at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:259)
... 23 more
Caused by: java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:205)
at org.rnorth.ducttape.timeouts.Timeouts.callFuture(Timeouts.java:65)
... 27 more
Disconnected from the target VM, address: '127.0.0.1:51062', transport: 'socket'
Test ignored.
Process finished with exit code 255
If I comment out this line
// .withCreateContainerCmdModifier(command -> ((CreateContainerCmd)command).withTty(Boolean.TRUE))
Then it starts, but then gets stuck in a loop endlessly with these messages then ultimately timesout the same way
6:09:07.489 [ducttape-1] DEBUG com.github.dockerjava.core.exec.InspectExecCmdExec - GET: OkHttpWebTarget(okHttpClient=org.testcontainers.shaded.okhttp3.OkHttpClient@1a2e2935, baseUrl=http://docker.socket/, path=[/exec/ab3ed2f2d3fa129b21c787a7bcce603a267fea48268ab7c861657005919ee546/json], queryParams={})
16:09:08.494 [ducttape-1] DEBUG org.testcontainers.containers.ExecInContainerPattern - /elastic_raman: Running "exec" command: /bin/sh -c cat /proc/net/tcp{,6} | awk '{print $2}' | grep -i :2380
16:09:08.495 [ducttape-1] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: 3a30ec6ec83dff4b2f330b9c9d71b907dbfd7596a0bd9cc54d1b4f7eb2164f3e,<null>,true,true,<null>,<null>,<null>,{/bin/sh,-c,cat /proc/net/tcp{,6} | awk '{print $2}' | grep -i :2380},com.github.dockerjava.core.exec.ExecCreateCmdExec@74c5bfba
16:09:08.582 [ducttape-1] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b82e102d716c5530e5aa8c9699f8f5a5e0d6aa6cc4aa69c44b8553f79de4101f,com.github.dockerjava.core.exec.InspectExecCmdExec@90283ab
16:09:08.582 [ducttape-1] DEBUG com.github.dockerjava.core.exec.InspectExecCmdExec - GET: OkHttpWebTarget(okHttpClient=org.testcontainers.shaded.okhttp3.OkHttpClient@1a2e2935, baseUrl=http://docker.socket/, path=[/exec/b82e102d716c5530e5aa8c9699f8f5a5e0d6aa6cc4aa69c44b8553f79de4101f/json], queryParams={})
There was a mis-configuration in the docker image for Informix. The servers that start in the docker containers only would listen on the hostname, and not localhost. Testcontainers uses 'localhost' as the network interface to connect to your containers. So when you used .withExposedPorts(9088)
the port was not actually exposed on a network interface TestContainers could connect to.
This is why you still had trouble most likely even if you waited for the log message you also waited on the port and it would never be available.
The good news is that this is now fixed and available by pulling down the latest Informix docker images
ibmcom/informix-developer-database:latest
for the latest 14.10 docker image
Below is the code I ran to validate the new images are working better with TestContainers.
public class DockerTest {
GenericContainer<?>container = new GenericContainer<>("ibmcom/informix-developer-database:latest")
.withExposedPorts(9088, 9089, 27017, 27018, 27883).withEnv("LICENSE", "accept");
@Test
public void testIfxContainer() throws Exception {
container.start();
System.out.println("Informix started");
//test the connection
try(Connection c = DriverManager.getConnection("jdbc:informix-sqli:localhost:" + container.getFirstMappedPort() + "/sysmaster:user=informix;password=your-password")) {
try(Statement s = c.createStatement(); ResultSet rs = s.executeQuery("SELECT FIRST 10 tabname from systables");) {
while(rs.next()) {
System.out.println(r.getString(1));
}
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With