Testcontainers-java: How do you define named volumes when using GenericContainers

Created on 1 May 2018  路  13Comments  路  Source: testcontainers/testcontainers-java

I have an image and I can set named volumes wither using docker run:

docker run -it \
-p 1990:1990 \
-v docker-maven-repo:/root/.m2 \
--name my-container \
my-local-image"

or inside a docker-compose.yml file:

version: "3"
services:
  my-service:
    image: my-local-image
    volumes:
      - "docker-maven-repo:/root/.m2"
    ...
volumes:
  docker-maven-repo:

I don't seem to find a way to declare a named volume using GenericContainer.

Thanks for your help.

typfeature typquestion

Most helpful comment

For those trying to achieve what I was mentioning above:

@ClassRule
public static MongoDBContainer mongo = new MongoDBContainer()
    .withCreateContainerCmdModifier(cmd -> cmd
    .withBinds(Bind.parse("mongodb_data:/data/db")));

All 13 comments

You are right, currently we only support volume mappings. Are named volumes required for your use case?

@aruizca FYI you can customize the CreateContainerCmd yourself if the feature you want is not supported (yet?) by Testcontainers:
https://www.testcontainers.org/usage/options.html#customizing-the-container

@kiview ,
Named volumes is the only effective way I know to share a volume among containers. Eg: a Maven repository, so I don't have to download dependencies for each container.

@bsideup ,
I'll try that. Please consider the possibility of adding support for named volumes.

Thanks guys!

@aruizca volume will be removed once tests are executed. Testcontainers is mainly focused on Integrating testing, and "download dependencies for each container" sounds like a misuse :)

You can use withFileSystemBind() to mount a directory on your host to persist some state, but this is not recommended in general

@bsideup you are right when on a CI environment. But to speed things up locally while you implement your tests, named volumes can be very beneficial. Maybe, when used, named volumes should not be removed by default.
In my use case I am working with Maven artifacts bigger than half a GB. So supporting this would make developing tests faster.

@bsideup My use case is very particular. I can probably change the approach so that I resolve the dependencies at image build time instead of at container start up time.

@aruizca the question is - why are you running Maven with Testcontainers? :)

resolve the dependencies at image build time instead of at container start up time.

This approach is much better and gives you a reproducible testing. By default Testcontainers will delete the image after the tests, but you can pass false to deleteOnExit to keep it 馃憤
See https://www.testcontainers.org/usage/dockerfile.html#automatic-deletion

@aruizca You can also try to leverage Docker features such as multi-stage builds and image layer caching for caching your build dependencies (we once did something similar for a NPM based project). This way you can share (non-dynamic) data between containers/images. Feel free to share your actual use case if possible, so we can recommend some ideas (either here or in our Slack channel).

Thanks @kiview!! I was trying to run Confluence using the Atlassian SDK which implies executing a command as container entrypoint which then would use Maven to download deps. I have changed the approach know because the advantages are not enough to justify not using the normal tar.gz standalone distribution of Confluence.

I can see another use case.
In our case, we're using testContainers for integration test. For some cases, we want to spin up a mongodb container with a qa dump. A mongorestore takes long but if we were able to just mount the named volume to the MongoDBContainer, it would be almost instantaneous.
I'm not sure if it is the best approach, nevertheless. I'm open for discussion on alternative.
Thank you

For those trying to achieve what I was mentioning above:

@ClassRule
public static MongoDBContainer mongo = new MongoDBContainer()
    .withCreateContainerCmdModifier(cmd -> cmd
    .withBinds(Bind.parse("mongodb_data:/data/db")));

As cmd.withBinds is marked as deprecated, this works as well:

@ClassRule
public static MongoDBContainer mongo = new MongoDBContainer()
    .withCreateContainerCmdModifier(cmd -> cmd.getHostConfig().withBinds(Bind.parse("mongodb_data:/data/db")));

As cmd.withBinds is marked as deprecated, this works as well:

@ClassRule
public static MongoDBContainer mongo = new MongoDBContainer()
    .withCreateContainerCmdModifier(cmd -> cmd.getHostConfig().withBinds(Bind.parse("mongodb_data:/data/db")));

Would withFileSystemBind("mongodb_data", "/data/db") work just as well, or are there differences that I've missed?

Was this page helpful?
0 / 5 - 0 ratings