Java Code Examples for org.testcontainers.images.builder.ImageFromDockerfile

The following examples show how to use org.testcontainers.images.builder.ImageFromDockerfile. These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source Project: camel-kafka-connector   Source File: HadoopBaseContainer.java    License: Apache License 2.0 6 votes vote down vote up
public HadoopBaseContainer(Network network, String name) {
    super(new ImageFromDockerfile("hadoop-2x:ckc", false)
            .withFileFromClasspath(".",
                    "org/apache/camel/kafkaconnector/hdfs/services/"));

    withNetwork(network);

    withCreateContainerCmdModifier(
            new Consumer<CreateContainerCmd>() {
                @Override
                public void accept(CreateContainerCmd createContainerCmd) {
                    createContainerCmd.withHostName(name);
                    createContainerCmd.withName(name);
                }
            }
    );
}
 
Example 2
Source Project: microshed-testing   Source File: PayaraMicroAdapter.java    License: Apache License 2.0 6 votes vote down vote up
@Override
public ImageFromDockerfile getDefaultImage(File appFile) {
    String appName = appFile.getName();
    // Compose a docker image equivalent to doing:
    // FROM payara/micro:5.193
    // CMD ["--deploymentDir", "/opt/payara/deployments", "--noCluster"]
    // ADD target/myservice.war /opt/payara/deployments
    ImageFromDockerfile image = new ImageFromDockerfile()
            .withDockerfileFromBuilder(builder -> builder.from("payara/micro:5.193")
                    .cmd("--deploymentDir", "/opt/payara/deployments", "--noCluster")
                    .add(appName, "/opt/payara/deployments")
                    .build())
            .withFileFromFile(appName, appFile);
    return image;

}
 
Example 3
private static GenericContainer<?> masterContainer(
    ImageFromDockerfile appImage,
    Network network,
    List<GenericContainer<?>> dependents,
    int numWorkers,
    @Nullable Logger masterLogger) {
  final GenericContainer<?> master =
      new GenericContainer(appImage)
          .withNetwork(network)
          .withNetworkAliases(MASTER_HOST)
          .withEnv("ROLE", "master")
          .withEnv("MASTER_HOST", MASTER_HOST)
          .withCommand("-p " + numWorkers)
          .withExposedPorts(8081);

  for (GenericContainer<?> dependent : dependents) {
    master.dependsOn(dependent);
  }

  if (masterLogger != null) {
    master.withLogConsumer(new Slf4jLogConsumer(masterLogger, true));
  }

  return master;
}
 
Example 4
Source Project: syndesis   Source File: SyndesisS2iAssemblyContainer.java    License: Apache License 2.0 6 votes vote down vote up
public SyndesisS2iAssemblyContainer(String integrationName, Path projectDir, String imageTag) {
    super(new ImageFromDockerfile(integrationName + "-s2i", true)
        .withFileFromPath(SRC_DIR, projectDir)
        .withDockerfileFromBuilder(builder -> builder.from(String.format("syndesis/syndesis-s2i:%s", imageTag))
            .withStatement(new MultiArgsStatement("ADD", SRC_DIR, SRC_DIR))
            .user("0")
            .run("chown", "-R", "1000", SRC_DIR)
            .user("1000")
            .cmd(S2I_ASSEMBLE_SCRIPT)
            .build()));

    final WaitStrategy onLogDone = new LogMessageWaitStrategy()
        .withRegEx(".*\\.\\.\\. done.*\\s")
        .withStartupTimeout(SyndesisTestEnvironment.getContainerStartupTimeout());

    setWaitStrategy(onLogDone);
}
 
Example 5
Source Project: java-dcp-client   Source File: AgentContainer.java    License: Apache License 2.0 6 votes vote down vote up
private static Future<String> createImage(File appFile) throws FileNotFoundException {
  if (!appFile.exists()) {
    throw new FileNotFoundException(appFile.getAbsolutePath());
  }

  final List<String> command = new ArrayList<>(Arrays.asList("java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"));
  if (debuggerPresent()) {
    // The integration tests are running in debug mode, so launch the agent in debug mode too.
    command.add(1, "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=" + CONTAINER_DEBUG_PORT);
  }
  final String[] entryPoint = command.toArray(new String[0]);

  return new ImageFromDockerfile("dcp-test-agent", true)
      .withDockerfileFromBuilder(dockerfileBuilder -> dockerfileBuilder
          .from("openjdk:8-jdk-alpine")
          .volume("/tmp")
          .add("/app.jar", "app.jar")
          .entryPoint(entryPoint))
      .withFileFromFile("/app.jar", appFile);
}
 
