caching custom maven container to avoid to apt update each time
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
index 0205f42..e388e55 100644
--- a/integration-test/pom.xml
+++ b/integration-test/pom.xml
@@ -30,6 +30,11 @@
   <artifactId>integration-test</artifactId>
   <name>Arthur :: Integration Tests</name>
 
+  <properties>
+    <!-- feel free to set it to true to avoid to "leak" a docker image, but it will slow down runs -->
+    <arthur.container.maven.deleteOnExit>false</arthur.container.maven.deleteOnExit>
+  </properties>
+
   <dependencies>
     <dependency>
       <groupId>org.testcontainers</groupId>
@@ -70,7 +75,11 @@
         <configuration>
           <systemPropertyVariables>
             <arthur.m2.repository>${settings.localRepository}</arthur.m2.repository>
+            <arthur.container.maven.deleteOnExit>${arthur.container.maven.deleteOnExit}</arthur.container.maven.deleteOnExit>
           </systemPropertyVariables>
+          <environmentVariables>
+            <TESTCONTAINERS_RYUK_DISABLED>true</TESTCONTAINERS_RYUK_DISABLED>
+          </environmentVariables>
         </configuration>
       </plugin>
     </plugins>
diff --git a/integration-test/src/test/java/org/apache/geronimo/arthur/integrationtests/container/MavenContainer.java b/integration-test/src/test/java/org/apache/geronimo/arthur/integrationtests/container/MavenContainer.java
index e43cbe4..04d54bb 100644
--- a/integration-test/src/test/java/org/apache/geronimo/arthur/integrationtests/container/MavenContainer.java
+++ b/integration-test/src/test/java/org/apache/geronimo/arthur/integrationtests/container/MavenContainer.java
@@ -16,18 +16,21 @@
  */
 package org.apache.geronimo.arthur.integrationtests.container;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
 import java.io.IOException;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
 
+import com.github.dockerjava.api.DockerClient;
+import org.testcontainers.DockerClientFactory;
 import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.images.builder.ImageFromDockerfile;
 
 import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
 public class MavenContainer extends GenericContainer<MavenContainer> {
     public MavenContainer() {
-        super(System.getProperty("arthur.container.maven.image", "maven:3.6.2-jdk-8-slim"));
+        super(findImage());
         setWorkingDirectory("/opt/geronimo/arthur/integration-test");
         setCommand("sleep", "infinity");
         withFileSystemBind(System.getProperty("arthur.m2.repository"), "/root/.m2/repository"); // cache
@@ -35,21 +38,40 @@
         setNetworkMode(System.getProperty("arthur.container.maven.network", "host"));
     }
 
-    @Override
-    public void start() {
-        super.start();
-        try {
-            log.info("Ensuring gcc is present");
+    private static String findImage() {
+        return Optional.of(System.getProperty("arthur.container.maven.image", "auto"))
+                .filter(it -> !"auto".equals(it))
+                .orElseGet(MavenContainer::getOrCreateAutoBaseImage);
+    }
 
-            final ExecResult update = execInContainer("apt", "update");
-            assertEquals(0, update.getExitCode(), () -> "Can't update apt: " + update.getStderr());
+    // we can run apt update && apt install -y gcc libc6-dev zlib1g-dev in start() but it is slow so we cache it through an image
+    // note: we don't clean the image to be able to reuse it and speed up integration-tests, use -Darthur.container.maven.deleteOnExit=true to auto clean it
+    private static String getOrCreateAutoBaseImage() {
+        final String fromImage = System.getProperty("arthur.container.maven.baseimage", "maven:3.6.2-jdk-8-slim");
+        // creating a tag from the source image to ensure we can have multiple test versions (maven/jdk matrix)
+        final String tag = fromImage.split(":")[1];
+        final String targetImage = "apache/geronimo/arthur/maven-test-base:" + tag;
 
-            final ExecResult gcc = execInContainer("apt", "install", "-y", "gcc", "libc6-dev", "zlib1g-dev");
-            assertEquals(0, gcc.getExitCode(), () -> "Can't install gcc: " + gcc.getStderr());
-        } catch (final IOException e) {
-            throw new IllegalStateException(e);
-        } catch (final InterruptedException e) {
+        try (final DockerClient client = DockerClientFactory.instance().client()) {
+            if (!client.listImagesCmd().withImageNameFilter(targetImage).exec().isEmpty()) {
+                log.info("Found '{}' image, reusing it", targetImage);
+                return targetImage;
+            }
+
+            log.info("Didn't find '{}', creating it from '{}'", targetImage, fromImage);
+            return new ImageFromDockerfile(
+                    targetImage, Boolean.getBoolean("arthur.container.maven.deleteOnExit"))
+                    .withDockerfileFromBuilder(builder -> builder.from(fromImage)
+                            .run("apt update && apt install -y gcc libc6-dev zlib1g-dev")
+                            .label("org.apache.geronimo.arthur.environment", "integration-tests")
+                            .label("org.apache.geronimo.arthur.baseImage", fromImage)
+                            .label("org.apache.geronimo.arthur.tag", tag))
+                    .get();
+        } catch (final InterruptedException ie) {
             Thread.currentThread().interrupt();
+            throw new IllegalStateException(ie);
+        } catch (final IOException | ExecutionException e) {
+            throw new IllegalStateException(e);
         }
     }
 }