dev.to Open in urlscan Pro
151.101.66.217  Public Scan

URL: https://dev.to/ndaidong/how-to-make-your-mongodb-container-more-secure-1646
Submission: On January 22 via api from IN — Scanned from DE

Form analysis 3 forms found in the DOM

GET /search

<form method="get" action="/search" role="search" accept-charset="UTF-8"><input name="utf8" type="hidden" value="✓">
  <div class="crayons-fields crayons-fields--horizontal">
    <div class="crayons-field flex-1 relative"><input class="crayons-header--search-input crayons-textfield" type="text" id="" name="q" placeholder="Search..." autocomplete="off" aria-label="Search term"><button type="submit" aria-label="Search"
        class="c-btn c-btn--icon-alone absolute inset-px left-auto mt-0 py-0"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" class="crayons-icon c-btn__icon" focusable="false">
          <path
            d="m18.031 16.617 4.283 4.282-1.415 1.415-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9 9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617zm-2.006-.742A6.977 6.977 0 0 0 18 11c0-3.868-3.133-7-7-7-3.868 0-7 3.132-7 7 0 3.867 3.132 7 7 7a6.977 6.977 0 0 0 4.875-1.975l.15-.15z">
          </path>
        </svg></button></div>
  </div>
</form>

POST /comments

<form class="comment-form print-hidden" id="new_comment" action="/comments" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" autocomplete="off">
  <input type="hidden" name="authenticity_token" value="NOTHING" id="new_comment_authenticity_token">
  <input value="454805" autocomplete="off" type="hidden" name="comment[commentable_id]" id="comment_commentable_id">
  <input value="Article" autocomplete="off" type="hidden" name="comment[commentable_type]" id="comment_commentable_type">
  <span class="crayons-avatar m:crayons-avatar--l mr-2 shrink-0">
    <img src="https://media.dev.to/cdn-cgi/image/width=256,height=,fit=scale-down,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j7kvp660rqzt99zui8e.png" width="32" height="32" alt="pic"
      class="crayons-avatar__image overflow-hidden" id="comment-primary-user-profile--avatar" loading="lazy">
  </span>
  <div class="comment-form__inner">
    <div class="comment-form__field" data-tracking-name="comment_form_textfield">
      <textarea placeholder="Add to the discussion" onfocus="handleFocus(event)" onkeyup="handleKeyUp(event)" onkeydown="handleKeyDown(event)" oninput="handleChange(event)" id="text-area" required="required"
        class="crayons-textfield comment-textarea crayons-textfield--ghost" aria-label="Add a comment to the discussion" name="comment[body_markdown]"></textarea>
    </div>
    <div class="response-templates-container crayons-card crayons-card--secondary p-4 mb-4 comment-form__templates fs-base hidden">
      <header class="mb-3">
        <button type="button" class="crayons-btn personal-template-button active" data-target-type="personal" data-form-id="new_comment">Personal</button>
        <button type="button" class="crayons-btn moderator-template-button hidden" data-target-type="moderator" data-form-id="new_comment">Trusted User</button>
      </header>
      <div class="personal-responses-container">
      </div>
      <div class="moderator-responses-container hidden">
      </div>
      <a target="_blank" rel="noopener nofollow" href="/settings/response-templates">
        Create template
      </a>
      <p>Templates let you quickly answer FAQs or store snippets for re-use.</p>
    </div>
    <div class="comment-form__preview text-styles text-styles--secondary" id="preview-div"></div>
    <div class="comment-form__buttons mb-4">
      <button type="submit" class="crayons-btn mr-2 js-btn-enable" onclick="validateField(event)" data-tracking-name="comment_submit_button" disabled="">Submit</button>
      <button type="button" class="preview-toggle crayons-btn crayons-btn--secondary comment-action-preview js-btn-enable mr-2" data-tracking-name="comment_preview_button" disabled="">Preview</button>
      <a href="/404.html" class="dismiss-edit-comment crayons-btn crayons-btn--ghost js-btn-dismiss hidden">Dismiss</a>
    </div>
  </div>
  <div class="code-of-conduct" id="toggle-code-of-conduct-checkbox"></div>
</form>

POST /comments/hide

<form id="hide-comments-modal__form" class="hide-comments-modal__form" data-type="json" action="/comments/hide" accept-charset="UTF-8" data-remote="true" method="post"><input name="utf8" type="hidden" value="✓" autocomplete="off"><input type="hidden"
    name="_method" value="patch" autocomplete="off"><input type="hidden" name="authenticity_token" value="xyj899Q6h1IIs8uBmHZYSHePBRNMaN1o3d8oPvEA_xG1rIjigDEq-VHI6EoZ4Bz_s_oEohUbvsvzc79jDpTWTw" autocomplete="off">
  <div class="hide-comments-modal__content">
    <p class="pb-2"> Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's <a id="hide-comments-modal__comment-permalink" href="#">permalink</a>. </p>
    <label class="crayons-field crayons-field--checkbox my-2">
      <input name="hide_children" type="hidden" value="0" autocomplete="off"><input class="hide_children crayons-checkbox" type="checkbox" value="1" name="hide_children" id="hide_children">
      <p class="crayons-field__label">Hide child comments as well</p>
    </label>
    <p class="pb-4 pt-2">
      <button type="submit" class="crayons-btn"> Confirm </button>
    </p>
  </div>
