0

I'm starting postgres container with maven docker plugin and then use the DB to generate some artefacts in later steps.

<plugin>
   …
    <artifactId>docker-maven-plugin</artifactId>
    …
    <configuration>
        <images>
            <image>
                ...
                <name>postgres:11</name>
                ...
            </image>
        </images>
    </configuration>

    <executions>
        <execution>
            <id>start-postgres-container</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
        <execution>
            <id>stop-postgres-container</id>
            <phase>process-sources</phase>
            <goals>
                <goal>stop</goal>
            </goals>
        </execution>
    </executions>

 </plugin>

The issue I have is that when there is some error with any operations between start and stop above, then maven leaves the running container and consecutive build attempts will fail so one has to put down the leftover container manually first.

Is there a way/plugin in maven to specify some finally action/phase? So that in case of failure in build scripts one would still be able to release some resources which might've been already reserved?

alwi
  • 431
  • 6
  • 21
  • If you need to start a docker container with a database this sounds more like an integration tests ... This should be done via pre-integration-test,integration-test and post-integration-test ... the other option would be to check [testcontainers](https://www.testcontainers.org/) which sound more appropriate for this kind of problem apart from that I don't understand to use database and create code somehow here?... – khmarbaise Nov 12 '20 at 14:44
  • Not necessarily. This is in fact code generation in reality, e.g. Jooq classes based on schema with most recent migrations applied (see: ```jooq-codegen-maven```). During verify phase we use test containers for testing purpose, incl. DB setup. But aside from how we use it the issue I'm describing will be general issue for ```docker-maven-plugin``` which has ```stop``` execution goal while there seems to be no way in MVN to be able to rely on it in the build script. – alwi Nov 13 '20 at 10:54
  • Docker means usually integration testing which I have described (or using testcontainers is different)... any other area sounds to me wrong ... a solution could be to put the generation into a separate module which only is responsible for generation where this can be done different which then can be used as a dependency in your project... – khmarbaise Nov 13 '20 at 16:22
  • Putting the code generation into a separate module will just move the problem elsewhere and won't solve it (besides it's already a separate, small DAO module within the project). I need to run DB for https://www.jooq.org/doc/latest/manual/code-generation/ before entering compile phase for the module. Maybe docker mvn plugin is not best for that but then I'm open for any suggestions how can it be substituted for mvn code generation while still keeping everything fully automated... – alwi Nov 16 '20 at 08:33

1 Answers1

0

The goal could be achieved applying similar solution to what testcontainers are doing using Ryuk: https://github.com/testcontainers/moby-ryuk

The image to reap should be labeled, e.g. as:

<autoRemove>true</autoRemove>
<labels>
   <killme>true</killme>
</labels>
<wait>
   <time>3000</time>
</wait>

The above delay is to give some time for Ryuk setup. As this one must be started in parallel...

                        <image>
                            <alias>ryuk-summoned</alias>
                            <name>testcontainers/ryuk:0.3.0</name>
                            <run>
                                <ports>
                                    <port>ryuk.port:8080</port>
                                </ports>
                                <volumes>
                                    <bind>
                                        <volume>/var/run/docker.sock:/var/run/docker.sock</volume>
                                    </bind>
                                </volumes>
                                <autoRemove>true</autoRemove>
                            </run>
                        </image>

The challange is that there must be feed with a hartbeat towards Ryuk container at least 1 per 10s through a TCP socket containing deathnote, eg. like this: printf "label=killme" | nc localhost 8080.

This is easy to achieve with below maven exec plugin and a simple setup-ryuk.sh script calling the command mentioned above. (NOTE: this provides only single deathnote with no consecutive heartbeats so Ryuk dies by itself in next 10s - at that time it will reap all items for which it received a note).

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <execution>
                        <id>stop-postgres</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <target>
                        <exec executable="bash">
                            <arg value="setup-ryuk.sh"/>
                            <arg value="${ryuk.port}"/>
                        </exec>
                    </target>
                </configuration>
            </plugin>

To make this platform independent (as the above is valid for Linux/Mac) and to keep Ryuk alive for longer time the best way seems to be to come up with own maven plugin sending messages to TCP socket.

alwi
  • 431
  • 6
  • 21