Setting Up Node App using Docker

·

3 min read

Create a docker setup to build a Node Express app with MySQL and Redis

  1. Create a directory and go switch to it

     mkdir nodeapp
     cd nodeapp
    
  2. Create package.json

    To avoid installing Node locally, we will use this docker command to npm init

     docker run --rm -v "$PWD:/$(basename $PWD)" -w "/$(basename $PWD)" -it node:current-alpine sh -c "npm init"
    
  3. Install dotenv and express packages

     docker run --rm -v "$PWD:/$(basename $PWD)" -w "/$(basename $PWD)" -it node:current-alpine sh -c "npm install dotenv express"
    
     docker run --rm -v "$PWD:/$(basename $PWD)" -w "/$(basename $PWD)" -it node:current-alpine sh -c "npm install --save-dev nodemon"
    
  4. Edit package.json to add to scripts section

     "start": "node index.js",
     "dev": "nodemon index.js"
    
  5. Create .env

     APP_PORT=3000
     DOCKER_PORT=3000
    
     #db is the service name in docker-compose.yml
     DB_HOST=db
     DB_PORT=3306
     DB_NAME=nodeapp
    
     # can be left blank if using root username
     DB_USERNAME=
     DB_PASSWORD=
     DB_PORT=3306
    
     # redis is the service name in docker-compose.yml
     REDIS_HOST=redis
     REDIS_PASSWORD=null
     REDIS_PORT=6379
    
  6. Create Dockerfile

     #change node version to your liking
     FROM node:18
     WORKDIR /app/
     COPY ./package.json .
     RUN npm install
     COPY ./* .
     EXPOSE $DOCKER_PORT
    
  7. Create docker-compose.yml

     version: '3'
     services: 
       web:
         build:
           context: .
         env_file: ./.env
         tty: true
         volumes: 
           - ./:/app/
           - node_modules:/app/node_modules
         ports:
           - '${APP_PORT:-3000}:${DOCKER_PORT:-3000}'
         depends_on: 
           - db
         networks:
           - nodeapp
       db:
         image: mysql:latest
         env_file: ./.env
         environment: 
           MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
           MYSQL_ROOT_HOST: "%"
           MYSQL_DATABASE: '${DB_NAME}'
           MYSQL_USER: '${DB_USERNAME}'
           MYSQL_PASSWORD: '${DB_USERNAME}'
           MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
         ports:
           - '${DB_PORT:-3306}:3306'
         volumes:
           - mysql:/var/lib/mysql
         networks:
           - nodeapp
       redis:
         image: 'redis:alpine'
         ports:
           - '${REDIS_PORT:-6379}:6379'
         volumes:
           - 'redis:/data'
         networks:
           - nodeapp
         healthcheck:
           test: ["CMD", "redis-cli", "ping"]
           retries: 3
           timeout: 5s
     networks:
       nodeapp:
         driver: bridge
     volumes:
       node_modules:
         driver: local
       mysql: 
         driver: local
       redis:
         driver: local
    
  8. Create index.js

     require('dotenv').config();
    
     const express = require('express');
     const app = express();
    
     // Constants
     const PORT = process.env.DOCKER_PORT || 3000;
     const HOST = '0.0.0.0';
    
     // App
     app.get('/', (req, res) => {
         res.send('Hello World!');
     });
    
     app.listen(PORT, HOST, () => {
          console.log(`Running on http://${HOST}:${PORT}`);
     });
    
  9. Run docker-compose up -d

  10. Run docker-compose exec web npm run dev

  11. Go to http://localhost:3000 3000 will be APP_PORT

BONUS

To easily run npm commands, do the following

  1. Create a file with the name soar

     #!/bin/bash
    
     path=$(printf '%s\n' "${PWD##*/}")
    
     # get first arg
     arg1=$1
    
     if [[ $arg1 == "up" ]]; then
         command="docker-compose up -d"
         $command
     elif [[ $arg1 == "down" ]]; then
         command="docker-compose down"
         $command
     else
         # remove first arg
         shift
    
         # get rest of args
         argrest=$@
    
         # web is the service name in docker-compose.yml
         command="docker-compose exec web $arg1 "$argrest""
    
         # run the command
         $command
     fi
    
  2. Make soar runnable

     chmod 700 soar
    
  3. Test it with

     ./soar npm -h
    
  4. Create an alias for ./soar to soar

     alias './soar'
    

    To make sure this is always available, you may add this to your shell configuration file in your home directory, such as ~/.zshrc or ~/.bashrc, and then restart your shell.

  5. Now you can start docker, run npm, or npx

    Start docker container

     soar up
    

    Stop docker container

     soar down
    

    Run npm

     soar npm list
    

    Run npx

     soar npx ...