├── mysql-microservice ├── data │ └── .gitkeep ├── Dockerfile └── test-dump.sql ├── nodejs-microservice ├── .dockerignore ├── Dockerfile ├── package.json ├── index.js └── package-lock.json ├── screenshots ├── building-test-mysql-image.png ├── building-test-nodejs-image.png ├── connecting-to-test-mysql-microservice.png ├── running-test-mysql-microservice-container.png └── running-test-nodejs-microservice-container.png ├── .gitignore ├── LICENSE.md └── README.md /mysql-microservice/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nodejs-microservice/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /screenshots/building-test-mysql-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/getting-started-docker-mysql-nodejs/HEAD/screenshots/building-test-mysql-image.png -------------------------------------------------------------------------------- /screenshots/building-test-nodejs-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/getting-started-docker-mysql-nodejs/HEAD/screenshots/building-test-nodejs-image.png -------------------------------------------------------------------------------- /screenshots/connecting-to-test-mysql-microservice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/getting-started-docker-mysql-nodejs/HEAD/screenshots/connecting-to-test-mysql-microservice.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # exclude everything form data folder 2 | mysql-microservice/data/* 3 | 4 | # exception to the rule 5 | !mysql-microservice/data/.gitkeep 6 | 7 | nodejs-microservice/node_modules 8 | -------------------------------------------------------------------------------- /screenshots/running-test-mysql-microservice-container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/getting-started-docker-mysql-nodejs/HEAD/screenshots/running-test-mysql-microservice-container.png -------------------------------------------------------------------------------- /screenshots/running-test-nodejs-microservice-container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/varunon9/getting-started-docker-mysql-nodejs/HEAD/screenshots/running-test-nodejs-microservice-container.png -------------------------------------------------------------------------------- /mysql-microservice/Dockerfile: -------------------------------------------------------------------------------- 1 | ## Pull the mysql:5.7 image 2 | FROM mysql:5.7 3 | 4 | ## The maintainer name and email 5 | MAINTAINER Varun Kumar 6 | 7 | # database = test and password for root = password 8 | ENV MYSQL_DATABASE=test \ 9 | MYSQL_ROOT_PASSWORD=password 10 | 11 | # when container will be started, we'll have `test` database created with this schema 12 | COPY ./test-dump.sql /docker-entrypoint-initdb.d/ 13 | -------------------------------------------------------------------------------- /nodejs-microservice/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use Node v8 as the base image. 2 | FROM node:8 3 | 4 | # create and set app directory 5 | RUN mkdir -p /usr/src/app 6 | WORKDIR /usr/src/app 7 | 8 | # Install app dependencies 9 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 10 | # where available (npm@5+) 11 | COPY package*.json ./ 12 | RUN npm install 13 | 14 | # Bundle app source 15 | COPY . . 16 | 17 | # Run app 18 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /nodejs-microservice/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-microservice", 3 | "version": "1.0.0", 4 | "description": "Running a nodejs application with mysql database as microservices using docker", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/varunon9/getting-started-docker-mysql-nodejs.git" 13 | }, 14 | "keywords": [ 15 | "docker", 16 | "mysql-docker", 17 | "nodejs-docker", 18 | "microservice" 19 | ], 20 | "author": "Varun Kumar ", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/varunon9/getting-started-docker-mysql-nodejs/issues" 24 | }, 25 | "homepage": "https://github.com/varunon9/getting-started-docker-mysql-nodejs#readme", 26 | "dependencies": { 27 | "body-parser": "^1.18.3", 28 | "express": "^4.16.3", 29 | "mysql": "^2.15.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Varun kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /mysql-microservice/test-dump.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 5.6.16, for debian-linux-gnu (x86_64) 2 | -- 3 | -- Host: localhost Database: test 4 | -- ------------------------------------------------------ 5 | -- Server version 5.6.16-1~exp1 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `students` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `students`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!40101 SET character_set_client = utf8 */; 25 | CREATE TABLE `students` ( 26 | `rollNo` int(11) NOT NULL, 27 | `name` varchar(255) DEFAULT NULL, 28 | PRIMARY KEY (`rollNo`) 29 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 30 | /*!40101 SET character_set_client = @saved_cs_client */; 31 | 32 | -- 33 | -- Dumping data for table `students` 34 | -- 35 | 36 | LOCK TABLES `students` WRITE; 37 | /*!40000 ALTER TABLE `students` DISABLE KEYS */; 38 | INSERT INTO `students` VALUES (1130328,'Varun Kumar'); 39 | /*!40000 ALTER TABLE `students` ENABLE KEYS */; 40 | UNLOCK TABLES; 41 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 42 | 43 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 44 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 45 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 46 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 47 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 48 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 49 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 50 | 51 | -- Dump completed on 2018-07-06 23:57:05 52 | -------------------------------------------------------------------------------- /nodejs-microservice/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Varun Kumar 3 | */ 4 | 5 | const app = require('express')(); 6 | const mysql = require('mysql'); 7 | 8 | const bodyParser = require('body-parser'); 9 | 10 | app.use(bodyParser.json({ 11 | limit: '8mb' 12 | })); // support json encoded bodies 13 | 14 | // environment variables 15 | const PORT = process.env.PORT || 4000; 16 | const HOST = process.env.HOST || '0.0.0.0'; 17 | 18 | // mysql credentials 19 | const connection = mysql.createConnection({ 20 | host: process.env.MYSQL_HOST || '172.17.0.2', 21 | user: process.env.MYSQL_USER || 'root', 22 | password: process.env.MYSQL_PASSWORD || 'password', 23 | database: process.env.MYSQL_DATABASE || 'test' 24 | }); 25 | 26 | connection.connect((err) => { 27 | if (err) { 28 | console.error('error connecting mysql: ', err); 29 | } else { 30 | console.log('mysql connection successful'); 31 | app.listen(PORT, HOST, (err) => { 32 | if (err) { 33 | console.error('Error starting server', err); 34 | } else { 35 | console.log('server listening at port ' + PORT); 36 | } 37 | }); 38 | } 39 | }); 40 | 41 | // home page 42 | app.get('/', (req, res) => { 43 | res.json({ 44 | success: true, 45 | message: 'Hello world' 46 | }); 47 | }); 48 | 49 | // insert a student into database 50 | app.post('/add-student', (req, res) => { 51 | const student = req.body; 52 | const query = 'INSERT INTO students values(?, ?)'; 53 | 54 | connection.query(query, [student.rollNo, student.name], (err, results, fields) => { 55 | if (err) { 56 | console.error(err); 57 | res.json({ 58 | success: false, 59 | message: 'Error occured' 60 | }); 61 | } else { 62 | res.json({ 63 | success: true, 64 | message: 'Successfully added student' 65 | }); 66 | } 67 | }); 68 | }); 69 | 70 | // fetch all students 71 | app.post('/get-students', (req, res) => { 72 | const query = 'SELECT * FROM students'; 73 | connection.query(query, (err, results, fields) => { 74 | if (err) { 75 | console.error(err); 76 | res.json({ 77 | success: false, 78 | message: 'Error occured' 79 | }); 80 | } else { 81 | res.json({ 82 | success: true, 83 | result: results 84 | }); 85 | } 86 | }); 87 | }); 88 | 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # getting started with docker-mysql-nodejs 2 | 3 | Running a nodejs application with mysql database using docker and microservice architecture 4 | 5 | ### Our end goal 6 | 7 | - Launch mysql server in a docker container. 8 | - Launch our simple node app in a separate container. 9 | - Link these two containers and test our integrated mysql-nodejs app. 10 | 11 | ### Youtube link- 12 | 13 | Watch this tutorial at https://youtu.be/tIbMSqTEpfY 14 | 15 | ### Prerequisite 16 | 17 | - must have docker set up and running on your system 18 | 19 | ### Launching mysql in a container 20 | 21 | 1. Create a directory for our tutorial `mkdir getting-started-docker-mysql-nodejs` 22 | 2. Move to this directory `cd getting-started-docker-mysql-nodejs/` 23 | 3. Create a directory for our mysql microservice `mkdir mysql-microservice` 24 | 4. Move to this directory `cd mysql-microservice/` 25 | 5. Create a Dockerfile with following content (name of file will be `Dockerfile`) 26 | ``` 27 | ## Pull the mysql:5.7 image 28 | FROM mysql:5.7 29 | 30 | ## The maintainer name and email 31 | MAINTAINER Your Name 32 | 33 | # database = test and password for root = password 34 | ENV MYSQL_DATABASE=test \ 35 | MYSQL_ROOT_PASSWORD=password 36 | 37 | # when container will be started, we'll have `test` database created with this schema 38 | COPY ./test-dump.sql /docker-entrypoint-initdb.d/ 39 | 40 | ``` 41 | 6. We'll initialize our test database with a sample schema. 42 | Download [test-dump.sql](https://github.com/varunon9/getting-started-docker-mysql-nodejs/blob/master/mysql-microservice/test-dump.sql) and put it inside mysql-microservice folder along with Dockerfile 43 | 44 | 7. Create a data directory where mysql will store its content `mkdir data`. 45 | We will specify this directory while running our mysql container. 46 | On Linux default storage directory is `/var/lib/mysql` but in this tutorial we'll use a custom storage directory. 47 | 48 | 8. Build the image with Dockerfile `docker build -t test-mysql .` 49 | Note that we are inside mysql-microservice directory. `test-mysql` would be name of our image 50 | 51 | 9. You can check your newly built image using `docker images` 52 | ![Building the image using Dockerfile](./screenshots/building-test-mysql-image.png) 53 | 54 | 10. Run the newly created docker image as container 55 | ``` 56 | docker run -d \ 57 | --publish 6603:3306 \ 58 | --volume=/home/varunkumar/getting-started-docker-mysql-nodejs/mysql-microservice/data:/var/lib/mysql \ 59 | --name=test-mysql-microservice test-mysql 60 | ``` 61 | 62 | 11. With above command we started our container in detach mode `-d` and mapped host(your machine) port 6603 with container port 3306 (mysql server) `--publish 6603:3306`. 63 | We are also using our custom data storage directory by specifying host path volume `--volume`. 64 | Replace `/home/varunkumar/getting-started-docker-mysql-nodejs/mysql-microservice/data` path to absolute path of data directory which you created on your system. 65 | We are also naming our container as test-mysql-microservice `--name` 66 | 67 | 12. Check logs to see if everything went smooth `docker logs test-mysql-microservice` 68 | 69 | 13. Check your container state `docker ps` 70 | ![Running the docker image](./screenshots/running-test-mysql-microservice-container.png) 71 | 72 | 14. We have successfully launched a mysql container 73 | 74 | 75 | ### Connecting to newly launched mysql container from host (optional) 76 | 77 | To verify that our test-mysql-microservice container is up and running, we'll connect to it. 78 | Follow below steps if you have mysql (mysql-client) installed on your system. 79 | 80 | 1. Check the ip of your system. On Linux use `ifconfig`. Lets say that ip is 192.168.43.147 81 | 2. Connect to test-mysql-microservice container with following params- 82 | user-root, host=192.168.43.147, port=6603, database=test and password=password. 83 | Remember that we have specified root username and password in Dockerfile. 84 | Also our container is initialized with test-dump.sql (a schema with database name test) 85 | 86 | 3. `mysql -u root -p -h 192.168.43.147 -P 6603 -D test` 87 | Use password=password when prompt and hit enter 88 | 89 | 4. If connected successfully you can see a sample table students `show tables` 90 | `exit` when done. 91 | ![Connecting to mysql container from host](./screenshots/connecting-to-test-mysql-microservice.png) 92 | 93 | ### Launching nodejs app in a container 94 | 95 | 1. Right now we are in mysql-microservice directory. We go to project root directory `cd ..` 96 | 2. create directory for node microservice `mkdir nodejs-microservice` 97 | 3. Move to this directory `cd nodejs-microservice/` 98 | 4. Create a Dockerfile with following content (name of file will be `Dockerfile`) 99 | ``` 100 | # Use Node v8 as the base image. 101 | FROM node:8 102 | 103 | # create and set app directory 104 | RUN mkdir -p /usr/src/app 105 | WORKDIR /usr/src/app 106 | 107 | # Install app dependencies 108 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 109 | # where available (npm@5+) 110 | COPY package*.json ./ 111 | RUN npm install 112 | 113 | # Copy app source from current host directory to container working directory 114 | COPY . . 115 | 116 | # Run app 117 | CMD ["npm", "start"] 118 | 119 | ``` 120 | 5. We need a package.json file for our node-microservice app as well as source code. 121 | For this tutorial, I've already created one. 122 | Download [package.json](https://github.com/varunon9/getting-started-docker-mysql-nodejs/blob/master/nodejs-microservice/package.json) as well as [index.js](https://github.com/varunon9/getting-started-docker-mysql-nodejs/blob/master/nodejs-microservice/index.js) and put it inside nodejs-microservice folder along with Dockerfile. 123 | 124 | 6. Build the image with Dockerfile `docker build -t test-nodejs .` 125 | Note that we are inside nodejs-microservice directory. `test-nodejs` would be name of our image 126 | 127 | 7. You can check your newly built image using `docker images` 128 | ![Building the image using Dockerfile](./screenshots/building-test-nodejs-image.png) 129 | 130 | 8. Run the newly created docker image as container 131 | ``` 132 | docker run -d \ 133 | --publish 4000:4000 \ 134 | -e MYSQL_USER='root' \ 135 | -e MYSQL_PASSWORD='password' \ 136 | -e MYSQL_DATABASE='test' \ 137 | -e MYSQL_HOST='172.17.0.2' \ 138 | --link test-mysql-microservice:db \ 139 | --name=test-nodejs-microservice test-nodejs 140 | ``` 141 | ![Running the image using Dockerfile](./screenshots/running-test-nodejs-microservice-container.png) 142 | 143 | 9. Explaination of above command- 144 | * `-d` run in detach mode 145 | * `--publish` map the host port 4000 to the container port 4000 146 | * `-e` pass environment variables to nodejs app necessary to make mysql connection (check index.js file) 147 | * `--link test-mysql-microservice:db` link to the container named test-mysql-microservice and refer to it as db 148 | * `--name` naming our container as test-nodejs-microservice 149 | 150 | 10. How to know your MYSQL_HOST- 151 | Note that I am using `172.17.0.2` ip-address as MYSQL_HOST. This is the IpAddress of our test-mysql-microservice container. 152 | You must replace this value to your container's ipAddress. Use `docker inspect test-mysql-microservice | grep IPAddress` 153 | 154 | 155 | ### Testing our complete app 156 | 157 | If everything is good so far then congratulations :smile: You have a complete app running with two microservices. To test this you can use CURL command from your host machine 158 | 159 | 1. Get homepage of your app `curl -X GET localhost:4000` 160 | 161 | 2. Get list of all students from test database `curl -X POST 192.168.43.147:4000/get-students` 162 | Here 192.168.43.147 is my host IpAddress `ifconfig | grep inet` 163 | 164 | 3. Add a new student to your test db `curl --header "Content-Type: application/json" -d '{"rollNo": 1130360, "name": "Abhishek Goswami"}' -X POST localhost:4000/add-student` 165 | 166 | 4. Again fetch all students to see updated results `curl -X POST 192.168.43.147:4000/get-students` 167 | 168 | 5. Modify source code of nodejs app, build image, run container and test again. 169 | 170 | ### Queries/Comments 171 | 172 | You can contact me at varunon9@gmail.com or create github issues. 173 | -------------------------------------------------------------------------------- /nodejs-microservice/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-microservice", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.5", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", 10 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", 11 | "requires": { 12 | "mime-types": "~2.1.18", 13 | "negotiator": "0.6.1" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "bignumber.js": { 22 | "version": "4.0.4", 23 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.0.4.tgz", 24 | "integrity": "sha512-LDXpJKVzEx2/OqNbG9mXBNvHuiRL4PzHCGfnANHMJ+fv68Ads3exDVJeGDJws+AoNEuca93bU3q+S0woeUaCdg==" 25 | }, 26 | "body-parser": { 27 | "version": "1.18.3", 28 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", 29 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", 30 | "requires": { 31 | "bytes": "3.0.0", 32 | "content-type": "~1.0.4", 33 | "debug": "2.6.9", 34 | "depd": "~1.1.2", 35 | "http-errors": "~1.6.3", 36 | "iconv-lite": "0.4.23", 37 | "on-finished": "~2.3.0", 38 | "qs": "6.5.2", 39 | "raw-body": "2.3.3", 40 | "type-is": "~1.6.16" 41 | }, 42 | "dependencies": { 43 | "qs": { 44 | "version": "6.5.2", 45 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 46 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 47 | } 48 | } 49 | }, 50 | "bytes": { 51 | "version": "3.0.0", 52 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 53 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 54 | }, 55 | "content-disposition": { 56 | "version": "0.5.2", 57 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 58 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 59 | }, 60 | "content-type": { 61 | "version": "1.0.4", 62 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 63 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 64 | }, 65 | "cookie": { 66 | "version": "0.3.1", 67 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 68 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 69 | }, 70 | "cookie-signature": { 71 | "version": "1.0.6", 72 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 73 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 74 | }, 75 | "core-util-is": { 76 | "version": "1.0.2", 77 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 78 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 79 | }, 80 | "debug": { 81 | "version": "2.6.9", 82 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 83 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 84 | "requires": { 85 | "ms": "2.0.0" 86 | } 87 | }, 88 | "depd": { 89 | "version": "1.1.2", 90 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 91 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 92 | }, 93 | "destroy": { 94 | "version": "1.0.4", 95 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 96 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 97 | }, 98 | "ee-first": { 99 | "version": "1.1.1", 100 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 101 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 102 | }, 103 | "encodeurl": { 104 | "version": "1.0.2", 105 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 106 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 107 | }, 108 | "escape-html": { 109 | "version": "1.0.3", 110 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 111 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 112 | }, 113 | "etag": { 114 | "version": "1.8.1", 115 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 116 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 117 | }, 118 | "express": { 119 | "version": "4.16.3", 120 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", 121 | "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", 122 | "requires": { 123 | "accepts": "~1.3.5", 124 | "array-flatten": "1.1.1", 125 | "body-parser": "1.18.2", 126 | "content-disposition": "0.5.2", 127 | "content-type": "~1.0.4", 128 | "cookie": "0.3.1", 129 | "cookie-signature": "1.0.6", 130 | "debug": "2.6.9", 131 | "depd": "~1.1.2", 132 | "encodeurl": "~1.0.2", 133 | "escape-html": "~1.0.3", 134 | "etag": "~1.8.1", 135 | "finalhandler": "1.1.1", 136 | "fresh": "0.5.2", 137 | "merge-descriptors": "1.0.1", 138 | "methods": "~1.1.2", 139 | "on-finished": "~2.3.0", 140 | "parseurl": "~1.3.2", 141 | "path-to-regexp": "0.1.7", 142 | "proxy-addr": "~2.0.3", 143 | "qs": "6.5.1", 144 | "range-parser": "~1.2.0", 145 | "safe-buffer": "5.1.1", 146 | "send": "0.16.2", 147 | "serve-static": "1.13.2", 148 | "setprototypeof": "1.1.0", 149 | "statuses": "~1.4.0", 150 | "type-is": "~1.6.16", 151 | "utils-merge": "1.0.1", 152 | "vary": "~1.1.2" 153 | }, 154 | "dependencies": { 155 | "body-parser": { 156 | "version": "1.18.2", 157 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", 158 | "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", 159 | "requires": { 160 | "bytes": "3.0.0", 161 | "content-type": "~1.0.4", 162 | "debug": "2.6.9", 163 | "depd": "~1.1.1", 164 | "http-errors": "~1.6.2", 165 | "iconv-lite": "0.4.19", 166 | "on-finished": "~2.3.0", 167 | "qs": "6.5.1", 168 | "raw-body": "2.3.2", 169 | "type-is": "~1.6.15" 170 | } 171 | }, 172 | "iconv-lite": { 173 | "version": "0.4.19", 174 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 175 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 176 | }, 177 | "raw-body": { 178 | "version": "2.3.2", 179 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 180 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 181 | "requires": { 182 | "bytes": "3.0.0", 183 | "http-errors": "1.6.2", 184 | "iconv-lite": "0.4.19", 185 | "unpipe": "1.0.0" 186 | }, 187 | "dependencies": { 188 | "depd": { 189 | "version": "1.1.1", 190 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 191 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 192 | }, 193 | "http-errors": { 194 | "version": "1.6.2", 195 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 196 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 197 | "requires": { 198 | "depd": "1.1.1", 199 | "inherits": "2.0.3", 200 | "setprototypeof": "1.0.3", 201 | "statuses": ">= 1.3.1 < 2" 202 | } 203 | }, 204 | "setprototypeof": { 205 | "version": "1.0.3", 206 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 207 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 208 | } 209 | } 210 | } 211 | } 212 | }, 213 | "finalhandler": { 214 | "version": "1.1.1", 215 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", 216 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", 217 | "requires": { 218 | "debug": "2.6.9", 219 | "encodeurl": "~1.0.2", 220 | "escape-html": "~1.0.3", 221 | "on-finished": "~2.3.0", 222 | "parseurl": "~1.3.2", 223 | "statuses": "~1.4.0", 224 | "unpipe": "~1.0.0" 225 | } 226 | }, 227 | "forwarded": { 228 | "version": "0.1.2", 229 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 230 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 231 | }, 232 | "fresh": { 233 | "version": "0.5.2", 234 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 235 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 236 | }, 237 | "http-errors": { 238 | "version": "1.6.3", 239 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 240 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 241 | "requires": { 242 | "depd": "~1.1.2", 243 | "inherits": "2.0.3", 244 | "setprototypeof": "1.1.0", 245 | "statuses": ">= 1.4.0 < 2" 246 | } 247 | }, 248 | "iconv-lite": { 249 | "version": "0.4.23", 250 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 251 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 252 | "requires": { 253 | "safer-buffer": ">= 2.1.2 < 3" 254 | } 255 | }, 256 | "inherits": { 257 | "version": "2.0.3", 258 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 259 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 260 | }, 261 | "ipaddr.js": { 262 | "version": "1.6.0", 263 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", 264 | "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" 265 | }, 266 | "isarray": { 267 | "version": "1.0.0", 268 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 269 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 270 | }, 271 | "media-typer": { 272 | "version": "0.3.0", 273 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 274 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 275 | }, 276 | "merge-descriptors": { 277 | "version": "1.0.1", 278 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 279 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 280 | }, 281 | "methods": { 282 | "version": "1.1.2", 283 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 284 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 285 | }, 286 | "mime": { 287 | "version": "1.4.1", 288 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 289 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 290 | }, 291 | "mime-db": { 292 | "version": "1.33.0", 293 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", 294 | "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" 295 | }, 296 | "mime-types": { 297 | "version": "2.1.18", 298 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", 299 | "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", 300 | "requires": { 301 | "mime-db": "~1.33.0" 302 | } 303 | }, 304 | "ms": { 305 | "version": "2.0.0", 306 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 307 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 308 | }, 309 | "mysql": { 310 | "version": "2.15.0", 311 | "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.15.0.tgz", 312 | "integrity": "sha512-C7tjzWtbN5nzkLIV+E8Crnl9bFyc7d3XJcBAvHKEVkjrYjogz3llo22q6s/hw+UcsE4/844pDob9ac+3dVjQSA==", 313 | "requires": { 314 | "bignumber.js": "4.0.4", 315 | "readable-stream": "2.3.3", 316 | "safe-buffer": "5.1.1", 317 | "sqlstring": "2.3.0" 318 | } 319 | }, 320 | "negotiator": { 321 | "version": "0.6.1", 322 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 323 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 324 | }, 325 | "on-finished": { 326 | "version": "2.3.0", 327 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 328 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 329 | "requires": { 330 | "ee-first": "1.1.1" 331 | } 332 | }, 333 | "parseurl": { 334 | "version": "1.3.2", 335 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 336 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 337 | }, 338 | "path-to-regexp": { 339 | "version": "0.1.7", 340 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 341 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 342 | }, 343 | "process-nextick-args": { 344 | "version": "1.0.7", 345 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 346 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 347 | }, 348 | "proxy-addr": { 349 | "version": "2.0.3", 350 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", 351 | "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", 352 | "requires": { 353 | "forwarded": "~0.1.2", 354 | "ipaddr.js": "1.6.0" 355 | } 356 | }, 357 | "qs": { 358 | "version": "6.5.1", 359 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 360 | "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" 361 | }, 362 | "range-parser": { 363 | "version": "1.2.0", 364 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 365 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 366 | }, 367 | "raw-body": { 368 | "version": "2.3.3", 369 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", 370 | "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", 371 | "requires": { 372 | "bytes": "3.0.0", 373 | "http-errors": "1.6.3", 374 | "iconv-lite": "0.4.23", 375 | "unpipe": "1.0.0" 376 | } 377 | }, 378 | "readable-stream": { 379 | "version": "2.3.3", 380 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", 381 | "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", 382 | "requires": { 383 | "core-util-is": "~1.0.0", 384 | "inherits": "~2.0.3", 385 | "isarray": "~1.0.0", 386 | "process-nextick-args": "~1.0.6", 387 | "safe-buffer": "~5.1.1", 388 | "string_decoder": "~1.0.3", 389 | "util-deprecate": "~1.0.1" 390 | } 391 | }, 392 | "safe-buffer": { 393 | "version": "5.1.1", 394 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 395 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 396 | }, 397 | "safer-buffer": { 398 | "version": "2.1.2", 399 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 400 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 401 | }, 402 | "send": { 403 | "version": "0.16.2", 404 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", 405 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", 406 | "requires": { 407 | "debug": "2.6.9", 408 | "depd": "~1.1.2", 409 | "destroy": "~1.0.4", 410 | "encodeurl": "~1.0.2", 411 | "escape-html": "~1.0.3", 412 | "etag": "~1.8.1", 413 | "fresh": "0.5.2", 414 | "http-errors": "~1.6.2", 415 | "mime": "1.4.1", 416 | "ms": "2.0.0", 417 | "on-finished": "~2.3.0", 418 | "range-parser": "~1.2.0", 419 | "statuses": "~1.4.0" 420 | } 421 | }, 422 | "serve-static": { 423 | "version": "1.13.2", 424 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", 425 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", 426 | "requires": { 427 | "encodeurl": "~1.0.2", 428 | "escape-html": "~1.0.3", 429 | "parseurl": "~1.3.2", 430 | "send": "0.16.2" 431 | } 432 | }, 433 | "setprototypeof": { 434 | "version": "1.1.0", 435 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 436 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 437 | }, 438 | "sqlstring": { 439 | "version": "2.3.0", 440 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz", 441 | "integrity": "sha1-UluKT9Jtb3GqYegipsr5dtMa0qg=" 442 | }, 443 | "statuses": { 444 | "version": "1.4.0", 445 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 446 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 447 | }, 448 | "string_decoder": { 449 | "version": "1.0.3", 450 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 451 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 452 | "requires": { 453 | "safe-buffer": "~5.1.0" 454 | } 455 | }, 456 | "type-is": { 457 | "version": "1.6.16", 458 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", 459 | "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", 460 | "requires": { 461 | "media-typer": "0.3.0", 462 | "mime-types": "~2.1.18" 463 | } 464 | }, 465 | "unpipe": { 466 | "version": "1.0.0", 467 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 468 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 469 | }, 470 | "util-deprecate": { 471 | "version": "1.0.2", 472 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 473 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 474 | }, 475 | "utils-merge": { 476 | "version": "1.0.1", 477 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 478 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 479 | }, 480 | "vary": { 481 | "version": "1.1.2", 482 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 483 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 484 | } 485 | } 486 | } 487 | --------------------------------------------------------------------------------