</form>

Text Content

Skip to content
Navigation menu

Search
Log in Create account


DEV COMMUNITY

Close




22 Add reaction
18 Like 4 Unicorn 0 Exploding Head 0 Raised Hands 0 Fire
1 Jump to Comments 39 Save

More...
Copy link Copy link
Copied to Clipboard
Share to Twitter Share to LinkedIn Share to Reddit Share to Hacker News Share to
Facebook Share to Mastodon
Share Post via... Report Abuse
Dong Nguyen

Posted on Sep 13, 2020

18 4      


HOW TO MAKE YOUR MONGODB CONTAINER MORE SECURE?

#mongodb #docker #security


START IT WITH DOCKER

The most simple way to get MongoDB instance in your machine is using docker to
run mongodb image on docker hub as below:


docker run --name mongodb -p 27017:27017 mongo


Enter fullscreen mode Exit fullscreen mode

By specifying -p 27017:27017, you can access to it with the connection string
such as mongodb://localhost:27017 or mongodb://0.0.0.0:27017, as same as
installed MongoDB server.

This database instance is only available locally. In the case you want to access
to it from another computer, you have to overwrite the default config file with
a custom MongoDB configuration file.


ALLOW TO CONNECT FROM OUTSIDE

The command looks like below:


docker run --name mongodb -p 27017:27017 -v /path/to/custom/mongod.conf:/etc/mongod.conf mongo


Enter fullscreen mode Exit fullscreen mode

In which, the mongod.conf file has been customized to allow to connect from
outside:


# mongod.conf

# other settings

# network interfaces
net:
  port: 27017
  # bindIp: 127.0.0.1  # this is default setting
  bindIp: 0.0.0.0  # this is what changed

# other settings


Enter fullscreen mode Exit fullscreen mode

But since now your database is public and no longer secure.

In my experience, the first thing we should do in this situation is change the
default port.


CHANGE DEFAULT PORT

Let's map it to another free port:


docker run --name mongodb -p 27117:27017 -v /path/to/custom/mongod.conf:/etc/mongod.conf mongo


Enter fullscreen mode Exit fullscreen mode

So that the connection string will become mongodb://IP_ADDRESS:27117, not
default port.

As you know, there are many bots those automatically scan for public databases
on the internet. They try to check the popular default ports, such as 3306
(mysql), 5432 (posgres), 6379 (redis), 27017 (mongo), etc. Changing to a strange
port may help you in almost cases.

However, that's not enough.


ENABLE AUTHENTICATION

By default MongoDB will start with authentication disabled. We should enable it
with a little bit change to entrypoint. In order to make things easier
management, we create a docker-compose.yaml file as below:


version: "3"

services:
  mongodb:
    image: mongo
    container_name: mongodb
    ports:
      - 27117:27017
    volumes:
      - ./mongod.conf:/etc/mongod.conf
    entrypoint: ["mongod", "--auth", "--config", "/etc/mongod.conf"]


Enter fullscreen mode Exit fullscreen mode

In the above .yaml file, we added our custom entrypoint to run mongodb with
--auth flag. Now when we run it with docker-compose, we should get MongoDB
within a container named mongodb similar to the docker run command earlier.



And the following is the most important parts of this article...


CREATE USERS WITH SPECIFIC PERMISSIONS

Until now, our MongoDB instance does not have any user yet. We will get into its
container and create a few ones.

Firstly, let's get the interactive mongo shell by running:


docker exec -it mongodb mongo


Enter fullscreen mode Exit fullscreen mode

With opening mongo shell, we can now run the commands to switch to admin
database and create a user named boss with admin permission on any database:


use admin
db.createUser({
  user: 'boss',
  pwd: 'YourVeryComplexPassword',
  roles:['userAdminAnyDatabase']
})


Enter fullscreen mode Exit fullscreen mode

Done, press Ctrl + C to exit the shell and leave that session.



Note that, at this time, we had already a MongoDB instance run with
authentication mode enabled, and an admin user. The connection string for boss
user now looks like:

mongodb://boss:YourVeryComplexPassword@IP_ADDR:27117

But that's power user, don't use it for regular applications. Instead, we should
create more users for different purposes.

To create more user or database, we have to come back to mongo shell as boss
user:


docker exec -it mongodb mongo -u boss


Enter fullscreen mode Exit fullscreen mode

Enter password when asked and you should see something like:



Assume that we have a plan to use a database blogs to store our great blog
posts. We should add a user named writer which can write to this database, and a
user named reader which can read only.

Do that as below:


# go to database `admin`
use admin

# add writer
db.createUser({
  user: 'writer',
  pwd: 'YourComplexPassword',
  roles:[
    { 
      role: 'readWrite',
      db: 'blogs'
    }
  ]
})

# add reader
db.createUser({
  user: 'reader',
  pwd: 'YourSimplePassword',
  roles:[
    { 
      role: 'read',
      db: 'blogs'
    }
  ]
})


Enter fullscreen mode Exit fullscreen mode

Done, press Ctrl + C to exit the shell and leave that session again.



Now we have 2 new users, one for read/write and other for read only action.
Their connection strings are:

mongodb://writer:YourComplexPassword@IP_ADDR:27117
mongodb://reader:YourSimplePassword@IP_ADDR:27117

With the apps or API endpoints those only load and show blog posts, we just need
to use the connection string for reader. Otherwise, when we need to add more
blog posts, we will connect to database as writer.

That's it. Enjoy playing with docker and MongoDB :)


TOP COMMENTS (1)

Subscribe
Personal Trusted User


Create template

Templates let you quickly answer FAQs or store snippets for re-use.


Submit Preview Dismiss

Collapse Expand
 
Mohamed
Mohamed
Mohamed
Follow
Learning & growing that's what I am all about!
 * Location
   Netherlands
 * Work
   Software Engineer
 * Joined
   Nov 3, 2020

• Nov 3 '20
Dropdown menu
 * Copy link
 * 
 * Hide
 * 
 * Report abuse
 * 

Thank you for your blog! I appreciate the effort :)

Like comment: Like comment: 1 like Like Comment button Reply
Code of Conduct • Report abuse

Are you sure you want to hide this comment? It will become hidden in your post,
but will still be visible via the comment's permalink.

Hide child comments as well

Confirm

For further actions, you may consider blocking this person and/or reporting
abuse




READ NEXT


CRAFTING A DOCKER IMAGE FOR YOUR FLASK WEB APP

tinega - Jan 12


TERRAPIN SSH ATTACK: AN OVERVIEW

Sandipan Roy - Jan 12


BUILD DOCKER IMAGES FASTER USING BUILD CACHE

Kyle Galbraith - Jan 7


MINDSDB DOCKER EXTENSION: BUILD ML POWERED APPS AT A MUCH FASTER PACE

Ajeet Singh Raina - Jan 1

Dong Nguyen
Follow
A software engineer who is also interested in finance, crypto and stock market.
 * Location
   Vietnam
 * Joined
   Mar 8, 2018


TRENDING ON DEV COMMUNITY HOT

Coding Bootcamps: Elevate Your Career or Stall Your Ambitions?
#discuss #career #beginners
What was your win this week?
#discuss #weeklyretro
3 Tools increasing your productivity 📈🤯
#programming #productivity #career #webdev
DEV Community
Dropdown menu
 * What's a billboard?
 * Manage preferences

   --------------------------------------------------------------------------------

 * Report billboard


DID YOU KNOW?

You can use this area right here to promote your company's:

🧠 Products and tools
🎪 Events
🍎 Job listings
🎉 And more

We run simple, no-tracking, privacy-focused ads that convert because they are
contextual and community-focused.

Learn More




Once suspended, ndaidong will not be able to comment or publish posts until
their suspension is removed.

Note:



Submit & Suspend

Once unsuspended, ndaidong will be able to comment and publish posts again.

Note:



Submit & Unsuspend

Once unpublished, all posts by ndaidong will become hidden and only accessible
to themselves.

If ndaidong is not suspended, they can still re-publish their posts from their
dashboard.

Note:

Unpublish all posts

Once unpublished, this post will become invisible to the public and only
accessible to Dong Nguyen.

They can still re-publish the post if they are not suspended.

Unpublish Post

Thanks for keeping DEV Community safe. Here is what you can do to flag ndaidong:

Make all posts by ndaidong less visible

ndaidong consistently posts content that violates DEV Community's code of
conduct because it is harassing, offensive or spammy.

Report other inappropriate conduct



Confirm Flag

Unflagging ndaidong will restore default visibility to their posts.

Confirm Unflag


DEV Community — A constructive and inclusive social network for software
developers. With you every step of your journey.

 * Home
 * Podcasts
 * Videos
 * Tags
 * FAQ
 * Forem Shop
 * Advertise on DEV
 * About
 * Contact
 * Guides
 * Software comparisons

 * Code of Conduct
 * Privacy Policy
 * Terms of use

Built on Forem — the open source software that powers DEV and other inclusive
communities.

Made with love and Ruby on Rails. DEV Community © 2016 - 2024.



We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

Some content on our site requires cookies for personalization.

Read our full privacy policy to learn more.

Dismiss Accept Cookies