DEV Community

Cover image for How to Create Dockerized NodeJS with MySQL Database
Frastyawan Nym
Frastyawan Nym

Posted on

How to Create Dockerized NodeJS with MySQL Database

TLDR;
You can access the code here on Github
(step by step how to run included 🤝)

Hello 👋, This will be my first post on this forum.
I will show you guys how to create a NodeJS-MySQL database with help of Docker.

FYI, I just learn using docker too and I found that docker is very good to help development process faster ⚡.

Here we go

I will assume that you already know what docker is and already installed it on your machine. I will use docker-compose to create this project.

  1. Create MySQL Container, I'm using MySQL image to help me build this container.
  2. Create docker-compose.yaml file. I this file we will be specifying our docker app.
version: '3.8'

services: 
  mysqldb:
    image: mysql
    restart: always
    env_file: ./.env
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
      MYSQL_DATABASE: $MYSQL_DATABASE
    ports:
      - $MYSQL_LOCAL_PORT:$MYSQL_DOCKER_PORT
    volumes: 
      - db-config:/etc/mysql
      - db-data:/var/lib/mysql
      - ./db/backup/files/:/data_backup/data

volumes: 
  db-config:
  db-data:
Enter fullscreen mode Exit fullscreen mode

Description:

  • version: '3.8': This first line of code must be provided on docker-compose.yaml file. This will tell docker which version of docker we used
  • services:: Inside this tag we will tell docker what service we will make
  • mysqldb:: The first service is mysqldb. You're free to choose the name
  • image: mysql: We tell docker what image we will use. mysql is official image for MySQL
  • restart: always: This command will tell docker always restart the container regardless of the exit status
  • env_file: ./.env: We specify our .env path
  • environment: ON this tag we provide our MySQL connection setting
  • MYSQL_ROOT_PASSWORD:: Specify password for root username
  • $MYSQL_ROOT_PASSWORD is key from .env
  • MYSQL_DATABASE: $MYSQL_DATABASE: create initial database
  • ports:: we specify what port docker will be used. We will specify 2 port
  • $MYSQL_LOCAL_PORT: The first one is what port on our machine will be used
  • $MYSQL_DOCKER_PORT: The second one is what port we used inside docker container
  • volumes:: Volume will help us to keeping our data alive though restart
  • db-config:/etc/mysql: Volume to save config
  • db-data:/var/lib/mysql: Volume to save database data
  • ./db/backup/files/:/data_backup/data: Mount bind backup data

That a lot of typing already LOL 😂

Let's continue 🚀

  1. Now we make our NodeJS app, inside of app folder
  2. You can initialize npm as usual
  3. Here we will be create a Dockerfile, this will help us to create image for NodeJS App
FROM node:14

WORKDIR /app

COPY /app/package.json .

RUN npm install

COPY /app .

EXPOSE 3000

CMD [ "npm", "start" ]
Enter fullscreen mode Exit fullscreen mode

Description:

  • FROM node:14: Specify base image for node. I take official image of NodeJS
  • WORKDIR /app: Define working directory of docker. Our app will be placed on this folder inside docker
  • COPY /app/package.json .: Copy our package.json file to our working directory (declared by dot(.) code)
  • RUN npm install: Install npm dependency as always
  • COPY /app .: Next we will copy our rest of file to working directory
  • EXPOSE 3000: We expose port to access via localhost
  • CMD [ "npm", "start" ]: Specify script to run after image is builded

Did you confused? If yes, me too when first learning this docker thing 😁

Continue 🚀

Back to our docker-compose.yaml file

  1. Now we will define our NodeJS App on docker-compose
  app:
    build:
      context: .
      dockerfile: ./app/Dockerfile
    image: node-mysql-app
    depends_on:
      - mysqldb
    stdin_open: true
    tty: true

volumes: 
  db-config:
  db-data:
Enter fullscreen mode Exit fullscreen mode

The command is more or less the same

Description

  • app:: This is our second service's name
  • build:: For custom image we will use build
  • context: .: Specify the file PATH
  • dockerfile: ./app/Dockerfile: This will be our previous Dockerfile
  • image: node-mysql-app: Define name to our custom image
  • depends_on: - mysqldb: This will tell docker that the second service will depends on first service
  • stdin_open: true: This will tell docker that keep open the terminal after complete building container
  • tty: true: Same as above
  • volumes:: Last, we tell docker that we have named volume inside our service
  • db-config:: This is the name of the named volume
  • db-data:: This is the name of the named volume

