繁体   English   中英

无法在 Docker 中连接 NoSQLClient

[英]Cannot connect NoSQLClient in Docker

我在我的 Macbook 中运行 mongo 以及 mongoclient/mongoclient docker 服务。

➜  ~ docker ps 
CONTAINER ID        IMAGE                     COMMAND                  CREATED              STATUS              PORTS                      NAMES
40b69cb63c1d        mongoclient/mongoclient   "./entrypoint.sh nod…"   About a minute ago   Up About a minute   0.0.0.0:3000->3000/tcp     clever_golick
57ba76f4340f        mongo                     "docker-entrypoint.s…"   14 minutes ago       Up 14 minutes       0.0.0.0:27017->27017/tcp   cranky_villani

启动命令是:

docker run -p 3000:3000 -e MONGO_URL="mongodb://127.0.0.1:27017/pymongo_test" mongoclient/mongoclient

docker run -p 27017:27017 mongo

我访问 mongo 服务器并且可以在 Python 中使用 pymongo 添加一个集合

from pymongo import MongoClient   
mongo_client = MongoClient('mongodb://localhost:27017')
mongodb = mongo_client.pymongo_test
channel_table = mongodb.channel_table
data = {"col1":"something","col2":"something2"}
channel_table.insert_one(data)

我可以成功执行这个 python 没有任何 Mongo 连接问题。 我使用 Robo 3T ( https://robomongo.org/ ) 验证了数据已添加到 pymongotest DB 中。

但是当我在 localhost:3000 上运行 mongoclient 时,我看不到任何添加的数据。 mongo里面的一些细节图片

➜  ~ docker exec -it eb265221846d bash
root@eb265221846d:/# printenv
HOSTNAME=eb265221846d
GPG_KEYS=E162F504A20CDF15827F718D4B7C549A058F8B6B
PWD=/
HOME=/root
GOSU_VERSION=1.11
MONGO_VERSION=4.2.2
MONGO_REPO=repo.mongodb.org
TERM=xterm
MONGO_PACKAGE=mongodb-org
SHLVL=1
MONGO_MAJOR=4.2
JSYAML_VERSION=3.13.0
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
_=/usr/bin/printenv

内部mongoclient/mongoclient图片:

➜  ~ docker exec -it 6674c0109b7b bash 
node@6674c0109b7b:/opt/meteor/dist/bundle$ printenv
NODE_VERSION=8.4.0
HOSTNAME=6674c0109b7b
TERM=xterm
INSTALL_MONGO=true
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/opt/meteor/dist/bundle
MONGO_URL=mongodb://127.0.0.1:27017/pymongo_test
APP_BUNDLE_DIR=/opt/meteor/dist
BUILD_SCRIPTS_DIR=/opt/build_scripts
ROOT_URL=http://localhost
SHLVL=1
HOME=/home/node
MONGOCLIENT_DEFAULT_CONNECTION_URL=
APP_SOURCE_DIR=/opt/meteor/src
MONGOCLIENT_CONNECTIONS_FILE_PATH=/opt/meteor/dist/predefined_connections.json
GOSU_VERSION=1.10
PORT=3000
_=/usr/bin/printenv

当您在 mongo 客户端MONGO_URL="mongodb://127.0.0.1:27017/pymongo_test"它表示 mongo 客户端的本地主机,而不是 mongo 容器。

您需要 docker 网络,您可以使用传统linking运行,但最好使用 docker-compose 来处理所有这些事情。

你可以试试这个

version: '3.1'

services:

  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: example

docker 为 mongo 撰写

并且在您的 python 应用程序中似乎它在容器之外运行,因此您可以使用mongo_client = MongoClient('mongodb://localhost:27017')与 mongo 连接,但在容器 localhost 中表示此容器。

您也可以尝试使用 Moongose 客户端。

services:
    mongodb:
      image: mongo:latest
      container_name: mongodb
      hostname: mongodb
      ports:
        - 27017:27017
    mongoclient:
      image: mongoclient/mongoclient:latest
      container_name: mongoclient
      hostname: mongoclient
      depends_on:
        - mongodb
      ports:
        - 3300:3000

正如@Adiii 提到的,docker docker-compose在这些场景中确实可以提供帮助,因为它可以解决很多网络问题。 我将概述它在 vanilla docker 中的工作原理。

首先,本地主机。 容器是它们自己的小网络,这意味着它们有自己的外部接口(eth0),也有自己的本地主机。 因此,当您在容器中调用 localhost 时,它不是调用主机的 localhost,而是容器的localhost。 您需要能够在容器外部调用以找到另一个服务。

容器名称在这里变得非常有用。 容器是短暂的,不应被视为具有固定的 IP 地址,除非另有说明,否则它们的名称也是随机生成的。 当您执行 http 请求时,可以在路由表中查找名称:

# I'll just run a sample httpbin service as an example
docker run -d -p 80:80 kennethreitz/httpbin

docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                  PORTS                NAMES
a93a1ab833f6        kennethreitz/httpbin   "gunicorn -b 0.0.0.0…"   1 second ago        Up Less than a second   0.0.0.0:80->80/tcp   sleepy_brattain

一直向右滚动,您会看到容器被分配了名称sleepy_brattain 现在,如果我进入python

import requests

r = requests.get('http://sleepy_brattain')
r
<Response [200]>

我得到了 200。这意味着如果你修复了容器的名称,你就有了一个参考点来查找它们。 我将我的 httpbin 容器testbin

docker run -d --name testbin -p 80:80 kennethreitz/httpbin

docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                  PORTS                NAMES
ead322a3d53f        kennethreitz/httpbin   "gunicorn -b 0.0.0.0…"   1 second ago        Up Less than a second   0.0.0.0:80->80/tcp   testbin

请注意最后一列中的名称。 现在,如果我运行一个 python 容器,我可以针对该名称发出一个 http get 请求,它会起作用:

docker run -it python:3.6 /bin/bash

$ python -m pip install requests
$ python

>>> import requests
>>> r = requests.get('http://testbin')
>>> r
<Response [200]>

但是,要使您的 mongo 示例正常工作,您还需要最后一件,那就是network 创建网络很容易:

docker network create mongo

然后,为了让容器能够看到彼此,您将它们分配到该网络。 对于mongo

docker run -d --network mongo -p 27017:27017 --name mymongo mongo

docker run -it --network mongo python:3.6
$ python -m pip install pymongo
$ python
>>> from pymongo import MongoClient
>>> client = MongoClient('mongodb://mymongo:27017')

我会知道发生了连接,因为检查日志:

docker logs $(docker ps -aq --filter "ancestor=mongo") | tail -n 3
2019-12-21T05:32:08.002+0000 I  SHARDING [ftdc] Marking collection local.oplog.rs as collection version: <unsharded>
2019-12-21T05:32:50.773+0000 I  NETWORK  [listener] connection accepted from 172.18.0.3:34346 #1 (1 connection now open)
2019-12-21T05:32:50.773+0000 I  NETWORK  [conn1] received client metadata from 172.18.0.3:34346 conn1: { driver: { name: "PyMongo", version: "3.10.0" }, os: { type: "Linux", name: "Linux", architecture: "x86_64", version: "4.9.184-linuxkit" }, platform: "CPython 3.6.8.final.0" }

我看到来自我的 python 容器的连接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM