如何使用docker容器名称而不是IP通过knex进行数据库连接

时间:2019-05-24 21:06:33

标签: docker knex.js

我在docker容器中有一个postgresql数据库,在另一个docker容器(nodeJS)中有一个后端API。这两个容器都是使用docker-compose启动的,因此使用的是桥接网络。

如果我在节点后端API中使用标准的http post请求,则可以使用数据库的docker容器名称(如预期的那样)连接到数据库,如下所示(仅显示设置的代码段):

const UN = 'postgres';
const PW = '<PW>';
const host = 'myContainerName:5432';
const database = '<DB>';

const expireDuration = 120;

//DB Connection object (client)
var conString = "postgres://" + UN + ":" + PW + "@" + host + "/" + database;
...

这有效,因为容器名称(向下3行)由Docker中的某种NAT关联来解释(我不太了解Docker的内部工作原理)。但是我知道使用容器名称是必要的,因为容器的IP地址可能会更改。

但是,我现在希望改为在后端API中使用Knex连接到postgresql数据库,因为我希望开始使用数据库迁移,而Knex是我选择的工具。

但是,例如,Knex仅允许我使用docker容器的IP地址而不是其容器名称进行连接(这是Knex设置):

development: {
    client: 'pg',
    connection: {
      host : 'myContainerName:5432',
      //host : '172.20.0.3:5432',
      user : 'postgres',
      password : '<PW>',
      database : '<DB>'
    },
    migrations: {
      tableName: 'knex_migrations'
    }
}

如果我将主机名的注释更改为容器名,它将无法连接。

有人能期望我的工作正常吗?是否可以在Knex中使用容器名称?

2 个答案:

答案 0 :(得分:2)

  1. 如果要从主机上的Knex连接到数据库容器,则必须公开数据库容器中的端口。这是通过使用-p选项完成的:
docker container run -p 5432:5432 dbImageName

您将能够使用localhost:5432作为主机从knex连接到数据库。

  1. 如果您正在使用docker-compose,并且想要在另一个容器中运行knex,只需将服务定义放在docker-compose中。它将创建默认网络并将所有容器连接到该网络。然后,由于在下面创建了DNS服务器,因此可以通过其名称从该网络上的其他容器访问容器。

  2. 如果您不使用docker compose。您可以自己创建网络:

docker network create my_net

驱动程序默认为bridge。然后,在运行容器时,您必须传递--network选项:

docker container run --network=my_net imageName

当然,您仍然可以根据需要公开主机的端口。

  1. 也请尝试在配置中分离主机和端口:
connection: {
      host : 'myContainerName',
      port : 5432
...
  1. 您还可以尝试将connection作为字符串连接:
var pg = require('knex')({
  client: 'pg',
  connection: 'postgres://postgres:pass@myContainerName:5432/db'
})

答案 1 :(得分:0)

带有容器名称的Docker DNS解析只能在容器内部使用,但是您可以将端口发布到主机IP / localhost并连接到该主机。 看起来像这样:

//this is the entire js page at the moment
var WorkingOutManager = (function () {

    this.setCounter = 1;
    this.workoutCounter = 1;

    this.workoutID = "workout" + workoutCounter + "_set" + setCounter;

    this.changeState = () => {
        //I will eventually add the code to change the state of the div
        console.log(this.workoutID);
    }

    this.currentSetButton = document.getElementById(this.workoutID).
    this.currentSetButton.addEventListener("click", this.changeState);

    return {
        changeState: changeState
    }

})();