CODE FARM
Galaxy background

"The future belongs to those who believe in the beauty of their dreams."

- Eleanor Roosevelt

Deploy MongoDB with Docker


0. Prerequisites

Make sure you have already installed both Docker Engine and Docker Compose. You don’t need to install MongoDB, as it’s provided by Docker image.

1. Start a MongoDB Instance.

$ docker run -d -p 27017:27017 --name db mongo:3

2. Start a MongoDB Instance with Access Control.

$ docker run -d -p 27017:27017 --name db mongo:3 --auth

Connect a mongo shell to one of the config server mongod instances over the localhost interface and create the user administrator.

$ docker exec -it db mongo admin --quiet
> db.createUser({
... user:"admin",
... pwd:"admin",
... roles: [
... {role: "userAdmin", db:"admin"}
... ]
... })
Successfully added user: {
        "user" : "admin",
        "roles" : [
                {
                        "role" : "userAdmin",
                        "db" : "admin"
                }
        ]
}
> db.auth("admin","admin")
1
> db.createUser({
... user: "user1",
... pwd: "user1",
... roles: [
... {
... role: "readWriteAnyDatabase",
... db: "admin"
... }
... ]
... })
Successfully added user: {
        "user" : "user1",
        "roles" : [
                {
                        "role" : "readWriteAnyDatabase",
                        "db" : "admin"
                }
        ]
}
> use test
switched to db test
> db.test.insertOne({ x: 1 })
2017-09-08T08:50:53.276+0000 E QUERY    [thread1] TypeError: err.hasWriteErrors ...
DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:244:13
@(shell):1:1
> db.auth("user1","user1")
Error: Authentication failed.
0
> use admin
switched to db admin
> db.auth("user1","user1")
1
> use test
switched to db test
> db.test.insertOne({ x: 1 })
{
        "acknowledged" : true,
        "insertedId" : ObjectId("59b25a108bcdfe4e19c35a13")
}
>

3. Deploy a Replica Set

$ mkdir mogors
$ cd mogors/
$ cat <<EOF > docker-compose.yml
> ---
> version: "3.2"
> services:
>     db-0:
>         container_name: db-0
>         image: mongo:3
>         # Start each member of the replica set with the appropriate options .
>         command:
>             - mongod
>             - "--replSet"
>             - "rs0"
>     db-1:
>         container_name: db-1
>         image: mongo:3
>         command:
>             - mongod
>             - "--replSet"
>             - "rs0"
>     db-2:
>         container_name: db-2
>         image: mongo:3
>         command:
>             - mongod
>             - "--replSet"
>             - "rs0"
> EOF
$ docker-compose up -d
Creating network "mongors_default" with the default driver
Creating db-2 ...
Creating db-0 ...
Creating db-1 ...
Creating db-2
Creating db-1
Creating db-0 ... done
$ docker ps -a
CONTAINER ID        IMAGE               STATUS              PORTS               NAMES
0f6a34b826b2        mongo:3             Up 45 seconds       27017/tcp           db-1
c4c04bfc53f3        mongo:3             Up 46 seconds       27017/tcp           db-0
9d8bc021082c        mongo:3             Up 46 seconds       27017/tcp           db-2
$ docker exec -it db-0 mongo --quiet
> rs.initiate( {
...    _id : "rs0",
...    members: [ { _id : 0, host : "db-0" } ]
... })
{ "ok" : 1 }
rs0:PRIMARY> rs.add("db-1")
{ "ok" : 1 }
rs0:PRIMARY> rs.add("db-2")
{ "ok" : 1 }
rs0:PRIMARY> db.runCommand("isMaster")
{
        "hosts" : [
                "db-0:27017",
                "db-1:27017",
                "db-2:27017"
        ],
        "setName" : "rs0",
        "setVersion" : 3,
        "ismaster" : true,
        "secondary" : false,
        "primary" : "db-0:27017",
        "me" : "db-0:27017",
        "electionId" : ObjectId("7fffffff0000000000000001"),
        "lastWrite" : {
                "opTime" : {
                        "ts" : Timestamp(1504859331, 1),
                        "t" : NumberLong(1)
                },
                "lastWriteDate" : ISODate("2017-09-08T08:28:51Z")
        },
        "maxBsonObjectSize" : 16777216,
        "maxMessageSizeBytes" : 48000000,
        "maxWriteBatchSize" : 1000,
        "localTime" : ISODate("2017-09-08T08:28:56.329Z"),
        "maxWireVersion" : 5,
        "minWireVersion" : 0,
        "readOnly" : false,
        "ok" : 1
}
rs0:PRIMARY>

