如何将 docker 容器应用程序连接到非容器化数据库?

How connect docker container application to a non containerized database?

首先:我不想连接到docker容器,运行宁mongo。

我正在构建一个 docker 容器,它应该访问我安装在 运行ning Ubuntu 18.04 机器上的 mongo 数据库。

Docker 建议这可以通过将标志 -p 添加到 运行 命令来相当容易地完成,所以我这样做了:

docker run -p 27017:27017 --name mycontainer myimage

端口 27017 是 mongo 的默认端口(参见 here)并且 运行ning netstat -pna | grep 27017 通过返回以下内容来确认:

tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:27017         127.0.0.1:55880         ESTABLISHED -                   
tcp        0      0 127.0.0.1:55882         127.0.0.1:27017         ESTABLISHED -                   
tcp        0      0 127.0.0.1:55880         127.0.0.1:27017         ESTABLISHED -                   
tcp        0      0 127.0.0.1:27017         127.0.0.1:55884         ESTABLISHED -                   
tcp        0      0 127.0.0.1:27017         127.0.0.1:55882         ESTABLISHED -                   
tcp        0      0 127.0.0.1:55884         127.0.0.1:27017         ESTABLISHED -                   
unix  2      [ ACC ]     STREAM     LISTENING     77163    -                    /tmp/mongodb-27017.sock

但是运行使用上面显示的docker命令,我得到一个错误提示我无法连接到端口因为它已经在使用中(这实际上是连接到它):

docker: Error response from daemon: driver failed programming external connectivity on endpoint mycontainer (1c69e178b48ee51ab2765479e0ecf3eea8f43e6420e34b878882db8d8d5e07dd): Error starting userland proxy: listen tcp4 0.0.0.0:27017: bind: address already in use.
ERRO[0000] error waiting for container: context canceled 

我该如何进行?我做错了什么?

这取决于您的应用程序如何连接到数据库。

几乎所有语言都需要连接参数。

节点示例 & mysql:

const knex = require('knex')({
    client: 'mysql',
    connection: {
        host: '10.10.10.10',
        user: 'root',
        password: 'changeme',
        database: 'Whosebug'
    },
    debug: true
});

示例 python & mongo

import pymongo
conn = pymongo.MongoClient('mongodb://root:pass@10.10.10.10:27017/')

传统上,这些连接参数存储在属性或配置文件中。每个环境一个:dev、staging、prod 等

配置文件

如果您的应用程序使用此方法获取连接参数,您只需按照以下步骤操作:

  • 在配置文件中设置ip、端口、用户、密码。通常在您的源代码中:application.properties、config.yml、parameters.ini 等
  • 对您的应用执行 docker build ...
  • 对您的应用执行 docker run ...。在此步骤中,您不需要传递任何 mongo 参数,因为您的应用程序已经“内部”。检查 this and this 以了解为什么在 docker.
  • 中不使用 localhost

Disadvantage: This approach works in simple scenarios but if you have several environments like dev, testing, staging, pre-prod, prod, etc you will need to perform a build for each environment because the connection parameters are inside of your app.

环境变量

这是我最喜欢的,并且在 heroku、openshift、couldfoundry 等多个平台中也被推荐

在这种方法中,您只需要一个构建。此映像可以部署在任何环境中,只需在 运行.

之前使用正确的参数即可

节点示例 & mysql 使用环境变量:

const knex = require('knex')({
    client: 'mysql',
    connection: {
        host: process.env.database_host,
        user: process.env.database_user,
        password: process.env.database_password,
        database: process.env.database_database
    },
    debug: true
});

python & mongo 使用环境变量的示例:

import pymongo
import os

database_host = os.environ['database_host']
database_user = os.environ['database_user']
database_password = os.environ['database_password']

urlConnect = "mongodb://{}:{}@{}:27017/".format(database_user, database_password,database_host )

conn = pymongo.MongoClient(urlConnect)

如您所见,源代码不需要读取属性文件来获取连接参数,因为它希望它们可用 environment variables

最后,这种方法的步骤是:

  • 对您的应用执行 docker build ...
  • 对您的应用执行 docker run ...。在这种情况下,您需要将变量从主机发送到您的容器
docker run -it -p 8080:80 \
-e "database_host=10.10.10.10"  \
-e "database_user=root"  \
-e "database_password=pass"  \
--name my_app my_container:1.0

远程变量

如果您有分布式环境、可扩展等,您将需要管理您的变量。

基本上,您将有一个 Web 控制台来创建、编辑、删除和导出变量。此外,这些变量必须以简单的方式注入到您的 docker 容器中。

Heroku 如何为您提供管理变量的方法的示例

检查: