Docker: Implement MongoDB with a React App

Looking for a great (remote only) React Dev? Or just feel like having a chat? Visit my profile on LinkedIn and say hi! 😃

In the previous article, we explored how to get started with Docker, but the app we built was incredibly simple. All it did was respond with a string to a HTTP request to the main URL.

What if we wanted to do something a little more complex? How about a React app that stores its state in MongoDB?

App Explanation

You can see the code for the app here:

https://github.com/bengrunfeld/docker-nextjs-mongo

So this is a really simple CRUD app. It only takes numbers as an input, but you can create a new record, update or delete an existing one, and of course, read all the existing records.

To execute an Create or Update action, just click out of the box.

Here’s the final result:

Tech Stack

Instead of coding everything from the ground up with Webpack and Express, I decided to use Next.JS, since everything’s already done for you and you don’t need to worry about that crap.

For the API layer, I’ve used GraphQL and Apollo, because industry is moving in that direction, and I felt like getting a bit more practice with it.

In this article, we won’t be focussing too much on the app code, but rather the bigger pieces — i.e. Docker and Mongo.

The Biggest Problem I Encountered

docker-compose has no --watch flag!!

OMG…!! WHY?!?!

Basically, you have to do this super hacky workaround where you store your app in a Docker volume… and I had no intention of doing that here. Let’s keep it simple to begin with.

Instead, I had to repeatedly delete and re-install Docker images, which was a time-wasting pain in the ass. Eventually, I got sick of doing that and asked for help on StackOverflow, and this got the following answer.

docker-compose up -d --build

Well, at least that saved me a few commands.

Of course, absolutely no mention of this in the Docker docs… 💩💩💩

Implementation

Ok, let’s get to the good stuff. You’re not here to listen to me complain about navigating local Docker usage.

Dockerfile

Here is my Dockerfile:

In the above file, we install NodeJS, set a working directory, and copy over the package.json. Then we get to the important part!

If you’re working locally with MongoDB, the url you’ll use will likely be mongodb://localhost:27017. NOT SO if you’re working with Docker. Instead, you have to use mongodb://mongo:27017.

I’m almost embarrassed to admit exactly how long it took me to figure this one out. The localhost url won’t work, and your code that tries to access Mongo will error out, so essentially, this little pearl of hard-won wisdom will likely be your biggest takeaway from this article.

After that, I declare some environment variables so that I can access them easily throughout the app, and the rest of the file I’m sure you can figure out.

Docker-Compose.yml

Here is my docker-compose.yml. There’s nothing too flashy in there.

Most notable is that by using the depends_on command, we ensure that the mongo container spins up first, so that when the web app starts, the mongo container is already there and ready to be used.

Access MongDB From Your App

NextJS has an awesome feature called API Routes that lets you accept HTTP requests, and in turn make your own requests on the server side. This is way easier and more “correct” that making request on the client side using something like the SWR hook.

One of my apps API Routes imports the following file and then calls the openDbConnection function. An object containing the MongoDB client is returned, and you can use that to execute queries against the database.

Here’s the code that calls it:

const { client, db } = await createDbConnection();const allRecords = await readAllRecords(db);
client.close();
return allRecords;

Now, you can take db and use it to make a query against MongoDB like so:

Notice that I’m using Promises to make my life easier. The function that calls readAllRecords is an async/await.

And that’s really about it.

Conclusion

Using Docker for local development (without the hack of live-reloading using volumes) is a total bitch! It’s tedious, clunky, and infuriatingly slow. Every time you make a change to your app, you have to wait for a long build process to complete, which is entirely not workable if you’re on a slow internet connection.

There are positives though. In return you get an isolated and version controlled installation of NodeJS and MongoDB, meaning you don’t have to worry that something else running on your computer will pollute the database.

My strong advice: either use the live-reloading hack, or don’t use Docker for local development.

OR — just run MongoDB in its own container and run your app locally using npm run dev or some such. But that is super problematic if you want to push the whole thing to prod as a self-contained image.

That’s all, folks…

Happy coding! 😃

I’m a Front End Engineer who loves React, NextJS, and GraphQL. Need a REMOTE React Developer? Contact me at: https://www.linkedin.com/in/bengrunfeld/

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store