Example 6
Source Project: testcontainers-java   Source File: DockerfileTest.java    License: MIT License 6 votes vote down vote up
@Test
public void customizableImage() {
    ImageFromDockerfile image = new ImageFromDockerfile() {
        @Override
        protected void configure(BuildImageCmd buildImageCmd) {
            super.configure(buildImageCmd);

            List<String> dockerfile = Arrays.asList(
                    "FROM alpine:3.2",
                    "RUN echo 'hello from Docker build process'",
                    "CMD yes"
            );
            withFileFromString("Dockerfile", String.join("\n", dockerfile));

            buildImageCmd.withNoCache(true);
        }
    };

    verifyImage(image);
}
 
Example 7
Source Project: testcontainers-java   Source File: DockerfileTest.java    License: MIT License 6 votes vote down vote up
@Test
public void dockerfileBuilderWorks() {
    ImageFromDockerfile image = new ImageFromDockerfile()
            .withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt")
            .withFileFromString("folder/someFile.txt", "hello")
            .withDockerfileFromBuilder(builder -> builder
                    .from("alpine:3.2")
                    .workDir("/app")
                    .add("test.txt", "test file.txt")
                    .run("ls", "-la", "/app/test file.txt")
                    .copy("folder/someFile.txt", "/someFile.txt")
                    .expose(80, 8080)
                    .cmd("while true; do cat /someFile.txt | nc -l -p 80; done")
            );

    verifyImage(image);
}
 
Example 8
Source Project: testcontainers-java   Source File: DirectoryTarResourceTest.java    License: MIT License 6 votes vote down vote up
@Test
public void simpleRecursiveFileTest() {
    // 'src' is expected to be the project base directory, so all source code/resources should be copied in
    File directory = new File("src");

    GenericContainer container = new GenericContainer(
            new ImageFromDockerfile()
                    .withDockerfileFromBuilder(builder ->
                            builder.from("alpine:3.3")
                                    .copy("/tmp/foo", "/foo")
                                    .cmd("cat /foo/test/resources/test-recursive-file.txt")
                                    .build()
                    ).withFileFromFile("/tmp/foo", directory))
            .withStartupCheckStrategy(new OneShotStartupCheckStrategy());

    container.start();

    final String results = container.getLogs();

    assertTrue("The container has a file that was copied in via a recursive copy", results.contains("Used for DirectoryTarResourceTest"));
}
 
Example 9
Source Project: testcontainers-java   Source File: DirectoryTarResourceTest.java    License: MIT License 6 votes vote down vote up
@Test
public void simpleRecursiveFileWithPermissionTest() {
    GenericContainer container = new GenericContainer(
            new ImageFromDockerfile()
                    .withDockerfileFromBuilder(builder ->
                            builder.from("alpine:3.3")
                                    .copy("/tmp/foo", "/foo")
                                    .cmd("ls", "-al", "/")
                                    .build()
                    ).withFileFromFile("/tmp/foo", new File("/mappable-resource/test-resource.txt"),
                    0754))
            .withStartupCheckStrategy(new OneShotStartupCheckStrategy());

    container.start();
    String listing = container.getLogs();

    assertThat("Listing shows that file is copied with mode requested.",
            Arrays.asList(listing.split("\\n")),
            exactlyNItems(1, allOf(containsString("-rwxr-xr--"), containsString("foo"))));
}
 
Example 10
Source Project: testcontainers-java   Source File: DirectoryTarResourceTest.java    License: MIT License 6 votes vote down vote up
@Test
public void simpleRecursiveClasspathResourceTest() {
    // This test combines the copying of classpath resources from JAR files with the recursive TAR approach, to allow JARed classpath resources to be copied in to an image

    GenericContainer container = new GenericContainer(
            new ImageFromDockerfile()
                    .withDockerfileFromBuilder(builder ->
                            builder.from("alpine:3.3")
                                    .copy("/tmp/foo", "/foo")
                                    .cmd("ls -lRt /foo")
                                    .build()
                    ).withFileFromClasspath("/tmp/foo", "/recursive/dir"))          // here we use /org/junit as a directory that really should exist on the classpath
            .withStartupCheckStrategy(new OneShotStartupCheckStrategy());

    container.start();

    final String results = container.getLogs();

    // ExternalResource.class is known to exist in a subdirectory of /org/junit so should be successfully copied in
    assertTrue("The container has a file that was copied in via a recursive copy from a JAR resource", results.contains("content.txt"));
}
 
Example 11
Source Project: testcontainers-java   Source File: AuthenticatedImagePullTest.java    License: MIT License 6 votes vote down vote up
@Test
public void testThatAuthLocatorIsUsedForDockerfileBuild() throws IOException {
    // Prepare a simple temporary Dockerfile which requires our custom private image
    Path tempFile = getLocalTempFile(".Dockerfile");
    String dockerFileContent = "FROM " + testImageNameWithTag;
    Files.write(tempFile, dockerFileContent.getBytes());

    // Start a container built from a derived image, which will require an authenticated pull
    try (final GenericContainer<?> container = new GenericContainer<>(
        new ImageFromDockerfile()
            .withDockerfile(tempFile)
    )
        .withCommand("/bin/sh", "-c", "sleep 10")) {
        container.start();

        assertTrue("container started following an authenticated pull", container.isRunning());
    }
}
 
Example 12
Source Project: james-project   Source File: DockerCassandra.java    License: Apache License 2.0 6 votes vote down vote up
public DockerCassandra(String imageName, AdditionalDockerFileStep additionalSteps) {
    client = DockerClientFactory.instance().client();
    boolean doNotDeleteImageAfterUsage = false;
    cassandraContainer = new GenericContainer<>(
        new ImageFromDockerfile(imageName,doNotDeleteImageAfterUsage)
            .withDockerfileFromBuilder(builder ->
                additionalSteps.applyStep(builder
                    .from("cassandra:3.11.3")
                    .env("ENV CASSANDRA_CONFIG", "/etc/cassandra")
                    .run("echo \"-Xms" + CASSANDRA_MEMORY + "M\" >> " + JVM_OPTIONS)
                    .run("echo \"-Xmx" + CASSANDRA_MEMORY + "M\" >> " + JVM_OPTIONS)
                    .run("sed", "-i", "s/auto_snapshot: true/auto_snapshot: false/g", "/etc/cassandra/cassandra.yaml")
                    .run("echo 'authenticator: PasswordAuthenticator' >> /etc/cassandra/cassandra.yaml")
                    .run("echo 'authorizer: org.apache.cassandra.auth.CassandraAuthorizer' >> /etc/cassandra/cassandra.yaml"))
                    .build()))
        .withTmpFs(ImmutableMap.of("/var/lib/cassandra", "rw,noexec,nosuid,size=200m"))
        .withExposedPorts(CASSANDRA_PORT)
        .withLogConsumer(DockerCassandra::displayDockerLog);
    cassandraContainer
        .waitingFor(new CassandraWaitStrategy(cassandraContainer));
}
 
Example 13
Source Project: james-project   Source File: DockerElasticSearch.java    License: Apache License 2.0 6 votes vote down vote up
WithAuth(String imageName) {
    this.network = Network.newNetwork();
    this.elasticSearch = new DockerElasticSearch.NoAuth(
        DockerElasticSearch.NoAuth
            .defaultContainer(imageName)
            .withLogConsumer(frame -> LOGGER.debug("[ElasticSearch] " + frame.getUtf8String()))
            .withNetwork(network)
            .withNetworkAliases("elasticsearch"));

    this.nginx = new DockerContainer(
            new GenericContainer<>(
                new ImageFromDockerfile()
                .withFileFromClasspath("conf/nginx-conf/", "auth-es/nginx-conf/")
                .withFileFromClasspath("conf/default.crt", "auth-es/default.crt")
                .withFileFromClasspath("conf/default.key", "auth-es/default.key")
                .withFileFromClasspath("Dockerfile", "auth-es/NginxDockerfile")))
        .withExposedPorts(ES_HTTP_PORT)
        .withLogConsumer(frame -> LOGGER.debug("[NGINX] " + frame.getUtf8String()))
        .withNetwork(network);
}
 
