Skip to content
Blog Home
Articles
Category
  • Blog Home
    • Slide page
      • Articles

          • Stopping specific bots from using your monthly ShipperHQ quota
            • Dockerizing a MERN stack
              • Intro
                • Folder structure
                  • Frontend
                    • Server
                      • Packing everything into a single file
                        • Important notes about docker-compose.yml
                          • Debugging
                        • Easy way to add google Ads to vuepress running on netlify
                          • Easy way to add google analytics to vuepress running on netlify

                        Dockerizing a MERN stack

                        author iconMichael LaPancalendar iconApril 5, 2022category icon
                        • Programming
                        tag icon
                        • programming
                        • docker
                        • mern
                        timer iconAbout 3 min

                        On This Page
                        • Intro
                          • Folder structure
                          • Frontend
                          • Server
                          • Packing everything into a single file
                          • Important notes about docker-compose.yml
                          • Debugging

                        # Dockerizing a MERN stack

                        Plus what they dont tell you.

                        # Intro

                        As there are loads of tutorials out there that go over the specifics of what everything does. I’m going to try and keep this short sweet and simple. This assumes you have basic docker knowledge. I will be touching on any issue I had come across and what I’ve done to resolve them.

                        In the end, you will have a docker-compose driven MERN stack with hot reload

                        # Folder structure

                        This docker app will have the following folder structure.

                        root-folder
                          |>frontend
                            Dockerfile
                            {front end files}
                          |>server
                            Dockerfile
                            {server end files}
                          docker-compose.yml
                        
                        1
                        2
                        3
                        4
                        5
                        6
                        7
                        8

                        # Frontend

                        From inside the frontend folder run npx create-react-app .

                        This command creates a full react app for you. With various folders, files, and configurations out of the box. This is the easiest way to do it if you want to start with a skeleton project.

                        After this command is done run yarn start or npm start. If you are able to access and edit the site + see hot reloading. then you are good to keep moving.

                        While still in the frontend folder, create a file named Dockerfile and paste the following

                        FROM node:alpine
                        
                        WORKDIR /app 
                        
                        COPY package.json package.json 
                        
                        RUN npm install
                        
                        COPY . .
                        
                        EXPOSE 3000
                        
                        CMD ["npm","run", "start"]
                        
                        1
                        2
                        3
                        4
                        5
                        6
                        7
                        8
                        9
                        10
                        11
                        12
                        13

                        This docker file does the following.

                        1. use the node:alpine base box. alpine is a minimal node.js docker box.
                        2. Set the folder we will be using to hold all our code
                        3. Copy are deps list, install them, then copy code to the folder.
                        4. Open port 3000 to the outside
                        5. Command to run when starting the box
                        6. You can check to see if everything is working by running the following commands
                        docker build -t react-app .
                        docker run -p 3000:3000 react-app
                        
                        1
                        2

                        # Server

                        For the server, we will be using a similar command to get us a skeleton project. Both the server setup and frontend setup are very similar

                        From inside the server folder run npx express-generator .

                        This command creates a full express app for you. With various folders, files, and configurations out of the box. This is the easiest way to do it if you want to start with a skeleton project.

                        You will need to create a .env file and put PORT=5000 for the express app to start on the correct port.

                        After this command is done run npm install -g nodemon to enable hot reloading.

                        nodemon ./bin/www to start the express app. You should then be able to access the site on localhost and ensure everything is working.

                        While still in the server folder, create a file named Dockerfile and paste the following

                        FROM node:alpine
                        
                        WORKDIR /app 
                        
                        COPY package.json package.json 
                        
                        RUN npm install 
                        
                        COPY . . 
                        
                        EXPOSE 5000 
                        
                        RUN npm install -g nodemon 
                        
                        CMD [ "nodemon", "./bin/www" ] 
                        
                        1
                        2
                        3
                        4
                        5
                        6
                        7
                        8
                        9
                        10
                        11
                        12
                        13
                        14
                        15

                        This docker file does the following.

                        1. use the node:alpine base box. alpine is a minimal node.js docker box.
                        2. Set the folder we will be using to hold all our code
                        3. Copy are deps list, install them, then copy code to the folder.
                        4. Open port 3000 to the outside
                        5. install hot reloading globally
                        6. Command to run when starting the box You can check to see if everything is working by running the following commands
                        docker build -t myapp-server .
                        docker run p 5000:5000 myapp-server 
                        
                        1
                        2

                        # Packing everything into a single file

                        Now in the main folder create a docker-compose.yml and past the following.

                        version: '3.7'
                        
                        services:
                          server:
                            tty: true
                            build:
                              context: ./server
                              dockerfile: Dockerfile
                            image: myapp-server
                            container_name: myapp-node-server
                            command: npm start
                            volumes:
                              - ./server:/app
                              - /app/node_modules
                            ports:
                              - "5000:5000"
                            depends_on:
                              - mongo
                            env_file: ./server/.env
                            environment:
                              - NODE_ENV=development
                            networks:
                              - app-network
                          mongo:
                            image: mongo
                            volumes:
                              - data-volume:/data/db
                            ports:
                              - "27017:27017"
                            networks:
                              - app-network
                          client:
                            tty: true
                            build:
                              context: ./frontend
                              dockerfile: Dockerfile
                            image: myapp-client
                            container_name: myapp-react-client
                            command: npm start
                            volumes:
                              - ./frontend:/app
                              - /app/node_modules
                            depends_on:
                              - server
                            ports:
                              - "3000:3000"
                            networks:
                              - app-network
                            environment:
                              - CHOKIDAR_USEPOLLING=true
                        networks:
                            app-network:
                                driver: bridge
                        
                        volumes:
                            data-volume:
                            node_modules:
                            web-root:
                              driver: local
                        
                        1
                        2
                        3
                        4
                        5
                        6
                        7
                        8
                        9
                        10
                        11
                        12
                        13
                        14
                        15
                        16
                        17
                        18
                        19
                        20
                        21
                        22
                        23
                        24
                        25
                        26
                        27
                        28
                        29
                        30
                        31
                        32
                        33
                        34
                        35
                        36
                        37
                        38
                        39
                        40
                        41
                        42
                        43
                        44
                        45
                        46
                        47
                        48
                        49
                        50
                        51
                        52
                        53
                        54
                        55
                        56
                        57
                        58
                        59

                        This may look like a lot, be reading through the file is very self-explaining.

                        You can now run the file with

                        docker-compose build
                        docker-compose up
                        
                        1
                        2

                        You should now be able to visit localhost:3000 and see your react app + hot reloading. Visit localhost:5000 and see your express app + hot reloading. Lastly, you should be able to connect to your mongo server on port 27017

                        # Important notes about docker-compose.yml

                        While doing this myself self I ran into a problem with the react app not hot reloading.

                        It is very important to have

                        environment:
                          - CHOKIDAR_USEPOLLING=true
                        tty: true
                        
                        1
                        2
                        3

                        in the file for the client section.

                        There is currently a bug in react-scripts 3.4.3 the breaks building in docker if the terminal is not open.

                        # Debugging

                        If you need to debug the express server, I would recommend commenting on the client section. You will then be able to see the output from the express server. This can sometimes lead you to any issues it is having.

                        If you keep getting module not found errors. Make sure the module is in your package.json. Make sure you rebuilt the docker-compose. If that fails try editing the Dockerfile for the app that is missing the module. adding node install -g module-name allows you to install it globally. While this is not the best option, it can be the fastest and least frustrating.

                        Last update: 4/5/2022, 11:56:16 PM
                        Contributors: Michael lapan
                        Prev
                        Stopping specific bots from using your monthly ShipperHQ quota
                        Next
                        Easy way to add google Ads to vuepress running on netlify
                        Copyright © 2022 Michael LaPan

                        This app can be installed on your PC or mobile device. This will allow this web app to look and behave like any other installed app. You will find it in your app lists and be able to pin it to your home screen, start menus or task bars. This installed web app will also be able to safely interact with other apps and your operating system.

                        Description