4. Deploy a Replica Set with Access Control.

$ mkdir mogors
$ cd mogors/
$ # Create a keyfile.
$ openssl rand -base64 756 > keyfile
$ cat keyfile
AFO3EYmmmQQLF68tUd3aQsFI/C53XtOpUGt8R5ecS1F9uWRFg4dN6jlCjiBbYqHC
w3lqUhlRBe00YhDM97z31oYkQBSyID20pIMeQ3e40FY6zBE1w+4lWYekuPJAUtzS
ZspGfFExltwL0700Dwu7b1mnMbqfmfrpSVxTKHaY7Hcw60mvbBPPCp6IWkDVZ9NX
NKveHX3Wuq28/PSMw8sVPUbP5eqPux05PCyp5VBp6/fhg8Np8vIlWAy9fMsAgkmE
kBeGcRNst6t0iXbqNi9VrW6szJN5yyq0x1+0XB1QJZCjnLczoXMTPQeDCTrijbpI
N4zr7L2EV6n8FsgSJ7vwzRMj0ZRFjuK/wwBblPCuisv5JlcClZ6I0WEtV1yg5HQu
AFv3v7FPmfodQ6Sz81c6sNEKuwg3kzCY7wkeA163RZrujHViYFka6zOcv/kDdQ5h
rL6EBXE3v6bnd24/nzys9Zx6CrqPPUqSVfugmIW78r9imXswUqdr/VZVbhGsKcjH
Uza306prvuWmh0o1hpFGReGbHIdWhEtP/ldXKBbPy+27tgNeSiSP1GjVG2rkaIlb
bsnahiNj2EaAa1ov9pYiyO51m+ouEg+H9LPBcLhLXipI3wbST8BqMZweLSNfeLFi
Kpel5Q3rNtmRrjCbVIiiAXmxECU+PcwL+a4XhISnktdq6Du43d4INSJ/cn8JVLFS
VbR5nTnc4cMmEE3n/0BrScZinGZT1gbtwbE5izA5E17/7n/HLGUXhfhMGWrwdL9f
CsDt8ZEg7AUCPhFhsbcwfHkROXmYYubcd41NqLEYyktDzqsu3CaXFvH3QyD5AqmN
ylh6UGgjqgWIC7y553qNE9v7Go/9zKTUj8Df/wcQVl6ALOdZgPmchNTX8PtENdKT
aPUu/dcctYZUxz1DKwkaH3aUblSBGtSHa94knUA+R3DWPTcGNt3n46AL45Ty5amX
c5yYTpaKB6jgXwIMjO96OA9XlZKxOVgqdASsN6O0wCzfAg55
$ chmod 400 keyfile
$ sudo chown 999 keyfile
$ cat docker-compose.yml
---
version: "3.2"
services:
    db-0:
        container_name: db-0
        image: mongo:3
        # Start each member of the replica set with the appropriate options .
        command:
            - mongod
            - "--replSet"
            - "rs0"
            - "--auth"
            - "--keyFile"
            - "/opt/mongors/keyfile"
        volumes:
            - type: bind
              source: ./keyfile
              target: /opt/mongors/keyfile
              read_only: true
    db-1:
        container_name: db-1
        image: mongo:3
        command:
            - mongod
            - "--replSet"
            - "rs0"
            - "--auth"
            - "--keyFile"
            - "/opt/mongors/keyfile"
        volumes:
            - type: bind
              source: ./keyfile
              target: /opt/mongors/keyfile
    db-2:
        container_name: db-2
        image: mongo:3
        command:
            - mongod
            - "--replSet"
            - "rs0"
            - "--auth"
            - "--keyFile"
            - "/opt/mongors/keyfile"
        volumes:
            - type: bind
              source: ./keyfile
              target: /opt/mongors/keyfile