And there we go, that's all is needed for creating our docker app 👍
Lastly, we will execute this command to start our apps: docker-compose up
After success, you can access your app on localhost:3000 🐳

Summary

With this, We don't need to install MySQL locally to start development right. I think this is the power of docker "To speed up our development process"
That's all I can share with you for now 😊
If you have any question, you can post it here. I hope that I can help to answer it 💪

Or maybe you can reach me on my Twitter
I love to build a new connection 😁

Until then... 🚀

Discussion (10)

Collapse
stevehsu profile image
Steve Hsu

Great Job! I'm a rookie for docker, your documentation is clear and easy to understand. Thans you!

Collapse
tremainebuchanan profile image
Tremaine Buchanan

Nice post. But I think for newbies, you could specific what values should be contained in the .env as this file would've left out of the repository. You can go even further to include the .env with the keys and omit the values such that newbies can fill in the blanks.

Collapse
frasnym profile image
Frastyawan Nym Author

Ah I see, thank you for your correction 🙏
I have updated the source code 🤝

Collapse
shoebpatel profile image
Shoeb Patel • Edited on

Hey Frastyawan Nym,

I have tried running docker with your repo but failed to connect with mysql server.

please refer below image.

dev-to-uploads.s3.amazonaws.com/up...

Collapse
hovhrachya93 profile image
Hrach

@shoebpatel How do you solved your problem because i have too

Collapse
pedromirandareis profile image
Pedro Miranda • Edited on

This is exactly what Im looking for, thanks for your hard work!

Mysql is working fine but json dont

Error: Cannot find module 'dotenv'
Require stack:

  • /app/index.js at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15) at Function.Module._load (internal/modules/cjs/loader.js:725:27) at Module.require (internal/modules/cjs/loader.js:952:19) at require (internal/modules/cjs/helpers.js:88:18) at Object. (/app/index.js:1:1) at Module._compile (internal/modules/cjs/loader.js:1063:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10) at Module.load (internal/modules/cjs/loader.js:928:32) at Function.Module._load (internal/modules/cjs/loader.js:769:14) at Function.executeUserEntryPoint as runMain
Collapse
frasnym profile image
Frastyawan Nym Author

Hello,

It's like that you don't install dotenv module 🤔
Can I see you package.json file? or project repo if possible?

Collapse
maxcrazy profile image
Maxcrazy1

I have been trying for days, but I can never connect to the container, the port is activated, everything is correct, but when I try to access localhost:3000 it does not connect 😿, any ideas?

Collapse
frasnym profile image
Frastyawan Nym Author

can u share your code?

Collapse
maxcrazy profile image
Maxcrazy1

Sure, thx.

Dockerfile

FROM node:14

# Create app directory
WORKDIR /usr/src/catidu-api

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY . .

RUN npm install -g serverless@2.68.0
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source

EXPOSE 3000

CMD [ "npm","start" ]
Enter fullscreen mode Exit fullscreen mode

docker-compose.yml

version: '3.8'
services:
  mysqldb:
    image: mysql
    restart: always
    env_file: ./.env
    environment:
      - MYSQL_ROOT_PASSWORD=$DB_PASSWORD_DEVELOPMENT
      - MYSQL_DATABASE=$DB_NAME_DEVELOPMENT
    ports:
      - $DB_LOCAL_PORT:$DB_DOCKER_PORT
    volumes:
      - db-config:/etc/mysql
      - db-data:/var/lib/mysql
      - ./db/backup/files/:/data_backup/data
  catidu-api:
    build:
      context: .
      dockerfile: ./Dockerfile
    image: catidu-sls-app
    depends_on:
      - mysqldb
    stdin_open: true
    ports:
      - 3000:3000
    tty: true
volumes: 
  db-config:
  db-data:
Enter fullscreen mode Exit fullscreen mode

.env

DB_PASSWORD_DEVELOPMENT=password
DB_NAME_DEVELOPMENT=my_db

DB_LOCAL_PORT=3306
DB_DOCKER_PORT=3307
Enter fullscreen mode Exit fullscreen mode

I've to say this project use serverless, maybe that's what's causing the error. I don't know, I appreciate any suggestion.