Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wait for 0.0.0.0:8080 instead of localhost:8080 #51

Closed
ghost opened this issue May 20, 2019 · 13 comments
Closed

Wait for 0.0.0.0:8080 instead of localhost:8080 #51

ghost opened this issue May 20, 2019 · 13 comments

Comments

@ghost
Copy link

ghost commented May 20, 2019

Hi all

Wait for 0.0.0.0:8080 instead of localhost:8080

In GenericContainer class, it exists a method waitingFor, that waits for status code 200 as reponse from the server.
I am running a web application in a container and use 0.0.0.0 as host instead of localhost.
When I try to run the sbt test, I've got following timeout:

[sweetsoft/sapmock:latest] - Could not start container
org.testcontainers.containers.ContainerLaunchException: Timed out waiting for container port to open (localhost ports: [8080] should be listening)  

I am using the test container as the following:

final class MessageSpec extends BddSpec
  with ForAllTestContainer
  with BeforeAndAfterAll {


  override val container = FixedHostPortGenericContainer("sweetsoft/sapmock",
    waitStrategy = Wait.forHttp("/"),
    exposedHostPort = 8080,
    exposedContainerPort = 8080,
  )


  override def beforeAll(): Unit = {

  }


  feature("Process incoming messages") {
    info("As a user, I want that incoming messages is going to process appropriately.")
    info("A message should contain the following properties: `sap_id`, `sap_event`, `payload`")

When I would remove waitStrategy = Wait.forHttp("/"), then it works fine but with waitStrategy = Wait.forHttp("/")
it goes into the timeout.

How to tell the Testcontainer to listen on 0.0.0.0 instead of the localhost?
I have described the problem with the localhost here: https://stackoverflow.com/questions/56201718/why-does-the-client-can-not-connect-to-localhost8080/56201938?noredirect=1#comment99027626_56201938

Thanks

@LMnet
Copy link
Contributor

LMnet commented May 20, 2019

Hi @bifunctor !

First of all, I'm trying to run your code but it looks like sweetsoft/sapmock is not a public container. Could you provide reproducible code, this will greatly simplify the search for a solution.

Are you sure that you need FixedHostPortGenericContainer? By default, testcontainers uses the random port and binds it for you. FixedHostPortGenericContainer is not recommended for most cases.

@ghost
Copy link
Author

ghost commented May 20, 2019

Hi LMnet

First of all, thanks for your response. I will publish the sweetsoft/sapmock container at this evening, because
I am at work now.

I am using FixedHostPortGenericContainer, because I do not know, how to get the random port.
I could not find the property, that provides the port like for Java:
https://www.testcontainers.org/features/networking/

Integer firstMappedPort = container.getFirstMappedPort(); 

How to get the random port?

Thanks

@LMnet
Copy link
Contributor

LMnet commented May 20, 2019

Here is the GenericContainer example in the docs: https://github.com/testcontainers/testcontainers-scala#generic-container.

You should add port you want to expose from the container in the exposedPorts argument. After that, you will be able to get mapped port with the mappedPort method. Like this:

override val container = GenericContainer("nginx:latest",
  exposedPorts = Seq(80)
)

"some test" in {
  container.mappedPort(80) // will return random mapped port
}

@ghost
Copy link
Author

ghost commented May 21, 2019

Hi @LMnet
Sorry for the late response. I uploaded the docker image to dockerhub and you can find it here https://hub.docker.com/r/kostonstyle/sapmock. The source code from the project, can be found here https://gitlab.com/sweetsoft/sapmock.

I've changed as you told me as the following:

inal class MessageSpec extends BddSpec
  with ForAllTestContainer
  with BeforeAndAfterAll {


  override val container = GenericContainer("sweetsoft/sapmock",
    exposedPorts = Seq(8080)
  )


  override def beforeAll(): Unit = {

  }


  feature("Process incoming messages") {
    info("As a user, I want that incoming messages is going to process appropriately.")
    info("A message should contain the following properties: `sap_id`, `sap_event`, `payload`")


    scenario("Message is not intended for the server") {
      Given("A message with `sap_id:unknown`")
      val req = SapRequestMsg("unknown", "unknown", "{foo: foo}")
      When("the message gets validated")
      val ws = WsClient.send(container.mappedPort(8080))(req)

But I've still got the message:

org.testcontainers.containers.ContainerLaunchException: Timed out waiting for container port to open (localhost ports: [32778] should be listening)

The statement docker ps shows:

 docker ps -a
CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS                      PORTS                     NAMES
05f2c7b5953f        kostonstyle/sapmock:latest          "/opt/docker/bin/sap…"   14 seconds ago      Exited (0) 11 seconds ago                             relaxed_cray
7f3d912dc2b7        quay.io/testcontainers/ryuk:0.2.3   "/app"                   15 seconds ago      Up 14 seconds               0.0.0.0:32779->8080/tcp   testcontainers-ryuk-52f86c68-ada3-43c7-a186-9cb050589b58

What am I doing wrong?

Hint: With the FixedHostPortGenericContainer, it worked.

Thanks

@LMnet
Copy link
Contributor

LMnet commented May 22, 2019

I didn't see from the docker ps output that your application exposes 8080 port: ports block is empty. Try to check your app.

I suggest you to try to run your application from the command line first, and after that integrate it with testcontainers.

@ghost
Copy link
Author

ghost commented May 22, 2019

Hi @LMnet

I've tried to run the server application from the commnad line and it works.
The container was started with following docker command:

docker run -it  -p 8080:8080 kostonstyle/sapmock
Server online at 0.0.0.0 on the port 8080
Press RETURN to stop...


and I could reached the web application via the browser. But with sbt test statement and got the timeout exception.

I am using https://github.com/sbt/sbt-native-packager to publish the docker image on local and as
you can see below, the exposed port is in https://gitlab.com/sweetsoft/sapmock/blob/master/build.sbt as the following:

enablePlugins(JavaServerAppPackaging)
enablePlugins(DockerPlugin)
enablePlugins(GitVersioning)
dockerExposedPorts := Seq(8080)

git.formattedShaVersion := git.gitHeadCommit.value map { sha =>
  s"$sha".substring(0, 7)
}

dockerUpdateLatest := true
dockerAlias := DockerAlias(None, Some("kostonstyle"), (packageName in Docker).value, git.gitDescribedVersion.value)

As mentioned above, starting the application manually with docker command, I have the access to the application.
But when I run the sbt test command, I've got the timeout exception.

The best way to figure out, what I mean is, to download the source code from the application on https://gitlab.com/sweetsoft/sapmock and
run the command sbt docker:publishLocal, then sbt test and you will see the timeout exception.

Hint: With the FixedHostPortGenericContainer, it works as expected.

Thanks for your help.

@ghost
Copy link
Author

ghost commented May 22, 2019

That is the whole log:

21:19:40.046 [pool-7-thread-6] ERROR 🐳 [kostonstyle/sapmock:latest] - Could not start container
org.testcontainers.containers.ContainerLaunchException: Timed out waiting for container port to open (localhost ports: [32770] should be listening)
        at org.testcontainers.containers.wait.strategy.HostPortWaitStrategy.waitUntilReady(HostPortWaitStrategy.java:47)
        at org.testcontainers.containers.wait.strategy.AbstractWaitStrategy.waitUntilReady(AbstractWaitStrategy.java:35)
        at org.testcontainers.containers.wait.HostPortWaitStrategy.waitUntilReady(HostPortWaitStrategy.java:23)
        at org.testcontainers.containers.wait.strategy.AbstractWaitStrategy.waitUntilReady(AbstractWaitStrategy.java:35)
        at org.testcontainers.containers.GenericContainer.waitUntilContainerStarted(GenericContainer.java:582)
        at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:259)
        at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:212)
        at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:76)
        at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:210)
        at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:199)
        at org.testcontainers.containers.GenericContainer.starting(GenericContainer.java:714)
        at org.testcontainers.containers.TestContainerAccessor$.starting(TestContainerAccessor.scala:13)
        at com.dimafeng.testcontainers.TestContainerProxy.starting(TestContainer.scala:106)
        at com.dimafeng.testcontainers.TestContainerProxy.starting$(TestContainer.scala:106)
        at com.dimafeng.testcontainers.SingleContainer.starting(TestContainer.scala:111)
        at com.dimafeng.testcontainers.ForAllTestContainer.run(TestContainer.scala:67)
        at com.dimafeng.testcontainers.ForAllTestContainer.run$(TestContainer.scala:63)
        at com.sweetsoft.MessageSpec.org$scalatest$BeforeAndAfterAll$$super$run(MessageSpec.scala:6)
        at org.scalatest.BeforeAndAfterAll.liftedTree1$1(BeforeAndAfterAll.scala:213)
        at org.scalatest.BeforeAndAfterAll.run(BeforeAndAfterAll.scala:210)
        at org.scalatest.BeforeAndAfterAll.run$(BeforeAndAfterAll.scala:208)
        at com.sweetsoft.MessageSpec.run(MessageSpec.scala:6)
        at org.scalatest.tools.Framework.org$scalatest$tools$Framework$$runSuite(Framework.scala:317)
        at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:510)
        at sbt.TestRunner.runTest$1(TestFramework.scala:113)
        at sbt.TestRunner.run(TestFramework.scala:124)
        at sbt.TestFramework$$anon$2$$anonfun$$lessinit$greater$1.$anonfun$apply$1(TestFramework.scala:282)
        at sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:246)
        at sbt.TestFramework$$anon$2$$anonfun$$lessinit$greater$1.apply(TestFramework.scala:282)
        at sbt.TestFramework$$anon$2$$anonfun$$lessinit$greater$1.apply(TestFramework.scala:282)
        at sbt.TestFunction.apply(TestFramework.scala:294)
        at sbt.Tests$.$anonfun$toTask$1(Tests.scala:309)
        at sbt.std.Transform$$anon$3.$anonfun$apply$2(System.scala:46)
        at sbt.std.Transform$$anon$4.work(System.scala:67)
        at sbt.Execute.$anonfun$submit$2(Execute.scala:269)
        at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
        at sbt.Execute.work(Execute.scala:278)
        at sbt.Execute.$anonfun$submit$1(Execute.scala:269)
        at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
        at sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
21:19:40.092 [pool-7-thread-6] ERROR 🐳 [kostonstyle/sapmock:latest] - Log output from the failed container:
Server online at 0.0.0.0 on the port 8080

Press RETURN to stop...

Look at the end, it starts the container. But it should start before this message appears

21:19:40.046 [pool-7-thread-6] ERROR 🐳 [kostonstyle/sapmock:latest] - Could not start container

Thanks

@ghost
Copy link
Author

ghost commented May 22, 2019

I did some research and I've found, that something is not right here:
Screenshot from 2019-05-22 22-20-06
Maybe it helps

@LMnet
Copy link
Contributor

LMnet commented May 23, 2019

I tried to use your container from the command line:

➜  ~ docker run -it  -p 32878:8080 kostonstyle/sapmock
Server online at 0.0.0.0 on the port 8080
Press RETURN to stop...

Here is docker ps output:

CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS              PORTS                     NAMES
4d075be5bbee        kostonstyle/sapmock                 "/opt/docker/bin/sap…"   4 seconds ago       Up 2 seconds        0.0.0.0:32878->8080/tcp   gracious_burnell

It looks like docker successfully bound 32878 host port to the 8080 container port.

In another terminal I tried to use wget to communicate with the app:

➜  ~ wget http://localhost:32878/
--2019-05-23 13:14:02--  http://localhost:32878/
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:32878... connected.
HTTP request sent, awaiting response... 404 Not Found
2019-05-23 13:14:02 ERROR 404: Not Found.