Example 14
Source Project: james-project   Source File: Linshare.java    License: Apache License 2.0 6 votes vote down vote up
@SuppressWarnings("resource")
private GenericContainer<?> createDockerBackend() {
    return new GenericContainer<>(
        new ImageFromDockerfile()
            .withFileFromClasspath("conf/log4j.properties", "backend/conf/log4j.properties")
            .withFileFromClasspath("conf/catalina.properties", "backend/conf/catalina.properties")
            .withFileFromClasspath("conf/id_rsa", "backend/conf/id_rsa.pri")
            .withFileFromClasspath("conf/id_rsa.pub", "backend/conf/id_rsa.pub")
            .withFileFromClasspath("Dockerfile", "backend/Dockerfile"))
        .withLogConsumer(frame -> LOGGER.debug("<linshare-backend> " + frame.getUtf8String()))
        .withNetworkAliases("backend")
        .withEnv("SMTP_HOST", "linshare_smtp")
        .withEnv("SMTP_PORT", "25")
        .withEnv("POSTGRES_HOST", "linshare_database")
        .withEnv("POSTGRES_PORT", "5432")
        .withEnv("POSTGRES_USER", "linshare")
        .withEnv("POSTGRES_PASSWORD", "linshare")
        .withEnv("MONGODB_HOST", "linshare_mongodb")
        .withEnv("MONGODB_PORT", "27017")
        .withEnv("THUMBNAIL_ENABLE", "false")
        .withExposedPorts(LINSHARE_BACKEND_PORT)
        .waitingFor(Wait.forLogMessage(WAIT_FOR_BACKEND_INIT_LOG, 1)
            .withStartupTimeout(Duration.ofMinutes(10)))
        .withNetwork(network);
}
 
Example 15
public QpidDispatchRouterContainer() {
    super(new ImageFromDockerfile("qpid-dispatch:ckc", false)
            .withFileFromClasspath("Dockerfile",
                    "org/apache/camel/kafkaconnector/sjms2/services/qpid-dispatch-router/Dockerfile"));

    withExposedPorts(DEFAULT_AMQP_PORT);

    waitingFor(Wait.forListeningPort());
}
 
Example 16
Source Project: camel-kafka-connector   Source File: ArtemisContainer.java    License: Apache License 2.0 5 votes vote down vote up
public ArtemisContainer() {
    super(new ImageFromDockerfile("apache-artemis:ckc", false)
            .withFileFromClasspath("Dockerfile",
                    "org/apache/camel/kafkaconnector/sjms2/services/artemis/Dockerfile"));

    withExposedPorts(DEFAULT_MQTT_PORT, DEFAULT_AMQP_PORT,
            DEFAULT_ADMIN_PORT, DEFAULT_ACCEPTOR_PORT);

    waitingFor(Wait.forListeningPort());
}
 
Example 17
Source Project: microshed-testing   Source File: LibertyAdapter.java    License: Apache License 2.0 5 votes vote down vote up
@Override
    public ImageFromDockerfile getDefaultImage(File appFile) {
        final String appName = appFile.getName();
        final File configDir = new File("src/main/liberty/config");
        final boolean configDirExists = configDir.exists() && configDir.canRead();
        // Compose a docker image equivalent to doing:
        // FROM openliberty/open-liberty:full-java8-openj9-ubi
        // COPY src/main/liberty/config /config/
        // RUN configure.sh
        // ADD build/libs/<appFile> /config/dropins
        ImageFromDockerfile image = new ImageFromDockerfile()
                        .withDockerfileFromBuilder(builder -> {
                            builder.from(getBaseDockerImage());
                            if (configDirExists) {
                                builder.copy("/config", "/config");
                            }
//                            // Best practice is to run configure.sh after the app is added, but we will
//                            // run it before adding the app because due to how often the app changes while
//                            // running tests this will yeild the most overall time saved
                            // TODO: Cache does not work correctly when running the previous docker line
                            // which causes configure.sh to be run every time. See https://github.com/MicroShed/microshed-testing/issues/122
//                            builder.run("configure.sh");
                            builder.add("/config/dropins/" + appName, "/config/dropins/" + appName);
                            builder.build();
                        })
                        .withFileFromFile("/config/dropins/" + appName, appFile);
        if (configDirExists)
            image.withFileFromFile("/config", configDir);
        return image;
    }
 
