首页 > 解决方案 > Jar 在主机上运行,​​但在 docker 容器中失败

问题描述

我有一个jar在我的主机上运行良好;具体来说,当我跑步时

java -jar myjar.jar

我得到了预期的输出:

[2018-12-05 16:46:53.917] boot - 21252 INFO [main] --- 应用程序:未设置活动配置文件,回退到默认配置文件:默认

[2018-12-05 16:47:00.855] boot - 21252 INFO [main] --- Application: Started Application in 8.176 seconds (JVM running for 9.106) 这是核心数据微服务。

[2018-12-05 16:47:00.856] boot - 21252 INFO [main] --- 应用程序:注册到事件队列

[2018-12-05 16:47:00.857] boot - 21252 INFO [main] --- ZeroMQEventSubscriber:获取订阅者,监听 tcp://localhost:5565

[2018-12-05 16:47:00.915] boot - 21252 INFO [main] --- ZeroMQEventSubscriber:正在查看新的事件消息...

但是,我尝试jar在 docker 容器中运行相同的内容。所以我创建这样的图像:

FROM openjdk:8-jdk-alpine
COPY myjar.jar /opt/spring-cloud/lib/
ENTRYPOINT ["/usr/bin/java"]
CMD ["-jar", "/opt/spring-cloud/lib/myjar.jar"]
EXPOSE 48080

并运行它:

sudo docker run [ID]

但是这一次,我从容器日志中得到了这个异常(这只是异常的一部分,因为它太大了,但如果需要我可以全部显示出来):

[2018-12-07 08:30:31.447] boot - 1  INFO [main] --- Application: No active profile set, falling back to default profiles: default

[2018-12-07 08:32:35.423] boot - 1 ERROR [main] --- SpringApplication: Application startup failed

...

...

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'readingControllerImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.edgexfoundry.dao.ValueDescriptorRepository org.edgexfoundry.controller.impl.ReadingControllerImpl.valDescRepos; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'valueDescriptorRepository': Invocation of init method failed; nested exception is org.springframework.dao.DataAccessResourceFailureException: Timed out after 120000 ms while waiting for a server that matches AnyServerSelector{}. Client view of cluster state is {type=Unknown, servers=[{address=localhost:27017, type=Unknown, state=Connecting, exception={com.mongodb.MongoException$Network: Exception opening the socket}, caused by {java.net.ConnectException: Connection refused (Connection refused)}}]; nested exception is com.mongodb.MongoTimeoutException: Timed out after 120000 ms while waiting for a server that matches AnyServerSelector{}. Client view of cluster state is {type=Unknown, servers=[{address=localhost:27017, type=Unknown, state=Connecting, exception={com.mongodb.MongoException$Network: Exception opening the socket}, caused by {java.net.ConnectException: Connection refused (Connection refused)}}]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)

...

...

Caused by: com.mongodb.MongoTimeoutException: Timed out after 120000 ms while waiting for a server that matches AnyServerSelector{}. Client view of cluster state is {type=Unknown, servers=[{address=localhost:27017, type=Unknown, state=Connecting, exception={com.mongodb.MongoException$Network: Exception opening the socket}, caused by {java.net.ConnectException: Connection refused (Connection refused)}}]
    at com.mongodb.BaseCluster.getServer(BaseCluster.java:82)
    at com.mongodb.DBTCPConnector.getServer(DBTCPConnector.java:664)
    at com.mongodb.DBTCPConnector.access$500(DBTCPConnector.java:40)
    at com.mongodb.DBTCPConnector$MyPort.getConnection(DBTCPConnector.java:513)
    at com.mongodb.DBTCPConnector$MyPort.get(DBTCPConnector.java:456)
    at com.mongodb.DBTCPConnector.getPrimaryPort(DBTCPConnector.java:415)
    at com.mongodb.DBCollectionImpl.createIndex(DBCollectionImpl.java:378)
    at com.mongodb.DBCollection.createIndex(DBCollection.java:597)
    at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.createIndex(MongoPersistentEntityIndexCreator.java:142)
    ... 57 more

Mongo 已经通过 docker-compose 在另一个容器中启动(连同其他容器中的其他服务):

ps aux | grep mongo

root     16226  0.0  0.0   4340   768 ?        Ss   10:27   0:00 /bin/sh -c /edgex/mongo/config/launch-edgex-mongo.sh
root     16292  0.0  0.0   4340   764 ?        S    10:27   0:00 /bin/sh /edgex/mongo/config/launch-edgex-mongo.sh
root     16293  0.5  0.3 961168 61400 ?        SLl  10:27   0:05 mongod --smallfiles

这是 docker-compose 文件:

version: '3'

services:
  volume:
    image: edgexfoundry/docker-edgex-volume:0.6.0
    container_name: edgex-files
    networks:
      - edgex-network
    volumes:
      - db-data:/data/db
      - log-data:/edgex/logs
      - consul-config:/consul/config
      - consul-data:/consul/data

  mongo:
    image: edgexfoundry/docker-edgex-mongo:0.6.0
    ports:
      - "27017:27017"
    container_name: edgex-mongo
    hostname: edgex-mongo
    networks:
      - edgex-network
    volumes:
      - db-data:/data/db
      - log-data:/edgex/logs
      - consul-config:/consul/config
      - consul-data:/consul/data
    depends_on:
      - volume

.... more services...

 networks:
   edgex-network:
     driver: "bridge

和 mongo db 配置属性:

spring.data.mongodb.username=core
spring.data.mongodb.password=password
spring.data.mongodb.database=coredata
#change to localhost when running locally during development 
# (or set hosts to point edgex-mongo to the mongo host
spring.data.mongodb.host=localhost
#spring.data.mongodb.host=edgex-mongo
spring.data.mongodb.port=27017
spring.data.mongodb.connectTimeout=120000
spring.data.mongodb.socketTimeout=60000
spring.data.mongodb.maxWaitTime=120000
spring.data.mongodb.socketKeepAlive=true

任何想法可能出了什么问题?

标签: mongodbdockerjardocker-container

解决方案


There are two things going wrong here, first of all spring tries to connect to your mongodb on localhost, within docker this does not work since localhost references to the current container where of course no mongodb is available. To fix this you have to comment out this line and uncomment the next line which lists the host as edgex-mongo which corresponds with the hostname of your mongodb container, so spring knows to connect to that container.

However when you would do this you would run into the issue that it would not recognize edgex-mongo since it has no connection to this container. edgex-mongo is inside a bridged network which requires you to add the spring container to this network by using the following command:

docker run --network edgex--network [image]

I hope this helps you


推荐阅读