Skip to content

Repeated creation of ImageFromDockerfile has problems with connectivity #262

Closed

Description

@lbialy

Hello,

I'm using testcontainers-java in my project to test FTP operations and I have run into strange connectivity issues. Docker container used is created via ImageFromDockerfile class. Tests are running using Docker for Mac (Docker version 1.12.6, build 78d1802). Here's the groovy code that prepares docker image:

        def image = new ImageFromDockerfile('vsftpd', false).withDockerfileFromBuilder { builder ->
            builder
                    .from("panubo/vsftpd:latest")
                    .expose(ftpdPort, pasvPort)
                    .copy("vsftpd.conf", "/etc/")
                    .copy("entry.sh", "/")
                    .copy("clean.sh", "/")
                    .run("chmod 777 /entry.sh")
                    .run("chmod 777 /clean.sh")
                    .build()
        }

        return image
                .withFileFromClasspath("vsftpd.conf", "vsftpd.conf")
                .withFileFromClasspath("entry.sh", "entry.sh")
                .withFileFromClasspath("clean.sh", "clean.sh")

That image is then fed to constructor of GenericContainer in child class which uses addFixedExposedPort to expose ftpd and pasv port. Image works wonderfully in single test suite, but when it is used in multiple test suites (each test suite uses Guice to obtain instances of objects under test) multiple instances are started in sequence and when two tests using this particular image happen to be next to each other the second one fails (most often only first test fails) due to connection to FTP server being closed mid-operation. This occurs only when test suites using this image are executed in sequence - if another test suite is executed between them everything works fine. I've been able to confirm that this is in fact a timing issue by using a naive implementation of WaitStrategy containing only: (withStartupTimeout simply returns this)

    @Override
    void waitUntilReady(GenericContainer container) {
        Thread.sleep(500)
    }

This solution actually works, but it's viable only as a temporary measure. A more sophisticated version of WaitStrategy using java.net.Socket::connect in while loop with timeout constraint wasn't helping due to connection being established on first attempt by Socket and then severed from server side during test using FTP client lib.

Any clues?

Activity

  1. bsideup commented on Jan 12, 2017

    @bsideup
    Member

    Hi!

    .expose(ftpdPort, pasvPort)
    if ftpdPort or pasvPort are random values then for each build you will build a new image, it's not recommended, also, luckily you don't have to.

    addFixedExposedPort is protected, not public, because usually, you don't have to use it. It's always better to use withExposedPort(somePort) and then getMappedPort(somePort).
    You can read about it in the docs: https://www.testcontainers.org/usage/generic_containers.html#accessing-a-container-from-tests

    This way you can build a single image and reuse it for every test.
    Hope it helps.

  2. lbialy commented on Jan 12, 2017

    @lbialy
    Author

    I am building single image - according to docs new ImageFromDockerfile('vsftpd', false) false as second parameter causes image to be cached until JVM exits. I also know that addFixedExposedPort is protected, but I have no other choice - ftp server has to run in PASV mode in which it transmits the PASV port during session for download. I could get mapped ports while using withExposedPort, but I can't tell my FTP client library (apache commons-net FTPClient): "use port x when server tells you to use port y". I've limited number of ports to one for incoming FTP connections and one for PASV mode, because I never download files concurrently and I'm providing 2 random free ports on each container start. The container works perfectly (I've added second bash script for ease of removal of files on testcase cleanup) and tests are passing - just not when two tests using this particular container are executed one after another.

  3. bsideup commented on Jan 23, 2017

    @bsideup
    Member

    Hey @lbialy,
    We released 1.1.8 with a fix for the pipes, could you please try it?

  4. lbialy commented on Feb 1, 2017

    @lbialy
    Author

    Hey @bsideup,
    Right now I'm focusing on #284, but I'll try removing that naive WaitStrategy and rerun tests with 1.1.8 sometime soon.

  5. stale commented on Oct 28, 2018

    @stale

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe this is a mistake, please reply to this comment to keep it open. If there isn't one already, a PR to fix or at least reproduce the problem in a test case will always help us get back on track to tackle this.

  6. stale commented on Nov 11, 2018

    @stale

    This issue has been automatically closed due to inactivity. We apologise if this is still an active problem for you, and would ask you to re-open the issue if this is the case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions