【问题标题】:Connecting Spring Boot Docker container to MongoDB docker container将 Spring Boot Docker 容器连接到 MongoDB docker 容器
【发布时间】:2017-11-10 09:31:42
【问题描述】:

我正在尝试将 spring boot docker 容器连接到 mongodb docker 容器。在开发 Spring Boot 应用程序时,我使用了一个 MongoDB docker 容器,其端口 27017 映射到主机的 27017 端口,docker run -p 27017:27017 mongo:3.4。开发完成后,我将spring app容器化了,但是容器化的spring app无法连接到mongodb容器。我知道问题是 spring 应用程序正在本地主机上寻找 mongodb。我的问题是我应该如何修改应用程序,以便它使用 mongodb 容器的地址而不是在本地主机上查找 mongodb?

我的数据库连接由以下类处理:

public class DB {
private final Datastore datastore;
private Morphia morphia;

/**
 * Constructor for creating database instance
 */
public DB() {
    morphia = new Morphia();
    morphia.mapPackage("users");
    datastore =
            morphia.createDatastore(new MongoClient(), "test");
    datastore.ensureIndexes();
}

/**
 * Inserts given user to the database
 *
 * @param u a newly created user.
 */
public void addUser(User u) {
    datastore.save(u);
}

/**
 * Fetches and prints all documents in database
 *
 * @return json array of all documents in database
 */
public String getUsers() {
    final Query<User> query = datastore.createQuery(User.class);
    final List<User> employees = query.asList();

    return objToJson(employees);
}

/**
 * Returns the user with the specified ID.
 *
 * @param userID is the ID of the document in database
 * @return document in json format
 */
public String getUser(ObjectId userID) {
    final Query<User> query = datastore.createQuery(User.class)
            .field("id").equal(userID);

    final List<User> employees = query.asList();
    return objToJson(employees);
}

/**
 * Deletes the document with the given ID from database.
 *
 * @param userID is the ID of the document to be removed
 */
public void removeUser(ObjectId userID) {
    final Query<User> query = datastore.createQuery(User.class)
            .field("id").equal(userID);
    datastore.delete(query);
}

/**
 * Deletes all documents from database.
 */
public void removeUsers() {
    final Query<User> query = datastore.createQuery(User.class);
    datastore.delete(query);
}

/**
 * Updates the fields of the document with given ID.
 *
 * @param userID  is the ID of the document to be updated
 * @param newUser contains the new fields
 * @return results of the update in json format
 */
public String updateUser(ObjectId userID, User newUser) {
    final Query<User> query = datastore.createQuery(User.class)
            .field("id").equal(userID);
    final UpdateOperations<User> updateOperations = datastore.createUpdateOperations(User.class);

    if (newUser.getFirst_name() != null) {
        String newName = newUser.getFirst_name();
        updateOperations.set("first_name", newName);
    }

    if (newUser.getLast_name() != null) {
        String newLastName = newUser.getLast_name();
        updateOperations.set("last_name", newLastName);
    }

    if (newUser.getSalary() != 0) {
        int newSalary = newUser.getSalary();
        updateOperations.set("salary", newSalary);
    }

    final UpdateResults results = datastore.update(query, updateOperations);
    return results.toString();

}

/**
 * Translate object lists to the json array.
 *
 * @param query is the list of the user objects
 * @return json array of the given users
 */
private String objToJson(List<User> query) {
    List<String> attsToRemove = Arrays.asList(new String[]{"className"});

    List<DBObject> dbObjList = new ArrayList<>(query.size());
    DBObject dbObj;
    for (Object obj : query) {
        dbObj = morphia.toDBObject(obj);
        for (int i = 0; i < attsToRemove.size(); i++) {
            dbObj.removeField(attsToRemove.get(i));
        }
        dbObjList.add(dbObj);
    }
    String json = JSON.serialize(dbObjList);
    return json;
}

这是我的 Spring Boot 控制器

@RestController
public class DemoController {

DB mongodb = new DB();

@RequestMapping(value = "/", method = RequestMethod.GET)
public String index() {
    return "Greetings from Spring Boot";
}

@RequestMapping(value = "/users/{user_id}", method = RequestMethod.GET)
public String getUser(@PathVariable("user_id") ObjectId userID) {
    return mongodb.getUser(userID);
}

@RequestMapping(value = "/users", method = RequestMethod.GET)
public String getUsers() {
    return mongodb.getUsers();
}

@RequestMapping(value = "/users", method = RequestMethod.POST)
public void createUser(@RequestBody User u) {
    try {
        mongodb.addUser(u);
    } catch (Exception e) {
        System.out.println(e.toString());
    }
}

@RequestMapping(value = "/users", method = RequestMethod.DELETE)
public void deleteUsers() {
    try {
        mongodb.removeUsers();
    } catch (Exception e) {
        System.out.println(e.toString());
    }
}

@RequestMapping(value = "/users/{user-id}", method = RequestMethod.DELETE)
public void deleteUser(@PathVariable("user-id") ObjectId userID) {
    try {
        mongodb.removeUser(userID);
    } catch (Exception e) {
        System.out.println(e.toString());
    }
}

@RequestMapping(value = "/users/{user-id}", method = RequestMethod.PUT)
public String updateUser(@PathVariable("user-id") ObjectId userID, @RequestBody User u) {
    return mongodb.updateUser(userID, u);
}

这是我的 Dockerfile: FROM frolvlad/alpine-oraclejdk8:slim VOLUME /tmp ADD demo-0.0.1-SNAPSHOT.jar app.jar EXPOSE 27017 EXPOSE 8080 RUN sh -c 'touch /app.jar' ENV JAVA_OPTS="" ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

我阅读了herehere 提到的解决方案。还通读了几个教程,但我无法将这些解决方案中的任何一个应用于我的代码。在我的代码中,我应该在哪里更改?

【问题讨论】:

    标签: java spring mongodb spring-mvc


    【解决方案1】:

    主要问题是您的容器不在同一个网络中。我想您可以通过 How to run Spring Boot and MongoDB in Docker containe 找到一个工作示例。这是一个简短的摘录:

    1. docker network create spring_demo_net创建网络
    2. docker run --name spring-demo-mongo --network=spring_demo_net -v /home/ubuntu/mongo-data:/data/db -d mongo启动一个mongo容器
    3. 在应用程序属性中修改mongo主机如下spring.data.mongodb.uri=mongodb://spring-demo-mongo/YOUR_DB这里spring-demo-mongo是你在步骤1中创建的容器的名称。

    由于您没有使用 SpringData 存储库,因此它无法工作,因此您需要通过显式传递主机和端口来创建 MongoClient:

    MongoClient mongoClient2 = new MongoClient("spring-demo-mongo", 27017);
    
    1. docker build --tag=spring-demo-1.0 用标签构建你的 docker 镜像
    2. docker run -d --name spring-demo --network=spring_demo_net -p 8080:8080 spring-demo-1.0 启动你的 docker 镜像

    【讨论】:

    • 我按照你说的做了,但是没用。 Spring Boot日志说:com.mongodb.MongoSocketOpenException:异常打开套接字原因:java.net.ConnectException:连接被拒绝(连接被拒绝)并且mongodb日志保持如下:2017-06-08T15:33:40.094 + 0000 I NETWORK [ thread1] 等待端口 27017 上的连接
    • @FatihBarmanbay 我想问题是您没有在 mongo 客户端中配置主机,因为您不使用 SringData 我提到的属性对您不起作用。
    • 我更改了行:datastore = morphia.createDatastore(new MongoClient(), "test");datastore = morphia.createDatastore(new MongoClient("spring-demo-mongo", 27017), "test"); 但是当我尝试使用 mvn clean install 构建项目时,我收到一条错误消息:com.mongodb.MongoSocketException: spring- demo-mongo 引起:java.net.UnknownHostException: spring-demo-mongo
    • @FatihBarmanbay 你有一些在 Maven 构建期间运行的单元测试吗?如果是这样,请通过运行“mvn package -Dmaven.test.skip=true”禁用它们,因为您正在尝试访问 docker 容器之外的 mongo 主机
    猜你喜欢
    • 2022-11-01
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 2019-02-16
    • 2019-02-24
    • 2019-01-12
    • 2019-08-27
    相关资源
    最近更新 更多