Example 18
Source Project: microshed-testing   Source File: WildFlyAdapter.java    License: Apache License 2.0 5 votes vote down vote up
@Override
public ImageFromDockerfile getDefaultImage(File appFile) {
    String appName = appFile.getName();
    // Compose a docker image equivalent to doing:
    // FROM jboss/wildfly:18.0.1.Final
    // ADD target/myservice.war /opt/jboss/wildfly/standalone/deployments
    ImageFromDockerfile image = new ImageFromDockerfile()
            .withDockerfileFromBuilder(builder -> builder.from("jboss/wildfly:18.0.1.Final")
                    .add(appName, "/opt/jboss/wildfly/standalone/deployments")
                    .build())
            .withFileFromFile(appName, appFile);
    return image;

}
 
Example 19
Source Project: microshed-testing   Source File: PayaraServerAdapter.java    License: Apache License 2.0 5 votes vote down vote up
@Override
public ImageFromDockerfile getDefaultImage(File appFile) {
    String appName = appFile.getName();
    // Compose a docker image equivalent to doing:
    // FROM payara/server-full:5.193
    // ADD target/myservice.war /opt/payara/deployments
    ImageFromDockerfile image = new ImageFromDockerfile()
            .withDockerfileFromBuilder(builder -> builder.from("payara/server-full:5.193")
                    .add(appName, "/opt/payara/deployments")
                    .build())
            .withFileFromFile(appName, appFile);
    return image;

}
 
Example 20
public StatefulFunctionsAppContainers build() {
  final ImageFromDockerfile appImage =
      appImage(appName, dynamicProperties, classpathBuildContextFiles);

  return new StatefulFunctionsAppContainers(
      masterContainer(appImage, network, dependentContainers, numWorkers, masterLogger),
      workerContainers(appImage, numWorkers, network));
}
 
Example 21
private static List<GenericContainer<?>> workerContainers(
    ImageFromDockerfile appImage, int numWorkers, Network network) {
  final List<GenericContainer<?>> workers = new ArrayList<>(numWorkers);

  for (int i = 0; i < numWorkers; i++) {
    workers.add(
        new GenericContainer(appImage)
            .withNetwork(network)
            .withNetworkAliases(workerHostOf(i))
            .withEnv("ROLE", "worker")
            .withEnv("MASTER_HOST", MASTER_HOST));
  }

  return workers;
}
 
Example 22
Source Project: flink-statefun   Source File: RemoteModuleE2E.java    License: Apache License 2.0 5 votes vote down vote up
private static ImageFromDockerfile remoteFunctionImage() {
  final Path pythonSourcePath = remoteFunctionPythonSourcePath();
  LOG.info("Building remote function image with Python source at: {}", pythonSourcePath);

  final Path pythonSdkPath = pythonSdkPath();
  LOG.info("Located built Python SDK at: {}", pythonSdkPath);

  return new ImageFromDockerfile("remote-function")
      .withFileFromClasspath("Dockerfile", "Dockerfile.remote-function")
      .withFileFromPath("source/", pythonSourcePath)
      .withFileFromClasspath("requirements.txt", "requirements.txt")
      .withFileFromPath("python-sdk/", pythonSdkPath);
}
 
Example 23
Source Project: apm-agent-java   Source File: WebSphereIT.java    License: Apache License 2.0 5 votes vote down vote up
public WebSphereIT(final String version) {
    super((ENABLE_DEBUGGING
            ? new GenericContainer<>(new ImageFromDockerfile()
            .withDockerfileFromBuilder(builder -> builder
                .from("websphere-liberty:" + version).cmd("/opt/ibm/wlp/bin/server", "debug", "defaultServer")))
            : new GenericContainer<>("websphere-liberty:" + version)
        )
            .withEnv("JVM_ARGS", "-javaagent:/elastic-apm-agent.jar"),
        9080,
        7777,
        "websphere-application",
        "/config/dropins",
        "websphere");
}
 
Example 24
Source Project: apm-agent-java   Source File: PayaraIT.java    License: Apache License 2.0 5 votes vote down vote up
public PayaraIT(final String serverVersion, final String deploymentsFolder) {
    super(new GenericContainer<>(
            new ImageFromDockerfile()
                .withDockerfileFromBuilder(builder -> {
                        builder
                            .from("payara/server-web:" + serverVersion)
                            .run("sed", "-i", "s#" +
                                    "</java-config>#" +
                                    "<jvm-options>-javaagent:/elastic-apm-agent.jar</jvm-options></java-config>#",
                                "glassfish/domains/domain1/config/domain.xml")
                            .run("sed", "-i", "s#" +
                                    "</java-config>#" +
                                    "<jvm-options>-Xdebug</jvm-options></java-config>#",
                                "glassfish/domains/domain1/config/domain.xml");
                        if (ENABLE_DEBUGGING) {
                            builder.run("sed", "-i", "s#" +
                                    "</java-config>#" +
                                    "<jvm-options>-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005</jvm-options></java-config>#",
                                "glassfish/domains/domain1/config/domain.xml");
                        }
                    }
                )
        ),
        "glassfish-application",
        deploymentsFolder,
        "payara");
}
 
Example 25
Source Project: syndesis   Source File: SyndesisServerContainer.java    License: Apache License 2.0 5 votes vote down vote up
protected SyndesisServerContainer(String serverJarPath, String javaOptions, boolean deleteOnExit) {
    super(new ImageFromDockerfile("syndesis-server", deleteOnExit)
            .withDockerfileFromBuilder(builder -> builder.from("fabric8/s2i-java:3.0-java8")
                         .env("JAVA_OPTIONS", javaOptions)
                         .expose(SERVER_PORT, JOLOKIA_PORT, SyndesisTestEnvironment.getDebugPort())
                         .build()));

    withClasspathResourceMapping(serverJarPath,"/deployments/server.jar", BindMode.READ_ONLY);
}
 
Example 26
private ImageFromDockerfile prepareImage(String imageName) {
    String pluginContainerPath = plugin == null ? null : ("/tmp/plugins/" + plugin.getName());
    ImageFromDockerfile image = new ImageFromDockerfile()
            .withDockerfileFromBuilder(builder -> {
                builder.from(imageName);
                if (pluginContainerPath != null) {
                    builder.copy(pluginContainerPath, pluginContainerPath);
                    builder.run("bin/elasticsearch-plugin", "install", "file://" + pluginContainerPath);
                }
            });
    if (pluginContainerPath != null) {
        image.withFileFromFile(pluginContainerPath, plugin);
    }
    return image;
}
 
Example 27
Source Project: testcontainers-java   Source File: DockerfileTest.java    License: MIT License 5 votes vote down vote up
@Test
public void simpleDockerfileWorks() {
    ImageFromDockerfile image = new ImageFromDockerfile()
            .withFileFromString("folder/someFile.txt", "hello")
            .withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt")
            .withFileFromClasspath("Dockerfile", "mappable-dockerfile/Dockerfile");

    verifyImage(image);
}
 
Example 28
Source Project: testcontainers-java   Source File: DockerfileTest.java    License: MIT License 5 votes vote down vote up
protected void verifyImage(ImageFromDockerfile image) {
    GenericContainer container = new GenericContainer(image);

    try {
        container.start();

        pass("Should start from Dockerfile");
    } finally {
        container.stop();
    }
}
 
Example 29
public ParameterizedDockerfileContainerTest(String baseImage, String expectedVersion) {
    container = new GenericContainer(new ImageFromDockerfile().withDockerfileFromBuilder(builder -> {
            builder
                    .from(baseImage)
                    // Could potentially customise the image here, e.g. adding files, running
                    //  commands, etc.
                    .build();
        })).withCommand("top");
    this.expectedVersion = expectedVersion;
}
 
Example 30
@Before
public void setUp() {
    // Using a Dockerfile here, since Dockerfile builder DSL doesn't support HEALTHCHECK
    container = new GenericContainer(new ImageFromDockerfile()
        .withFileFromClasspath("write_file_and_loop.sh", "health-wait-strategy-dockerfile/write_file_and_loop.sh")
        .withFileFromClasspath("Dockerfile", "health-wait-strategy-dockerfile/Dockerfile"))
        .waitingFor(Wait.forHealthcheck().withStartupTimeout(Duration.ofSeconds(3)));
}