docker-compose to run django with mongodb

2020-06-09 07:59发布

问题:

I am facing problem using docker-compose to link a django container with postgres and mongo containers? I am trying to use "docker-compose up" which starts up the mongo and postgres containers (as I need to link both) but still the django app is not able to connect to mongodb on default settings. My django-compose.yml file contents are copied below:

    db1:
      image: postgres
    db2:
      image: mongo
      ports:
        - "27017:27017"
    web:
      build: .
      command: python manage.py runserver 0.0.0.0:8000
      volumes:
        - .:/code
      ports:
        - "8000:8000"
      links:
        - db1
        - db2

It does connect with postgres with default settings. I can also telnet to the mongodb port locally. Still, I get this error on starting the web container:

File "/usr/local/lib/python2.7/site-packages/mongoengine/connection.py", line 124, in get_connection web_1 | raise ConnectionError("Cannot connect to database %s :\n%s" % (alias, e)) web_1 | mongoengine.connection.ConnectionError: Cannot connect to database default : web_1 | [Errno 111] Connection refused

PS: I had successfully started a django-postgres connected app on my localhost, but it failed connecting to db, on an AWS instance. That is another problem I still need to get to root of.

回答1:

I ran into a similar problem but with another service (not MongoDB). I'm not sure of what I'm doing wrong but this is how I could solve it :

import os
import mongoengine

MONGODB_HOST = os.environ.get('DB2_PORT_27017_TCP_ADDR', '127.0.0.1')
mongoengine.connect(host=MONGODB_HOST)
  • With DB2 being the name of your service in docker-compose.yml
  • 27017 being the port of the exposed service.
  • More about docker-compose environment variables
  • I'd put that in my settings file. But you are free to put it wherever you think it's appropriate depending on your project architecture

UPDATE

Now docker-compose containers are reachable by other services using a hostname similar to their alias. link documentation :

Containers for the linked service will be reachable at a hostname identical to the alias, or the service name if no alias was specified.

And that way you can connect to MongoDB like this:

import mongoengine

mongoengine.connect(host="db2")


回答2:

You should specify host name like in the docker compose file, instead of IP address.

I've faced similar problems in connecting from a Tornado Web app to Mongo DB. Here is my docker-compose.yml:

web:
  build: .
  ports:
   - "8888:8888"
  volumes:
   - .:/code
  links:
   - db
db:
  image: mongo:3.0

Here is my connection string:

motorengine.connect("db", host='db', port=27017, io_loop=io_loop)

My error was to specify IP address instead of host name (db) like in the docker compose file.



回答3:

The problem you face is that the application container and the DB container start independently from each other and most importantly, the app container won't wait until the DB container is started. There is as of docker compose 1.1.0 no feature which would allow to consider such dependencies.

This is a well known problem and has been discussed already. Consensus seems to be that this should not be solved on a docker compose level but in docker itself. There is a proposal already for the groundwork in docker.

In my case, I just built this kind of intelligence in the application itself. I check for port connectivity until successful and then start the rest of the application.



回答4:

I was able to containerize Django and MongoDB, connect both containers. I used Dockerfiles to build both containers and docker run to start the containers and have them connected. Just follow the steps in this repo. It was necessary for me to use Dockerfiles to have more power over the installed versions of the needed libraries because the latest versions of Django and mongoengine are not compatible. The stable working versions are

Django==1.10.0
pymongo==2.7.1
six==1.10.0
mongoengine==0.9.0