无法从外部Docker容器访问SpringBoot @RestController [英] SpringBoot @RestController not accessible from outside docker container
问题描述
tl; dr一个RestController如果在Docker容器中运行,则可以正确回答,而另一个则不能.
tl;dr One RestController answers properly, the other doesn't, if run inside a Docker container.
该服务有两个API alive
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);
}
}
和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);
}
}
它们都通过docker-compose运行.
They are both run through docker-compose.
version: '2'
services:
service:
image: my/service
ports:
- "4000:4000"
docker-machine ip
返回192.168.99.100
.
alive
返回一个空的200响应.符合预期.
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
应该返回200响应,并且每次调用API时数字都会增加.遗憾的是没有.
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
maven-spotify插件用于根据以下Dockerfile
创建图像.
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"]
我正在使用最新的Docker和Docker-Compose版本(已于2016年8月22日下载).
I am using the latest Docker and Docker-Compose versions (downloaded them 22. August 2016).
已解决!请参阅下面的更新部分.找到最终答案后将确定问题. -问题:为什么无法从Docker容器外部访问callcount
?
Solved! See updates section below. Will finalize question when final answer ist found. - Question: Why is callcount
not accessible from outside the Docker container?
进一步尝试:
-
@CrossOrigin(origins = "*", maxAge = 3600)
-相同的结果 - spring文档.
- 将这两种方法合并到AliveController中.
- 删除了每个容器和映像,并从头开始重新构建docker.
@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.
日期:
Spring未注册callcount
API.我添加了另一个test
API来验证这一点,它也无法通过curl访问. alive
仍然可以正常工作并显示在日志中.
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()
我在本地使用JDK 1.8(java.vm.vendor = Oracle Corporation).
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)
启动方法之间的差异
在IntelliJ之外并使用mvn spring-boot:run
运行应用程序时,callcount
已正确注册.如果使用
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
或
java -jar my-service.jar
.这应该是为什么无法从Docker容器中访问它的原因.
java -jar my-service.jar
. This should be the cause why it is not accessible from within the Docker container.
知道为什么会这样吗?在2015年末的另一个项目中,它的工作原理如此.
Any idea why this is the case? It worked like that in another project from late 2015.
推荐答案
我能够在@ daniel.eichten和@ShawnClark的帮助下解决问题,但我不明白为什么为什么失败/工作. T
I was able to solve the problem with help from @daniel.eichten and @ShawnClark, but I don't understand why this fails/works. T
这不是Docker问题,而是Spring.
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);
}
}
到
@EnableAutoConfiguration
@EnableWebMvc
@Configuration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
现在,即使在Docker容器中运行时,也可以按预期访问所有API.
Now all APIs are accessible as expected, also when running inside a Docker container.
这篇关于无法从外部Docker容器访问SpringBoot @RestController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!