But as you can see from the output, it returns 404. That's why Testcontainers can't start your container.

I didn't deeply dive in your application code, but I think that issue is on the application side. Try to use steps above to reproduce the problem and solve it.

@ghost
Copy link
Author

ghost commented May 23, 2019

You are right. I corrected the error and pushed the new changes to the docker hub https://cloud.docker.com/u/kostonstyle/repository/docker/kostonstyle/sapmock.

I run the container after the change as the following:

docker run -it  -p 32773:8080 kostonstyle/sapmock
Server online at 0.0.0.0 on the port 8080
Press RETURN to stop...

And on the other window, I did:

wget 127.0.0.1:32773
--2019-05-23 18:50:28--  http://127.0.0.1:32773/
Connecting to 127.0.0.1:32773... connected.
HTTP request sent, awaiting response... 200 OK
Length: 31 [text/html]
Saving to: ‘index.html’

index.html          100%[===================>]      31  --.-KB/s    in 0s      

2019-05-23 18:50:28 (7.20 MB/s) - ‘index.html’ saved [31/31]

As you can see, I've got now the response code 200.
Running 'sbt test', I've still got the error message:

0},com.github.dockerjava.core.exec.ExecCreateCmdExec@48011915
18:57:34.472 [pool-7-thread-2] ERROR 🐳 [kostonstyle/sapmock:latest] - Could not start container
org.testcontainers.containers.ContainerLaunchException: Timed out waiting for container port to open (localhost ports: [32773] should be listening)

I do not know anymore, what should I do.

Screenshot from 2019-05-23 18-59-59

Thanks

@LMnet
Copy link
Contributor

LMnet commented May 23, 2019

I think I found the problem. After starting your application is waiting for the user input. When user press enter — application stops. But it will work only with the interactive console mode. Try to run your app in docker from the command line without -it flags — it will immediately stop. Testcontainers don't start containers in the interactive mode. So, in case of testcontainers your app will stop right after the start.

To fix the problem your application should be able to work in the daemon mode.

@ghost
Copy link
Author

ghost commented May 23, 2019

Wow....Thanks so much for your help. It works!!!!!! 1000 thanks.

@ghost ghost closed this as completed May 23, 2019
@dimafeng
Copy link
Collaborator

@LMnet great job! thank you for helping 👍

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants