Sunday, January 29, 2017

Connection refused when running mongo DB command in docker

Leave a Comment

I'm new to docker and mongoDB, so I expect I'm missing some steps. Here's what I have in my Dockerfile so far:

FROM python:2.7  RUN apt-get update \     && apt-get install -y mongodb \     && rm -rf /var/lib/apt/lists/*  RUN mkdir -p /data/db  RUN service mongodb start  RUN mongod --fork --logpath /var/log/mongodb.log  RUN mongo db --eval 'db.createUser({user:"dbuser",pwd:"dbpass",roles:["readWrite","dbAdmin"]})' 

The connection fails on the last command:

Error: couldn't connect to server 127.0.0.1:27017 at src/mongo/shell/mongo.js:145 exception: connect failed`.

How can I connect successfully? Should I change the host/IP, and to what, in which commands?

2 Answers

Answers 1

Several things going wrong here. First are the commands you're running:

RUN service mongodb start  RUN mongod --fork --logpath /var/log/mongodb.log 

Each of these will run to create a layer in docker. And once the command being run returns, the temporary container that was started is stopped and any files changed in the container are captured to make a new layer. There are no persistent processes that last between these commands.

These commands are also running the background version of the startup commands. In docker, you'll find this to be problematic since when you use this as your container's command, you'll find the container dies as soon as the command finishes. Pid 1 on the container has the same role of pid 1 on a linux OS, once it dies, so does everything else.

The second issue I'm seeing is mixing data with your container in the form of initializing the database with the last RUN command. This fails since there's no database running (see above). I'd recommend instead to make an entrypoint that configures the database if one does not already exist, and then use a volume in your docker-compose.yml or on your docker run commandline to persist data between containers.

If you absolutely must initialize the data as part of your image, then you can try merging the various commands into a single run:

RUN mongod --fork --logpath /var/log/mongodb.log \  && mongo db --eval 'db.createUser({user:"dbuser",pwd:"dbpass",roles:["readWrite","dbAdmin"]})' 

Answers 2

I think you misunderstood what Dockerfiles are used for. As Dockerfile reference points out, a

Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image.

The whole concept of an image is to derive running container from it which are then filled with data and queried (in case of a database) or are beeing called by an external container / host (in case of an web service) or many other possible usages.

To answer your question I'll assume that:

  1. You want to use a mongo database to store data.

  2. You have some pyhton code which needs to have access to mongo.

  3. You want some initial data in your database.

To do so:

  1. Run a mongo database

    docker run --name my-mongo -d mongo

    Note: There is no need to write a custom image. Use the official mongo image!

  2. Create a python image which contains your script

    a) Write your Dockerfile

    FROM python:3-alpine  ADD my_script.py /  RUN pip install any-dependency-you-might-need  CMD [ "python", "./my_script.py" ] 

    b) Write your my_script.py

Insert your application stuff here. It will be executed in the python container. And as mongo will be linked, you can use s.th. like client = MongoClient('mongodb://mongo:27017/') to get started.

  1. Run your python container with a link to mongo

    a) Build it:

    docker build -t my-pyhthon-magic . 

    b) Run it:

    docker run -d --name python-magic-container --link my-mongo:mongo my-python-magic 

    Note: The --link here links a running container named my-mongo to be reached internally in my-python-magic-container as mongo. That`s why you can use it in your python script.

I hope this helped you - don't hesitate to ask or modify your question if I misunderstood you.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment