3

I have server and client applications. Server is launched inside docker container. I want to test scenario that server crashes and comes back. Client is connected to server before crash and automatically connects to server when server is back. The problem is that testcontainers maps ports randomly and server listens on different port after come back.

I use org.testcontainers.containers.GenericContainer#withExposedPorts method to expose ports. I kill and start container using following code:

container.getDockerClient()
            .killContainerCmd( container.getContainerId() )
            .exec();
container.getDockerClient()
            .startContainerCmd( container.getContainerId() )
            .exec();

or

container.stop();
container.start();

I tried to set port binding but it does not work.

setBinding(container)
container.getDockerClient()
            .killContainerCmd( container.getContainerId() )
            .exec();
container.getDockerClient()
            .startContainerCmd( container.getContainerId() )
            .exec();
...
  private void setBinding( GenericContainer aContainer )
    {
        List< Integer > exposedPorts = aContainer.getExposedPorts();
        List< String > bindings = new ArrayList<>();
        exposedPorts.forEach( e -> bindings.add( aContainer.getMappedPort( e ) + ":" + e ) );
        aContainer.setPortBindings( bindings );
    }

How to kill and start again container? I would like to note that I do not want to start other container with the same port mapping. I want to start the same container with the same port mapping.

Mariusz
  • 1,907
  • 3
  • 24
  • 39
  • do you really have to kill the whole container? Would it be an option to just temporarily stop the server inside the container? E.g. if it's a Java application kill the `java` process and then restart the server while keeping the container alive – rieckpil Dec 16 '20 at 07:07
  • I wanted to kill container because I was sure that it is easy and I did not expected such problems with testcontainers. I do not think it is easy to kill and start process inside container in automatic test. My container does not have ps command so probably I have to install it or use docker top. Executing `docker exec -it CID kill -9 PID` or `docker exec -it CID /bin/kill -9 PID` throws `"kill": executable file not found in $PATH: unknown` or `"/bin/kill": stat /bin/kill: no such file or directory: unknown`. – Mariusz Dec 16 '20 at 08:55
  • I cannot believe that library dedicated to containers testing does not support such base thing like container restart. I hope that container restart is possible, I just do not know hot to do it. – Mariusz Dec 16 '20 at 15:36
  • 1
    As Testcontainers is an open-source library, you can contribute and may consider implementing this feature https://github.com/testcontainers/testcontainers-java – rieckpil Dec 16 '20 at 17:13

1 Answers1

0

I have found a solution:

  1. Create a snapshot of your current running container using (docker commit via the dockerClient)
  2. stop your container
  3. Set the new image name to your same container object
  4. then call start method again

Example: (this refers to a GenericContainer object)

public void restart() {
        String tag = this.getContainerId();
        String snapshotId = dockerClient.commitCmd(this.getContainerId())
                .withRepository("tempImg")
                .withTag(tag).exec();
        this.stop();
        this.setDockerImageName("tempImg:" + tag);
        this.start();
}

Some advantages:

  • You will keep getting the benefit of the WaitStrategy (if defined).
  • The temp image will be removed after the end of the test.
  • The new exposed port will be mapped again to your GenericContainer object.
Shmayro
  • 1
  • 3