1

Firt of all: I don't want to connect to a docker container, running mongo.

I am building a docker container that should access the mongo database I have installed in my running Ubuntu 18.04 machine.

Docker suggests this could be done fairly easy by just adding the flag -pto the run command, so I did this:

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

Port 27017 is the default port for mongo (see here) and running netstat -pna | grep 27017 confirms by returning the following:

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

But running the docker command shown above, I get an error indicating that I can't connect to the port because it is already in use (which is actually the whole point of connecting to it):

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 

How should I proceed? What did I do wrong?

JRichardsz
  • 14,356
  • 6
  • 59
  • 94
Jere
  • 1,196
  • 1
  • 9
  • 31
  • 1
    The `-p` flag is for exposing a port in the container to the host. You're trying to do the opposite. You don't need to pass any particular flags to `docker run`; just point your application at an ip address of your host. – larsks Jul 17 '21 at 15:11

1 Answers1

1

This dependents on how your application connects to a database.

Almost all languages needs the connection parameters.

Example with nodes & mysql:

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

Example with python & mongo

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

Traditionally these connection parameters are stored in a properties or configuration file. One per environment: dev, staging, prod, etc

Configuration file

If your application use this method to get the connection parameters, you just need to follow these steps:

  • set the ip, port, user, password in the configuration file. Usually inside of your source code: application.properties, config.yml, parameters.ini, etc
  • perform a docker build ... of your app.
  • perform a docker run ... of your app. In this step, you don't need to pass any mongo parameter because there are already "inside" of your app. Check this and this to understand why localhost is not used in docker.

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.

Environment variables

This is my favorite and also is recommended in several platforms like heroku, openshift, couldfoundry, etc

In this approach you just need one build. This image could be deployed on any environment just playing with the correct parameters before the run.

Example with nodes & mysql using environment variables:

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
});

Example with python & mongo using environment variables:

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)

As you can see, the source code does not need to read a properties file to get the connection parameters because it hopes they are available as environment variables

Finally, the steps with this approach will be:

  • perform a docker build ... of your app.
  • perform a docker run ... of your app. In this case, you need to sent the variables from host to your container
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

Remote variables

If you have a distributed environment, scalable, etc you will want to manage your variables.

Basically you will have a web console to create, edit, delete and export your variables. Also these variables must be injected to your docker container in a easy way.

Example of how Heroku offer you a way to manage your variables

variables

Check:

JRichardsz
  • 14,356
  • 6
  • 59
  • 94
  • Thanks! But how should I proceed when my system is not connected to the outer world? Does Docker connect to the same local IP address as my machine? – Jere Jul 17 '21 at 16:25
  • Of course!! You just need to know the exact ip and port – JRichardsz Jul 17 '21 at 16:29