diff --git a/nginx-nodejs-redis/README.md b/nginx-nodejs-redis/README.md new file mode 100644 index 0000000..545f21a --- /dev/null +++ b/nginx-nodejs-redis/README.md @@ -0,0 +1,122 @@ + +## Node.js application with Nginx proxy and Redis database + +Project structure: +``` +. +├── docker-compose.yml +├── nginx +│   ├── Dockerfile +│   └── nginx.conf +├── web +│   ├── Dockerfile +│   ├── package.json +│   └── server.js +├── web1 +│   ├── Dockerfile +│   ├── package.json +│   └── server.js +└── web2 + ├── Dockerfile + ├── package.json + └── server.js + +4 directories, 12 files +``` + +[_docker-compose.yml_](docker-compose.yml) +``` +version: '3.9' +services: + redis: + image: 'redis:alpine' + ports: + - '6379:6379' + web1: + restart: on-failure + build: ./web1 + ports: + - '81:5000' + web2: + restart: on-failure + build: ./web2 + ports: + - '82:5000' + nginx: + build: ./nginx + ports: + - '80:80' + depends_on: + - web1 + - web2 +``` +The compose file defines an application with four services `redis`, `web`, `web1` and `web2`. +When deploying the application, docker-compose maps port 80 of the web service container to port 80 of the host as specified in the file. + + +> ℹ️ **_INFO_** +> Redis runs on port 6379 by default. Make sure port 6379 on the host is not being used by another container, otherwise the port should be changed. + +## Deploy with docker-compose + +``` +$ docker-compose up -d +``` +``` +Creating nginx-nodejs-redis_redis_1 ... done +Creating nginx-nodejs-redis_web1_1 ... done +Creating nginx-nodejs-redis_web2_1 ... done +Creating nginx-nodejs-redis_nginx_1 ... done +``` + + +## Expected result + +Listing containers must show three containers running and the port mapping as below: + + +``` +docker-compose ps + Name Command State Ports +------------------------------------------------------------------------------------------ +nginx-nodejs-redis_nginx_1 /docker-entrypoint.sh ngin Up 0.0.0.0:80->80/tcp + ... +nginx-nodejs-redis_redis_1 docker-entrypoint.sh redis Up 0.0.0.0:6379->6379/tcp + ... +nginx-nodejs-redis_web1_1 docker-entrypoint.sh npm Up 0.0.0.0:81->5000/tcp + start +nginx-nodejs-redis_web2_1 docker-entrypoint.sh npm Up 0.0.0.0:82->5000/tcp + start +``` + +## Testing the app + +After the application starts, navigate to `http://localhost:80` in your web browser or run: + +``` +curl localhost:80 +curl localhost:80 +web1: Total number of visits is: 1 +``` + +``` +curl localhost:80 +web1: Total number of visits is: 2 +``` +``` +$ curl localhost:80 +web2: Total number of visits is: 3 +``` + +``` +$ curl localhost:80 +web2: Total number of visits is: 4 +``` + + +## Stop and remove the containers + +``` +$ docker-compose down +``` + diff --git a/nginx-nodejs-redis/docker-compose.yml b/nginx-nodejs-redis/docker-compose.yml new file mode 100644 index 0000000..c367ce5 --- /dev/null +++ b/nginx-nodejs-redis/docker-compose.yml @@ -0,0 +1,25 @@ +version: '3.9' +services: + redis: + image: 'redis:alpine' + ports: + - '6379:6379' + web1: + restart: on-failure + build: ./web1 + ports: + - '81:5000' + web2: + restart: on-failure + build: ./web2 + ports: + - '82:5000' + nginx: + build: ./nginx + ports: + - '80:80' + depends_on: + - web1 + - web2 + + diff --git a/nginx-nodejs-redis/nginx/Dockerfile b/nginx-nodejs-redis/nginx/Dockerfile new file mode 100644 index 0000000..5b3e0c4 --- /dev/null +++ b/nginx-nodejs-redis/nginx/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx +RUN rm /etc/nginx/conf.d/default.conf +COPY nginx.conf /etc/nginx/conf.d/default.conf diff --git a/nginx-nodejs-redis/nginx/nginx.conf b/nginx-nodejs-redis/nginx/nginx.conf new file mode 100644 index 0000000..83c222b --- /dev/null +++ b/nginx-nodejs-redis/nginx/nginx.conf @@ -0,0 +1,12 @@ +upstream loadbalancer { + server web1:5000; + server web2:5000; +} + +server { + listen 80; + server_name localhost; + location / { + proxy_pass http://loadbalancer; + } +} diff --git a/nginx-nodejs-redis/web/Dockerfile b/nginx-nodejs-redis/web/Dockerfile new file mode 100644 index 0000000..2d1d46c --- /dev/null +++ b/nginx-nodejs-redis/web/Dockerfile @@ -0,0 +1,9 @@ +FROM node:alpine + +WORKDIR /usr/src/app + +COPY ./package.json ./ +RUN npm install +COPY ./server.js ./ + +CMD ["npm","start"] diff --git a/nginx-nodejs-redis/web/package.json b/nginx-nodejs-redis/web/package.json new file mode 100644 index 0000000..c5565bf --- /dev/null +++ b/nginx-nodejs-redis/web/package.json @@ -0,0 +1,15 @@ +{ + "name": "web", + "version": "1.0.0", + "description": "Running Node.js and Express.js on Docker", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "^4.17.2", + "redis": "3.1.2" + }, + "author": "", + "license": "MIT" +} diff --git a/nginx-nodejs-redis/web/server.js b/nginx-nodejs-redis/web/server.js new file mode 100644 index 0000000..9061c10 --- /dev/null +++ b/nginx-nodejs-redis/web/server.js @@ -0,0 +1,23 @@ +const express = require('express'); +const redis = require('redis'); +const app = express(); +const redisClient = redis.createClient({ + host: 'redis', + port: 6379 +}); + +app.get('/', function(req, res) { + redisClient.get('numVisits', function(err, numVisits) { + numVisitsToDisplay = parseInt(numVisits) + 1; + if (isNaN(numVisitsToDisplay)) { + numVisitsToDisplay = 1; + } + res.send('Number of visits is: ' + numVisitsToDisplay); + numVisits++; + redisClient.set('numVisits', numVisits); + }); +}); + +app.listen(5000, function() { + console.log('Web application is listening on port 5000'); +}); diff --git a/nginx-nodejs-redis/web1/Dockerfile b/nginx-nodejs-redis/web1/Dockerfile new file mode 100644 index 0000000..d2b472f --- /dev/null +++ b/nginx-nodejs-redis/web1/Dockerfile @@ -0,0 +1,9 @@ +FROM node:alpine + +WORKDIR /usr/src/app + +COPY ./package*.json ./ +RUN npm install +COPY ./server.js ./ + +CMD ["npm","start"] diff --git a/nginx-nodejs-redis/web1/package.json b/nginx-nodejs-redis/web1/package.json new file mode 100644 index 0000000..dcb7bac --- /dev/null +++ b/nginx-nodejs-redis/web1/package.json @@ -0,0 +1,15 @@ +{ + "name": "web1", + "version": "1.0.0", + "description": "Running Node.js and Express.js on Docker", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "^4.17.2", + "redis": "3.1.2" + }, + "author": "", + "license": "MIT" +} diff --git a/nginx-nodejs-redis/web1/server.js b/nginx-nodejs-redis/web1/server.js new file mode 100644 index 0000000..7be500e --- /dev/null +++ b/nginx-nodejs-redis/web1/server.js @@ -0,0 +1,24 @@ +const express = require('express'); +const redis = require('redis'); +const app = express(); +const redisClient = redis.createClient({ + host: 'redis', + port: 6379 +}); + + +app.get('/', function(req, res) { + redisClient.get('numVisits', function(err, numVisits) { + numVisitsToDisplay = parseInt(numVisits) + 1; + if (isNaN(numVisitsToDisplay)) { + numVisitsToDisplay = 1; + } + res.send('web1: Total number of visits is: ' + numVisitsToDisplay); + numVisits++; + redisClient.set('numVisits', numVisits); + }); +}); + +app.listen(5000, function() { + console.log('Web app is listening on port 5000'); +}); diff --git a/nginx-nodejs-redis/web2/Dockerfile b/nginx-nodejs-redis/web2/Dockerfile new file mode 100644 index 0000000..2d1d46c --- /dev/null +++ b/nginx-nodejs-redis/web2/Dockerfile @@ -0,0 +1,9 @@ +FROM node:alpine + +WORKDIR /usr/src/app + +COPY ./package.json ./ +RUN npm install +COPY ./server.js ./ + +CMD ["npm","start"] diff --git a/nginx-nodejs-redis/web2/package.json b/nginx-nodejs-redis/web2/package.json new file mode 100644 index 0000000..51e85c5 --- /dev/null +++ b/nginx-nodejs-redis/web2/package.json @@ -0,0 +1,15 @@ +{ + "name": "web2", + "version": "1.0.0", + "description": "Running Node.js and Express.js on Docker", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "^4.17.2", + "redis": "3.1.2" + }, + "author": "", + "license": "MIT" +} diff --git a/nginx-nodejs-redis/web2/server.js b/nginx-nodejs-redis/web2/server.js new file mode 100644 index 0000000..36c4ce7 --- /dev/null +++ b/nginx-nodejs-redis/web2/server.js @@ -0,0 +1,24 @@ +const express = require('express'); +const redis = require('redis'); +const app = express(); +const redisClient = redis.createClient({ + host: 'redis', + port: 6379 +}); + + +app.get('/', function(req, res) { + redisClient.get('numVisits', function(err, numVisits) { + numVisitsToDisplay = parseInt(numVisits) + 1; + if (isNaN(numVisitsToDisplay)) { + numVisitsToDisplay = 1; + } + res.send('web2: Total number of visits is: ' + numVisitsToDisplay); + numVisits++; + redisClient.set('numVisits', numVisits); + }); +}); + +app.listen(5000, function() { + console.log('Web app is listening on port 5000'); +});