SpringBoot @RestController not accessible from out

2019-06-01 04:27发布

问题:

tl;dr One RestController answers properly, the other doesn't, if run inside a Docker container.

The service has two APIs alive

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
public class AliveController {
    @RequestMapping(value = "/alive", method = RequestMethod.GET)
    public ResponseEntity<?> alive() {
        return new ResponseEntity<>(HttpStatus.OK);
    }
}

and callcount.

@CrossOrigin
@RestController
public class CallController {

    private static int callCount = 0;

    @RequestMapping(value = "/callcount", method = RequestMethod.GET)
    public ResponseEntity<?> callCount() {
        return new ResponseEntity<>(++callCount, HttpStatus.OK);
    }
}

They are both run through docker-compose.

version: '2'

services:
  service:
    image: my/service
    ports:
      - "4000:4000"

docker-machine ip returns 192.168.99.100.

alive returns an empty 200 response. As expected.

$ curl -i http://192.168.99.100:4000/alive
HTTP/1.1 200
Content-Length: 0
Date: Mon, 22 Aug 2016 17:33:58 GMT

callcount should return a 200 response and a number that increases every time the API is called. Sadly it does not.

$ curl -i http://192.168.99.100:4000/callcount
HTTP/1.1 404
Content-Type: application/hal+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 22 Aug 2016 17:37:26 GMT

{"timestamp":1471887446871,"status":404,"error":"Not Found","message":"No message available","path":"/callcount"}

Running the service locally provides the expected result.

$ curl -i http://localhost:4000/callcount
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 22 Aug 2016 17:43:40 GMT

1

The maven-spotify plugin is used to create an image from the following Dockerfile.

FROM java:8

EXPOSE 4000

VOLUME /tmp
ADD service*.jar app.jar

# http://stackoverflow.com/a/33882286/1309035
# Without this, Java uses /dev/random to seed its SecureRandom class, which can cause Java code to block unexpectedly.
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-jar","app.jar"]

I am using the latest Docker and Docker-Compose versions (downloaded them 22. August 2016).

Solved! See updates section below. Will finalize question when final answer ist found. - Question: Why is callcount not accessible from outside the Docker container?

Further attempts:

  • @CrossOrigin(origins = "*", maxAge = 3600) - same result
  • Global CORS configurations from the spring docs.
  • Merging the two methods into the AliveController.
  • Deleted every container and image and docker built again from scratch.

Udates:

The callcount API is not registered by Spring. I added another test API to verify this which is also not accessible through curl. alive still works fine and shows up in the logs.

bash-3.2$ docker logs asmstack_service_1 | grep callcount
bash-3.2$ docker logs asmstack_service_1 | grep test
bash-3.2$ docker logs asmstack_service_1 | grep alive
2016-08-23 08:42:06.530  INFO 1 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/alive],methods=[GET]}" onto public org.springframework.http.ResponseEntity<?> de.bahr.asmstack.AliveController.alive()

I use JDK 1.8 locally (java.vm.vendor = Oracle Corporation).

$ java -version
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)

Differences between startup methods

The callcount is properly registered when running the app out of IntelliJ and with mvn spring-boot:run. It does not get registered if run with

java -Djava.security.egd=file:/dev/./urandom -jar my-service.jar or

java -jar my-service.jar. This should be the cause why it is not accessible from within the Docker container.

Any idea why this is the case? It worked like that in another project from late 2015.

回答1:

I was able to solve the problem with help from @daniel.eichten and @ShawnClark, but I don't understand why this fails/works. T

It was not a Docker problem, but with Spring.

As seen here (question might be unrelated), I changed the Spring-Application from

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

to

@EnableAutoConfiguration
@EnableWebMvc
@Configuration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Now all APIs are accessible as expected, also when running inside a Docker container.