Tuesday, May 5, 2020

Docker Assignments #14: Node.js, MySQL, Express, Nodemon and Docker Compose Dependencies Wait-for-it

Usually we use "depends_on" configuration in docker-compose.yml file if you are working on multi container application where as one container depending on another  container.

However "depends_on" only checks whether a container is running or not. It doesn't not verify whether container accepting connections are not.

For Example,  web app depending on "mysql" service. It will only checks mysql container running or not. It will not check weather mysql ready to accept connections or not . i.e. mysql might be still executing migration db scripts or initial startup db script.

Wait-for-it bash script helps to over come this problem by checking the availability of TCP host and port before running web app container

Create a folder structure as per below image in the host machine

add following content into startscript.sql
create database hr;
use hr;
create table employee(id intname varchar(10));
insert INTO employee VALUES(1,'rama');

  1. Addd "mysql" and "express" npm packages as a dependency in the package.json file
  2. Add "nodemon" npm package as a dev dependency in the package.json file
  3. configure npm start command as "nodemon -L index.js" in package.json
  4. Write required code into index.js file to connect "mysql" container and expose endpoint using      express.js
  5. Configure Dockerfile with below instructions
  • set base image as "mhart/alpine-node"
  • setworking directory as "/usr/app"
  • download wait-for-it.sh from https://github.com/vishnubob/wait-for-it
  • provide execute permission to run wait-for-it.sh file
  • copy all files from host machine and do npm install
  • set CMD command to execute npm run start
     6. Write following instructions in docker-compose yml file
  • Configure"testmysql-service" service by pulling "mysql:5.7" image, set "MY_SQL_ROOT_PASSWORD" as "mysql123" , set up init script and port mapping - 3306
  • Configure"testnodeexpress-service" service by specifying build context as Dockerfile, create bindmount to /usr/app container path, volume mount to /usr/app/node_modules, dependent on "testmysql-service" and link to "testmysql-service"
  • Configure "testnodeexpress-service" npm command with wait-for-sh bash script
     7. Spin up containers using docker-compose up command
     8. check http://localhost:9030

Step 1: 
     > npm install mysql
     > npm install express

Step 2: 
     > npm install -D nodemon

Step 3: 
"scripts": {
    "start""nodemon -L index.js"
  },

Step 4:
var express = require('express');
var mysql=require('mysql');
var app = express();

app.get('/mysql'function (reqres) {
    var con = mysql.createConnection({
        host"testmysql",
        user"root",
        password"mysql123",
        port:"3306",
        database:"hr"
      });
      con.connect(function(err) {
        if (errthrow err;
        con.query("select * from employee",function(err,result,fields){
          if (errthrow err;
          res.send(result); 
        })
             
      });
});

app.listen(9030function () {
    console.log('App listening on port 9030!');
});

Step 5:
FROM mhart/alpine-node
WORKDIR /usr/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 9030

RUN chmod +x /usr/app/wait-for-it.sh
CMD ["npm""run""start"]

Step 6:
version'3'
services:
    testnodeexpress-service:
      build.
      volumes:
        - .:/usr/app 
        - /usr/app/node_modules       
      environment:
        NODE_ENVdevelopment  
      ports:
        - 9030:9030
      commandsh -c "/usr/app/wait-for-it.sh --timeout=0 testmysql:3306 && npm run start"
      depends_on
        - testmysql-service
      links
        - "testmysql-service:testmysql"  
    testmysql-service:
      imagemysql:5.7
      environment
        MYSQL_ROOT_PASSWORDmysql123  
      ports
        - 3306:3306  
      volumes
        - ./scripts:/docker-entrypoint-initdb.d   

Step 7:
docker-compose up


Monday, May 4, 2020

Docker Assignments #13: Node.js, MySQL, Express, Nodemon and Docker Compose

Docker Compose is a tool in the form of YAML configuration to run multi-container docker applications. With a single command, we can start or stop all the services specified in YAML configuration.

Docker Compose is a 3 step process

  1. Define app configuration using Dockerfile
  2. Define the services that app requires in docker-compose.yml so they can be run together in an isolated environment
  3. Run docker-compose up to starts and runs entire app
In the previous article (http://millionvisit.blogspot.com/2020/05/docker-assignments-12-nodejs-mysql.html) we had written docker run command to spin up "mysql" instance. But, In this article we are going to spin up "mysql" instance by using docker-compose.yml file

Create a folder structure as per below image in the host machine
  1. Add "mysql" and "express" npm packages as a dependency in the package.json file
  2. Add "nodemon" npm package as a dev dependency in the package.json file
  3. configure npm start command as "nodemon -L index.js" in package.json
  4. Write required code into index.js file to connect "mysql" container and expose endpoint using      express.js
  5. Configure Dockerfile with below instructions
  • set base image as "mhart/alpine-node"
  • set working directory  as "/usr/app"
  • copy all files from host machine and do npm install
  • set CMD command to execute npm run start
     6. Write following instructions in docker-compose yml file 
  • Configure "testmysql-service" service by pulling "mysql:5.7" image, set "MY_SQL_ROOT_PASSWORD" as "mysql123" and port mapping - 3306
  • Configure "testnodeexpress-service" service by specifying build context as Dockerfile, create bindmount to /usr/app container path, volume mount to /usr/app/node_modules, dependent on "testmysql-service" and link to "testmysql-service"
     7. Spin up containers using docker-compose up command
     8. check http://localhost:9030

Step 1: 
     > npm install mysql
     > npm install express

Step 2: 
     > npm install -D nodemon

Step 3: 
  "scripts": {
    "start""nodemon -L index.js"
  }

Step 4: 
var express = require('express');
var mysql=require('mysql');
var app = express();

app.get('/mysql'function (reqres) {
    var con = mysql.createConnection({
        host"testmysql",
        user"root",
        password"mysql123",
        port:"3306",
      });
      con.connect(function(err) {
        if (errthrow err;
        res.send("mysql connected successfully");      
      });
});

app.listen(9030function () {
    console.log('App listening on port 9030!');
});

Step 5:
FROM mhart/alpine-node
WORKDIR /usr/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 9030
CMD ["npm""run""start"]

Step 6:
version'3'
services:
    testnodeexpress-service:
      build.
      volumes:
        - .:/usr/app 
        - /usr/app/node_modules       
      environment:
        NODE_ENVdevelopment  
      ports:
        - 9030:9030
      commandnpm run start
      depends_on
        - testmysql-service
      links
        - "testmysql-service:testmysql"  
    testmysql-service:
      imagemysql:5.7      
      environment
        MYSQL_ROOT_PASSWORDmysql123  
      ports
        - 3306:3306  

Step 7:
docker-compose up

Friday, May 1, 2020

Docker Assignments #12: Node.js, MySQL, Express, Nodemon and Dockerfile

nodemon is used to develop node.js based applications by automatically restarting the node application when file changes in the directory.


Create a folder structure as per below image in the host machine
  1. Pull mysql:5.7 docker image into host machine
  2. Write docker run command by setting following options
  • enable detached mode
  • set container name as "testmysql"
  • map host port number to 3500
  • set MYSQL_ROOT_PASSWORD as “mysql123”
      3. Check testmysql container up and running
       4. Enter container using docker exec
       5. Connect to database using mysql CLI client with root user
       6. Create database with name “hr”
       7. Create table with name employee and “id, name” columns under “hr” database
       8. Insert sample data into employee table
       9. Check “HR” database and “Employee” table with data
      10. Add "mysql" and "express" npm packages as a dependency in the package.json file
      11. Add "nodemon" npm package as a dev dependency in the package.json file
      12. configure npm start command as "nodemon -L index.js" in package.json
      13. Write required code into index.js file to connect "testmysql" container and expose endpoint using      express.js
      14. Configure Dockerfile with below instructions
  • set base image as "mhart/alpine-node"
  • set working directory  as "/usr/app"
  • copy all files from host machine and do npm install
  • set CMD command to execute npm run start
    15. Build docker image with name "testnodemysqlimg"
    16. Write Docker run command by doing bindmount to host directory and linking "testmysql" container

Step 1: 
     > docker pull mysql:5.7
Step 2: 
     > docker run -d -p 3500:3306 -e MYSQL_ROOT_PASSWORD=mysql123 --name testmysql mysql:5.7
Step 3: 
     > docker ps
Step 4: 
     > docker exec -it testmysql mysql -u root -p

Step 6: 
     mysql> create database hr;
     mysql> use hr;
     mysql> create table employee(id int,name varchar(10));
     mysql> insert into employee values(1,'rama');
     mysql> select * from employee;

Step 10: 
     > npm install mysql
     > npm install express

Step 11: 
     > npm install -D nodemon

Step 12:
  "scripts": {
    "start""nodemon -L index.js"
  }

Step 13:
var express = require('express');
var mysql=require('mysql');
var app = express();

app.get('/mysql'function (reqres) {
    var con = mysql.createConnection({
        host"db"
        user"root",
        password"mysql123",
        port:"3306",
      });
      con.connect(function(err) {
        if (errthrow err;
        res.send("mysql connected successfully");      
      });
});

app.listen(9030function () {
    console.log('App listening on port 9030!');
});

Step 14:
FROM mhart/alpine-node
WORKDIR /usr/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 9030
CMD ["npm""run""start"]

Step 15:
docker build -t testnodemysqlimg .

Step 16:
  • Create volume called "nodeexpressvol" by using 
          >docker create volume nodeexpressvol

>docker run
-d
-p 9030:9030
  --link testmysql:db 
  --mount type=bind,source=/c/Users/rmukkama/node-express,target=/usr/app 
  --mount type=volume,source=nodeexpressvol,target=/usr/app/node_modules
  testnodemysqlimg

We are including two types of mounts here:

The first is a bind mount that mounts our application code on the host to the /usr/app directory on the container.
This will facilitate rapid development, since any changes you make to your host code will be populated immediately in the container.

The second is a named volume, "nodeexpressvol". When Docker runs the npm install instruction listed in the application Dockerfile, npm will create a new node_modules directory on the container that includes the packages required to run the application.
The bind mount we just created will hide this newly created node_modules directory,
however. Since node_modules on the host is empty, the bind will map an empty directory to the container, overriding the new node_modules directory and preventing our application from starting.
The named "nodeexpressvol" volume solves this problem by persisting the contents of the /usr/app/app/node_modules directory and mounting it to the container, hiding the bind.


Happy Coding :)