Goal
I want to use customized PostgreSQL image with locale support with test containers.
On postgres side
I prepared Dockerfile
as described in postgres image documentation:
You can extend the Debian-based images with a simple Dockerfile to set a different locale. The following example will set the default locale to de_DE.utf8:
FROM postgres:14.3
RUN localedef -i de_DE -c -f UTF-8 -A /usr/share/locale/locale.alias de_DE.UTF-8
ENV LANG de_DE.utf8
So essentially nothing changes in the way this image works, but has some more capabilities in terms of locale support.
On testcontainers side
I wanted to use it as described in testcontainers documentation:
Simply pass a configured instance of ImageFromDockerfile as a constructor parameter to GenericContainer. Testcontainers will docker build a temporary container image, and will use it when creating the container.
public GenericContainer dslContainer = new GenericContainer(
new ImageFromDockerfile()
.withFileFromString("folder/someFile.txt", "hello")
.withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt")
.withFileFromClasspath("Dockerfile", "mappable-dockerfile/Dockerfile"))
Problem
In examples above testcontainers uses GenericContainer
. GenericContainer
exposes constructor public GenericContainer(final Future<String> image)
, what allows it to be used with ImageFromDockerfile
. Sadly PostgreSQLContainer
does not provide such constructor but I still want to use this class because it has several internal setups to support postgres well. There are two constructors in PostgreSQLContainer
but they only accept image name.
Only solution I could think of was to essentially make a local copy of original PostgreSQLContainer
and add missing constructor. That seems to work fine but it is a dirty hack for obvious reasons.
Question
My question is: am I missing some other way to accomplish the task with tools testcontainers provide? Or is it an area of improvement to add such public constructor in testcontainers?
CodePudding user response:
I believe the solution would be:
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.utility.DockerImageName;
import java.net.URI;
import java.nio.file.Paths;
import java.time.Duration;
import static java.time.temporal.ChronoUnit.SECONDS;
public class Demo {
public static void main(String[] args) throws Exception {
// the most buggy part - need to investigate
// how to work properly with ImageFromDockerfile
URI path = Demo.class.getResource("/PostgreSQLde").toURI();
ImageFromDockerfile image = new ImageFromDockerfile()
.withDockerfile(Paths.get(path));
DockerImageName imageName = DockerImageName.parse(image.get())
.asCompatibleSubstituteFor(PostgreSQLContainer.IMAGE);
new PostgreSQLContainer<>(imageName)
.waitingFor(new LogMessageWaitStrategy()
// oops
.withRegEx(".*Datenbanksystem ist bereit, um Verbindungen anzunehmen.*\\s")
.withTimes(2)
.withStartupTimeout(Duration.of(60, SECONDS)))
.start();
}
}