$ docker-compose up -d
Creating network "mongors_default" with the default driver
Creating db-1 ...
Creating db-0 ...
Creating db-1
Creating db-0
Creating db-2 ...
Creating db-2 ... done
$ docker ps -a
CONTAINER ID        IMAGE               STATUS              PORTS               NAMES
02143821d0d7        mongo:3             Up 3 seconds        27017/tcp           db-2
338aef4ef282        mongo:3             Up 3 seconds        27017/tcp           db-0
ff459a50af25        mongo:3             Up 3 seconds        27017/tcp           db-1
$ docker exec -it db-0 mongo --quiet
> rs.initiate( {
...    _id : "rs0",
...    members: [ { _id : 0, host : "db-0" } ]
... })
{ "ok" : 1 }
rs0:SECONDARY> use admin
switched to db admin
rs0:PRIMARY> db.createUser({
... user:"admin",
... pwd:"admin",
... roles: [
... {role: "userAdmin", db:"admin"},
... {role: "clusterAdmin", db: "admin"}
... ]
... })
Successfully added user: {
        "user" : "admin",
        "roles" : [
                {
                        "role" : "userAdmin",
                        "db" : "admin"
                },
                {
                        "role" : "clusterAdmin",
                        "db" : "admin"
                }
        ]
}
rs0:PRIMARY> rs.add('db-1')
2017-09-08T09:44:33.194+0000 E QUERY    [thread1] Error: count failed: {
        "ok" : 0,
        "errmsg" : "not authorized on local to execute command ...
        "code" : 13,
        "codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DBQuery.prototype.count@src/mongo/shell/query.js:383:11
DBCollection.prototype.count@src/mongo/shell/collection.js:1700:12
rs.add@src/mongo/shell/utils.js:1227:1
@(shell):1:1
rs0:PRIMARY> db.auth('admin','admin')
1
rs0:PRIMARY> rs.add('db-1')
{ "ok" : 1 }
rs0:PRIMARY> rs.add('db-2')
{ "ok" : 1 }
rs0:PRIMARY> db.runCommand("isMaster")
{
        "hosts" : [
                "db-0:27017",
                "db-1:27017",
                "db-2:27017"
        ],
        "setName" : "rs0",
        "setVersion" : 3,
        "ismaster" : true,
        "secondary" : false,
        "primary" : "db-0:27017",
        "me" : "db-0:27017",
        "electionId" : ObjectId("7fffffff0000000000000001"),
        "lastWrite" : {
                "opTime" : {
                        "ts" : Timestamp(1504863894, 1),
                        "t" : NumberLong(1)
                },
                "lastWriteDate" : ISODate("2017-09-08T09:44:54Z")
        },
        "maxBsonObjectSize" : 16777216,
        "maxMessageSizeBytes" : 48000000,
        "maxWriteBatchSize" : 1000,
        "localTime" : ISODate("2017-09-08T09:45:04.775Z"),
        "maxWireVersion" : 5,
        "minWireVersion" : 0,
        "readOnly" : false,
        "ok" : 1
}
rs0:PRIMARY>

References:

  1. mongo | Docker Documentation
  2. Enable Auth — MongoDB Tutorials
  3. Manage Users and Roles — MongoDB Tutorials
  4. Built-In Roles — MongoDB Manual 3.4
  5. Deploy a Replica Set — MongoDB Manual 3.4
  6. Enforce Keyfile Access Control in a Replica Set — MongoDB Manual 3.4
  7. Compose file version 3 reference | Docker Documentation
  8. Deploy a MongoDB Cluster in 9 steps Using Docker
  9. Mongodb KeyFile too open permissions - Stack Overflow