Dockerize a MERN Stack app

7 min readNov 18, 2020

About :

You maybe developed your full-stack app with a huge set of dependencies and using this app from a client or another user will need a series of installations and system compatibility with the dependencies versions .. that’s why it would be better to use Docker :) So let’s go fast and deeper.

Quick reminder :

Photo by AbsolutVision on Unsplash

First of all, let’s have a quick briefing about docker; docker is simply an open source tool to launch apps on Linux containers and it’s considered the best substitute of VMs since it used less system memory and resources with a full resources and accesses management with more performance, so smooth and doesn’t require a performant laptop as a VMs does. With docker you just build specify your app’s configuration dependencies then create an image which is a set of layers created for your app to be able to launch an instance of your app on a container zipping all your configuration, you can find more comparison between these two with more described figures here . Docker is available on Linux, MacOS and Windows you can get it from here or you can try it out on the cloud with “Play with Docker” solution from here.

Things in action :

Photo by Mika Baumeister on Unsplash

As a first example we’ll take a simple app with React.js in the front-end, Express.js and MongoDB in the backend, so let’s set it up.


Let’s create our React.js app and name it “hello-world” by typing :

npx create-reate-app hello-world

Now open it in VSCode (for example) and edit the code to make a simple call for the backend, so let’s install Axios to manage our http/https calls :

npm install axios

Go and create a folder and call it services, inside that folder create an index file as follows :

Once we installed and configured Axios, let’s discover our frontend app briefly : We’ll build a simple React app that shows movies trending in a public access page but to access a movie details like description and videos the user will have to sign in, remember that the idea isn’t to build a huge set of functionalities but just to show how dockerizing works (if you’re interested in the full version of the movies app, you’ll find it as a mobile app that I built in React-Native on my GitHub), you’ll find later the link to the code on GitHub so just focus on the infrastructure :)

Now to go fast we’ll use Material-UI design library, let’s start by creating a simple form to log-in just simple as possible, so install Material-UI icons and core :

npm i @material-ui/icons @material-ui/core

Then to manage our data, we’ll use redux , so be sure to install redux and react-redux for the redux integration in react.js :

npm i redux react-redux

Our frontend repository tree looks like this :

Backend :

For the backend just create a folder in the same root directory and name it “server” for example then initialize it with npm :

npm init

Now we need to add “mongo” and “express” so just install them with :

npm i express mongodb

So now we can create our routes smoothly and fast, but don’t forget we need the movies trending and descriptions so I’ve chosen for that one of the most famous movies database it’s “TMDb”. Just for more better work management, create a file and name it “access.json” to store there our api_key and mongo database information

Now just set routes, below you can find a snippet of the source code :

Don’t worry the complete source code will be available on my GitHub with links just blow 😉.

Infrastructure :

Now let’s jump and start setting the Docker infrastructure for both frontend and backend :

Frontend :

Just create two files in the frontend directory “Dockerfile” and “.dockerignore” the first one is set our frontend configuration and the second one to tell docker to ignore some build generated files

For “Dockerfile” : Here telling Docker that first create a layer from the “node” docker image, create a work directory and name it “/app” , copy package.json and package-lock.json in that directory, run “npm install” to generate all the node_modules for our dependecies, copy all the generated folders in our work directory, the image will be listening on the port 3000 (you can set any port), then we specify the command to be run within the container, that’s it 😊.

Backend :

The same thing as before, create “Dockerfile” and “.dockerignore” files and with the same content since later we’ll use docker-compose the specify all the links between our different parts and images dependencies.

Now in the root folder create a file and name it “docker-compose.yml” :

Here Docker will create for us three services (images); app for the backend, client for the frontend and mongo for mongo image, as you can see after the “Dockerfile” files the “.yml” file becomes more readable and clear; the service app will be run on “app” container, uses the “app” docker image built with the backend dockerfile and depends on the mongo docker image which means that it has to create the mongo image before starting the “app” container. Quite the same for the second service; the client image is linked (depends on) the backend image so the system will start the backend image before the frontend image. Another thing maybe you might notice about the port it’s 3000:3000 , well actually the first “3000” means that the container will be run on the docker virtual machine with the port 3000 and for the external machine (our standard localhost) on the second “3000” (sure the port 3000 is the default port of React.js apps), this will be clearer when we start generated the images and starting them.

Now run the command below to build our images with the defined configurations above :

docker-compose build

Don’t worry about the lines in red they’re just npm warnings not that big deal😏.

Once the build is done, go and check if the images are created by running :

docker images

So now let’s start them, the best way to do that is to start them separatory, so first start mongo then the backend and the frontend :

docker-compose up -d mongo

docker-compose up -d server

docker-compose up -d client

Now it depends on your Docker installation config, normally you can access the app on http:localhost:3000 but it would be better to run :

docker-machine ip

This will give you the Docker machine IP address so just open in your browser <given_address>:3000 to load the app :

If the user click on a movie to see the description and videos or wanna check the bookmarked list, will be redirected to login first

Now after a correct inputs match try, he can access the bookmarked list and check the all information about a specific movie

Movie description :

And to stop your app either you can stop a specific container or if you want you can stop them all by typing :

docker-compose down

Bonus 😊:

If anything related to a localhost call (for example in the Axios Instance config file) doesn’t work for you then just replace it by the Docker machine IP address.

Source code :

— — — — — — — — — — — — -“Best of luck😊” — — — — — — — — — — — —