DevOps Docker Image === ![](https://i.imgur.com/hMQ3Eow.jpg) What we gonna Develop? --- > * We will be developing **Mean** App with angular 2 with automated code push, build, testing and Deploy by **Jenkins Tools** and **Docker**. > * At the end, will create it's **Docker** image. ### Git Hub Repository used: https://github.com/rohitCodeRed/angularCli https://github.com/rohitCodeRed/NodeServer https://github.com/rohitCodeRed/sabdkosh-devOps-image ### Static Web project link: https://ng-tabula.firebaseapp.com/ ## Introduction <i class="fa fa-file-text"></i> **DevOps** (a clipped compound of "development" and "operations") is a software engineering culture and practice that aims at unifying software development (Dev) and software operation (Ops). Basically It's an automatiom of end-to-end software delivery lifecycle. For more details (https://en.wikipedia.org/wiki/DevOps, https://www.versionone.com/devops-101/what-is-devops/). <i class="fa fa-file-text"></i> **Docker** It allows us to run applications inside containers. These containers in most cases communicate with each other. :::info Docker containers wrap a piece of software in a complete filesystem that contains everything needed to run: code, runtime, system tools, system libraries – anything that can be installed on a server. This guarantees that the software will always run the same, regardless of its environment. ::: For more details (https://www.docker.com/what-docker) <i class="fa fa-file-text"></i> **Docker Image** :::info An image is an inert, immutable, file that's essentially a snapshot of a container. Images are created with the build command, and they'll produce a container when started with run. Images are stored in a Docker registry such as registry.hub.docker.com. Because they can become quite large, images are designed to be composed of layers of other images, allowing a miminal amount of data to be sent when transferring images over the network. ::: <i class="fa fa-file-text"></i> **Jenkins** Jenkins is a Continuous Integration (CI) server or tool which is written in java. It provides Continuous Integration services for software development, which can be started via command line or web application server. For more details (https://vmokshagroup.com/blog/what-is-jenkins/) <i class="fa fa-file-text"></i> **MEAN App** :::info The term MEAN refers to a collection of JavaScript based technologies used to develop web applications. MEAN is an acronym for MongoDB, ExpressJS, AngularJS and Node.js. From client to server to database, MEAN is full stack JavaScript. ::: Mean App is App developed from all above technology. Please view source code on [GitHub](https://github.com/hackmdio/hackmd-io-issues/issues/new). **Table of Contents** [TOC] So Let's Start!! === ## Installing and Running Docker There are many ways of installing Docker, two of them are * Install using the repository * Manually Install from a package I tried both one, but faced error with repository option. So I installed manually. Please follow link before installation (https://docs.docker.com/install/linux/docker-ce/ubuntu/#upgrade-docker-ce). I installed **docker CE** for 64 bit linux OS with Ubuntu distro. ``` shell $ uname -a Linux rohit-comp 4.13.0-36-generic #40~16.04.1-Ubuntu SMP Fri Feb 16 23:25:58 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux $ cat /etc/os-release NAME="Linux Mint" VERSION="18.3 (Sylvia)" ID=linuxmint ID_LIKE=ubuntu PRETTY_NAME="Linux Mint 18.3" VERSION_ID="18.3" HOME_URL="http://www.linuxmint.com/" SUPPORT_URL="http://forums.linuxmint.com/" BUG_REPORT_URL="http://bugs.launchpad.net/linuxmint/" VERSION_CODENAME=sylvia UBUNTU_CODENAME=xenial ``` To check Docker Installation, ``` shell $ sudo docker info Containers: 1 Running: 0 Paused: 0 Stopped: 1 Images: 1 ... .. . ``` Docker install as a root privilages, to get rid of sudo follow link: https://docs.docker.com/install/linux/linux-postinstall/. ## Installing and Running Jenkin Image as Docker Container Go to jenkins website (https://jenkins.io/doc/book/getting-started/installing/) and find “Docker” section.All the options are briefly explained. ``` shell $ docker network create jenkins $ docker run --name jenkins-docker --rm --detach \ --privileged --network jenkins --network-alias docker \ --env DOCKER_TLS_CERTDIR=/certs \ --volume jenkins-docker-certs:/certs/client \ --volume jenkins-data:/var/jenkins_home \ --publish 2376:2376 docker:dind ``` Create Dockerfile with the following content: ``` FROM jenkins/jenkins:2.263.3-lts-jdk11 USER root RUN apt-get update && apt-get install -y apt-transport-https \ ca-certificates curl gnupg2 \ software-properties-common RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - RUN apt-key fingerprint 0EBFCD88 RUN add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/debian \ $(lsb_release -cs) stable" RUN apt-get update && apt-get install -y docker-ce-cli USER jenkins # RUN jenkins-plugin-cli --plugins blueocean:1.24.4 # blueocean is not required ``` Build a new docker image from this Dockerfile and assign the image a meaningful name, e.g. "sabdkosh-jenkins": ```shell $ docker build -t sabdkosh-jenkins . ``` Then run sabdkosh-jenkins image container ```shell $ docker run --name sabdkosh-jenkins-container --rm --detach \ --network jenkins --env DOCKER_HOST=tcp://docker:2376 \ --env DOCKER_CERT_PATH=/certs/client --env DOCKER_TLS_VERIFY=1 \ --publish 8080:8080 --publish 50000:50000 \ --volume jenkins-data:/var/jenkins_home \ --volume jenkins-docker-certs:/certs/client:ro \ sabdkosh-jenkins ``` :::info After Installation, I find jenkins is running on **http://localhost:8080**. :mega: First time it asking the password, which I get after running the below command: ```shell $ docker logs <containerID> ... .. Jenkins initial setup is required. An admin user has been created and a password generated. Please use the following password to proceed to installation: b7dfc43dad7f4ff58f3eadedd6ee1d97 This may also be found at: /var/jenkins_home/secrets/initialAdminPassword ... . ``` ::: Finally, I installed the suitable plugins. ``` shell $ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b92d3becccc6 sabdkosh-jenkins "/sbin/tini -- /usr/…" About an hour ago Up About an hour 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp sabdkosh-jenkins-container 194da4603b60 docker:dind "dockerd-entrypoint.…" About an hour ago Up About an hour 2375/tcp, 0.0.0.0:2376->2376/tcp jenkins-docker $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE sabdkosh-jenkins latest e8d46dc7be01 34 seconds ago 1.01GB docker dind d1a6345c23f3 3 days ago 257MB jenkins/jenkins 2.263.3-lts-jdk11 f50504bf2e45 10 days ago 681MB ``` ::: > * You can use more options: https://docs.docker.com/engine/reference/commandline/commit/. > * You can see all docker images in repository.json file at path: >**/var/lib/docker/image/repository.json** > * Also jenkin package at **/var/lib/docker/volume/jenkin-data**. ### Running hello-world build from jenkins Container After login into jenkins, let's create our own pipeline. :::info **Jenkins Pipeline** Jenkins Pipeline (or simply "Pipeline") is a suite of plugins which supports implementing and integrating continuous delivery pipelines into Jenkins. Jenkins Pipeline provides an extensible set of tools for modeling simple-to-complex delivery pipelines "as code". The definition of a Jenkins Pipeline is typically written into a text file (called a Jenkinsfile) which in turn is checked into a project’s source control repository. * For more details please refers: **https://jenkins.io/doc/pipeline/tour** ::: Steps: * **Go to "new items" in menu**. ![](https://i.imgur.com/9Vwj3L2.png) ![](https://i.imgur.com/SdAT8RC.png) * **After entering project name, select pipeline option**. * **Then you configure the project and at last write the script for running docker image**: ![](https://i.imgur.com/3MGqtWU.png) * **After above step dashboard look like**: ![](https://i.imgur.com/j6kdzjc.png) * **Then go to project and click the build now option from menu**: ![](https://i.imgur.com/8nFZl4R.png) * :tada: Hurray!!! finally we run the docker container from jenkins master conatiner . ![](https://i.imgur.com/uUbqzJh.png) ![](https://i.imgur.com/INXbrGw.png) :::info * Through **Open Blue Ocean** option, you can easily configure and set up multiple pipeline projects with so much interactive UI. :mega: * You can also pipeline with GIT, GITHUB,Bit Bucket repositories. for more details prefer: **https://jenkins.io/doc/book/blueocean/** ::: ## Installing and Running a MongoDB Server image through Docker I created a folder locally, under which DockerFile is saved. :::success **DockerFile** * A Dockerfile is a text configuration file written in a popular, human-readable Markup Language called YAML. * It is a step-by-step script of all the commands you need to run to assemble a Docker Image. * The docker build command processes this file generating a Docker Image in your Local Image Cache, which you can then start-up using the docker run command, or push to a permanent Image Repository. * for more details refer: https://codefresh.io/docker-tutorial/build-docker-image-dockerfiles/, https://docs.docker.com/engine/reference/builder/#usage ::: ```shell $ mkdir ~/dockerFiles/mongoDockerFile/ $ ls docker-entrypoint.sh Dockerfile ``` :point_right: I downloaded it from git repository:https://github.com/docker-library/mongo. **DockerFile** look like.. ```shell FROM ubuntu:xenial # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added RUN groupadd -r mongodb && useradd -r -g mongodb mongodb RUN apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ jq \ numactl \ && rm -rf /var/lib/apt/lists/* # grab gosu for easy step-down from root (https://github.com/tianon/gosu/releases) ENV GOSU_VERSION 1.10 # grab "js-yaml" for parsing mongod's YAML config files (https://github.com/nodeca/js-yaml/releases) ENV JSYAML_VERSION 3.10.0 RUN set -ex; \ \ apt-get update; \ apt-get install -y --no-install-recommends \ wget \ ; \ rm -rf /var/lib/apt/lists/*; \ \ dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ export GNUPGHOME="$(mktemp -d)"; \ gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ command -v gpgconf && gpgconf --kill all || :; \ rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc; \ chmod +x /usr/local/bin/gosu; \ .......... .... .. ``` :point_right: Building Mongodb Image steps . . . :fire: * **Run command docker < path >**: ```shell $ docker build -t mongo_image ~/dockerFiles/mongoDockerFile/ Sending build context to Docker daemon 29.18 kB Step 1/22 : FROM ubuntu:xenial xenial: Pulling from library/ubuntu 8ee29e426c26: Pull complete 6e83b260b73b: Pull complete e26b65fd1143: Pull complete 40dca07f8222: Pull complete b420ae9e10b3: Pull complete Digest: sha256:3097ac92b852f878f802c22a38f97b097b4084dbef82893ba453ba0297d76a6a Status: Downloaded newer image for ubuntu:xenial ---> 7aa3602ab41e ....... ......... ..... ---> 5182af174621 Removing intermediate container a993eac70d01 Step 17/22 : RUN mkdir -p /data/db /data/configdb && chown -R mongodb:mongodb /data/db /data/configdb ---> Running in 8f430a61c7a1 ---> f8416b437cd4 Removing intermediate container 8f430a61c7a1 Step 18/22 : VOLUME /data/db /data/configdb ---> Running in f70530166d9c ---> 6f7d4c1be4d4 Removing intermediate container f70530166d9c Step 19/22 : COPY docker-entrypoint.sh /usr/local/bin/ ---> f4dbc4ec208b Removing intermediate container e868262ee4a4 Step 20/22 : ENTRYPOINT docker-entrypoint.sh ---> Running in 398fd62574c3 ---> 2ecfb72fc501 Removing intermediate container 398fd62574c3 Step 21/22 : EXPOSE 27017 ---> Running in 6c90f7a5db9f ---> 6a138701af20 Removing intermediate container 6c90f7a5db9f Step 22/22 : CMD mongod ---> Running in e329ca553521 ---> 6155456a21b8 Removing intermediate container e329ca553521 Successfully built 6155456a21b8 $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE mongo_image latest 6155456a21b8 11 seconds ago 379 MB ubuntu xenial 7aa3602ab41e 11 days ago 115 MB master_jenkins latest b8a9e8c5ebe3 2 weeks ago 436 MB jenkinsci/blueocean latest f04e14ab531d 3 weeks ago 433 MB hello-world latest e38bc07ac18e 3 months ago 1.85 kB ``` * **Running the Mongo image**: ```shell $ docker run --name mongo_container -p 27017:27017 mongo_image 2018-08-07T16:14:46.306+0000 I CONTROL [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none' 2018-08-07T16:14:46.311+0000 I CONTROL [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=0b26e5b03843 2018-08-07T16:14:47.677+0000 I CONTROL [initandlisten] 2018-08-07T16:14:47.928+0000 I STORAGE [initandlisten] createCollection: local.startup_log with generated UUID: d846bf70-343c-4313-9407-9af118793080 2018-08-07T16:14:48.156+0000 I FTDC [initandlisten] Initializing full-time diagnostic data capture with directory '/data/db/diagnostic.data' 2018-08-07T16:14:48.158+0000 I STORAGE [LogicalSessionCacheRefresh] createCollection: config.system.sessions with generated UUID: e5da2512-ec6d-492e-a358-10ed70a2d2a0 2018-08-07T16:14:48.158+0000 I NETWORK [initandlisten] waiting for connections on port 27017 2018-08-07T16:14:48.628+0000 I INDEX [LogicalSessionCacheRefresh] build index on: config.system.sessions properties: { v: 2, key: { lastUse: 1 }, name: "lsidTTLIndex", ns: "config.system.sessions", expireAfterSeconds: 1800 } 2018-08-07T16:14:48.628+0000 I INDEX [LogicalSessionCacheRefresh] building index using bulk method; build may temporarily use up to 500 megabytes of RAM 2018-08-07T16:14:48.630+0000 I INDEX [LogicalSessionCacheRefresh] build index done. scanned 0 total records. 0 secs 2018-08-07T16:14:48.631+0000 I COMMAND [LogicalSessionCacheRefresh] command config.$cmd command: createIndexes { createIndexes: "system.sessions", indexes: [ { key: { lastUse: 1 }, name: "lsidTTLIndex", expireAfterSeconds: 1800 } ], $db: "config" } numYields:0 reslen:114 locks:{ Global: { acquireCount: { r: 1, w: 1 } }, Database: { acquireCount: { W: 1 } }, Collection: { acquireCount: { w: 1 } } } protocol:op_msg 472ms 2018-08-07T16:16:04.639+0000 I CONTROL [signalProcessingThread] got signal 15 (Terminated), will terminate after current cmd ends 2018-08-07T16:16:04.639+0000 I NETWORK [signalProcessingThread] shutdown: going to close listening sockets... 2018-08-07T16:16:04.639+0000 I NETWORK [signalProcessingThread] removing socket file: /tmp/mongodb-27017.sock 2018-08-07T16:16:04.639+0000 I CONTROL [signalProcessingThread] Shutting down free monitoring 2018-08-07T16:16:04.639+0000 I FTDC [signalProcessingThread] Shutting down full-time diagnostic data capture 2018-08-07T16:16:04.642+0000 I STORAGE [signalProcessingThread] WiredTigerKVEngine shutting down 2018-08-07T16:16:04.947+0000 I STORAGE [signalProcessingThread] shutdown: removing fs lock... 2018-08-07T16:16:04.947+0000 I CONTROL [signalProcessingThread] now exiting ``` :::info For backing up **MongoDB** data and also auto removal of created container, Use::mega: ```shell $ docker run --rm --name mongo_container -p 27017:27017 -v mongoData:/data/db mongo_image ``` "--rm" for auto removal "-v mongoData:/data/db" Creates a mount point within the Container linking it back to file systems accessible by the Docker Host ::: ## Running a Node server For running a server, I choose expressJs frame work: https://expressjs.com/. **Prerequisite** * npm * node that's it, and you are ready! Steps are very easy, also it is well documented. I have already my expressjs project in github repository. :::success :point_right: link: (https://github.com/rohitCodeRed/NodeServer) ::: ```shell $ node -v v14.15.4 $ npm -v 6.14.11 ``` **Project file structure** ![](https://i.imgur.com/qbL0hUS.png) Let discuss about folder: * There are three folder in **app** folder. * **api** folder contains all the external apis with token based authentication, like post, get apis for creating, deleting users. * **model** folder contains all the mongo db collections schemas. * **services** folder contains all the services or functions required by **api** folder. **Start the server** ```shell $ node index.js (node:14601) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html Example app listening on port: 3001 failed to connect to server [localhost:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017] ``` Server is started on port 3001, By hitting http://localhost:3001, web page look like: ![](https://i.imgur.com/7XNeEHD.png) ![](https://i.imgur.com/c2cbpEM.png) ![](https://i.imgur.com/h8XiMHl.png) :::info Above, it's all about basic static server info are showing with help of **npm** package: **systeminformation** ::mega: ::: ### Running a Node server image through Docker Let's create a Dockerfile for node app. **Docker** file look's like: ```Dockerfile FROM node:14.15.4 RUN mkdir -p /usr/src/app COPY . /usr/src/app/ WORKDIR /usr/src/app RUN ls -al RUN npm install EXPOSE 3001 CMD ["node", "index.js"] ``` * All Code of node app are stored in ~/DevsOpsImage/nodeSrever directory. Now built it.. ```shell $ docker build -t node_image ~/DevsOpsImage/nodeServer/ Sending build context to Docker daemon 29.58 MB Step 1/6 : FROM node:14.15.4 8: Pulling from library/node Digest: sha256:3422df4f7532b26b55275ad7b6dc17ec35f77192b04ce22e62e43541f3d28eb3 Status: Downloaded newer image for node:14.15.4 ---> 8198006b2b57 Step 2/6 : WORKDIR /node_app ---> b1a3bb04379c Removing intermediate container c2b630ad766c Step 3/6 : COPY . /node_app ---> 68caaf68d07b Removing intermediate container ea0956e26760 Step 4/6 : RUN npm install ---> Running in e07fa77acafa up to date in 1.463s ---> cf4816dcd3d9 Removing intermediate container e07fa77acafa Step 5/6 : CMD node index.js ---> Running in 2c39e44bfbea ---> 29174456cced Removing intermediate container 2c39e44bfbea Step 6/6 : EXPOSE 3001 ---> Running in 070e3f29ab1e ---> 425fc0606b38 Removing intermediate container 070e3f29ab1e Successfully built 425fc0606b38 ``` * Node app docker image is succesfully built, let's run it ```shell $ docker run --rm --name node_container -p 3001:3001 node_image (node:7) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html Example app listening on port: 3001 failed to connect to server [localhost:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017] ``` Now it's running on http://localhost:3001. :tada: ### Linking MongoDB and Node servers Docker Image Containers * Let's run our **mongoDB server image** ```shell $ docker run --rm --name mongo_container -p 27017:27017 -v mongoData:/data/db mongo_image 2018-09-10T15:09:36.188+0000 I CONTROL [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none' 2018-09-10T15:09:36.430+0000 I CONTROL [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=24871290d581 2018-09-10T15:09:36.430+0000 I CONTROL [initandlisten] db version v4.0.0 2018-09-10T15:09:36.430+0000 I CONTROL [initandlisten] git version: 3b07af3d4f471ae89e8186d33bbb1d5259597d51 2018-09-10T15:09:36.430+0000 I CONTROL [initandlisten] OpenSSL version: OpenSSL 1.0.2g 1 Mar 2016 2018-09-10T15:09:36.430+0000 I CONTROL [initandlisten] allocator: tcmalloc 2018-09-10T15:09:36.430+0000 I CONTROL [initandlisten] modules: none 2018-09-10T15:09:36.430+0000 I CONTROL [initandlisten] options: { net: { bindIpAll: true } } 2018-09-10T15:09:37.761+0000 I STORAGE [initandlisten] WiredTiger message [1536592177:761386][1:0x7f301685ba00], txn-recover: Recovering log 2 through 2 2018-09-10T15:09:38.599+0000 I FTDC [initandlisten] Initializing full-time diagnostic data capture with directory '/data/db/diagnostic.data' 2018-09-10T15:09:38.650+0000 I NETWORK [initandlisten] waiting for connections on port 27017 ``` * Then run our **Node server image**, before running node_app image we have to link with mongo_container ```shell $ docker run --rm --name node_container -p 3001:3001 --link=mongo_container:database node_image (node:7) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html Example app listening on port: 3001 **-----------MongoDB connection established------------** DB: angularChart Host: database Port: 27017 ``` * Now we clearly see that mongoDB connection is established. <i class="fa fa-eye fa-fw"></i> :::info I tried command to see the host information in node_container after linking with mongo_container `docker exec -it node_container cat /etc/hosts` `Output:` ```shell 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 database 17b74cacae30 mongo_container ``` ::: ### Requesting REST api of Node Server ( Only work, if mongoDB is connected ) **1. Register API** :::success * Url: "http://localhost:3001/api/apiAcess/register" * Method: POST * **Description**: `It register the user through which other user will created ,updated and deleted.` * **Request**: `curl -X POST \ http://localhost:3001/api/apiAcess/register \ -H 'cache-control: no-cache' \ -H 'content-type: application/json' \ -H 'postman-token: d2d1eec7-e2e5-a1b2-eb18-c69fa39c1fc0' \ -d '{ "username":"rohit1@amdocs.com", "password":"rohit123" }'` * **Response**: `{ "registered": true, "data": { "username": "rohit1@amdocs.com", "onCreated": "2018-09-14T15:07:59.345Z" } }` ::: **2. Acess token Api** :::success * Url: "http://localhost:3001/api/apiAcess/get_token" * Method: POST * **Description**: `It used to get JWT Token for accessing other users apis.` * **Request**: `curl -X POST \ http://localhost:3001/api/apiAcess/get_token \ -H 'cache-control: no-cache' \ -H 'content-type: application/json' \ -H 'postman-token: a19e348e-5bc1-0d9d-a66d-1363d8b42076' \ -d '{ "username":"rohit1@amdocs.com", "password":"rohit123" }'` * **Response**: `{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjQ4ZmNlNzg0Yjc1MmMzYjk3ZjM2ODM4ZTA4ZjM1OWY2IiwiaWF0IjoxNTM2OTM5MTc4LCJleHAiOjE1Mzc1NDM5Nzh9.UetQlScOaPn4fI-1cNB0GPSkbT85Yg_szMdBELZTNS8" }` ::: **3. Create New Users by registered JWT Token api** :::success * Url: "http://localhost:3001/api/user/create" * Method: POST * **Description**: `It create a new user by bearer token of registered token.` * **Request**: `curl -X POST \ http://localhost:3001/api/user/create \ -H 'authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjQ4ZmNlNzg0Yjc1MmMzYjk3ZjM2ODM4ZTA4ZjM1OWY2IiwiaWF0IjoxNTM2OTM5MTc4LCJleHAiOjE1Mzc1NDM5Nzh9.UetQlScOaPn4fI-1cNB0GPSkbT85Yg_szMdBELZTNS8' \ -H 'cache-control: no-cache' \ -H 'content-type: application/json' \ -H 'postman-token: c0160533-ca62-1a7c-9ea3-e8900d830557' \ -d '{ "nickname":"rohit2", "username":"rohit2@gmailcom", "password":"rohit123" }'` * **Response**: `{ "_id": "5b9bfe6df1eb9f1ab13bd0c8", "username": "rohit2@gmailcom", "nickname": "rohit2", "onCreated": "2018-09-14T18:31:09.054Z", "createdBy": "5b9bf92a657c401758c2ec80" }` ::: **4. Update User by Id with registered JWT Token api** :::success * Url: "http://localhost:3001/api/user/update/:id" * hitting Url: "http://localhost:3001/api/user/update/5b9bfe6df1eb9f1ab13bd0c8" * Method: PUT * **Description**: `It update a user nickname from rohit2 to rocky with bearer token of registered token.` * **Request**: ` curl -X PUT \ http://localhost:3001/api/user/update/5b9bfe6df1eb9f1ab13bd0c8 \ -H 'authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjViOWJmOTJhNjU3YzQwMTc1OGMyZWM4MCIsImlhdCI6MTUzNjk0ODcyNiwiZXhwIjoxNTM3NTUzNTI2fQ.tMbw0_ZCcead6MTo3b6jLSTMgYJ6rU1e_06heg1u28g' \ -H 'cache-control: no-cache' \ -H 'content-type: application/json' \ -H 'postman-token: 345ee8cd-06be-4ebc-ebf9-a48177524091' \ -d '{ "nickname":"roky" }' ` * **Response**: `{ "username": "rohit2@gmailcom", "nickname": "roky", "onCreated": "2018-09-14T18:31:09.054Z", "createdBy": "5b9bf92a657c401758c2ec80" }` ::: **5. Delete User by Id with registered JWT Token api** :::success * Url: "http://localhost:3001/api/user/delete/:id" * hitting Url: "http://localhost:3001/api/user/delete/5b9bfe6df1eb9f1ab13bd0c8" * Method: PUT * **Description**: `It delete a user by Id with bearer token of registered token.` * **Request**: `curl -X DELETE \ http://localhost:3001/api/user/delete/5b9bfe6df1eb9f1ab13bd0c8 \ -H 'authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjViOWJmOTJhNjU3YzQwMTc1OGMyZWM4MCIsImlhdCI6MTUzNjk0ODcyNiwiZXhwIjoxNTM3NTUzNTI2fQ.tMbw0_ZCcead6MTo3b6jLSTMgYJ6rU1e_06heg1u28g' \ -H 'cache-control: no-cache' \ -H 'content-type: application/json' \ -H 'postman-token: 20a060fc-a200-5b28-5c4a-06e4959cf8b3'` * **Response**: `{ "deleted": true, "data": { "n": 1, "ok": 1 } }` ::: ## Running an Angular app For an angular app, I use angular framework: https://angular.io/ **Prequisite** * npm * node **Steps** Install angular cli. :::info npm install -g @angular/cli ::: Create angular app. :::info ng new my-app ::: That's it and you ready to go. I have already my angular project in github repository. :::success :point_right: link: (https://github.com/rohitCodeRed/angularCli) ::: **Project file structure** ![](https://i.imgur.com/20CIOib.png) **Start the server** ```shell $ ng serve ** NG Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ ** Date: 2018-10-13T15:44:14.248Z Hash: d975bc6c74ccb6d0a321 Time: 29998ms chunk {inline} inline.bundle.js (inline) 3.85 kB [entry] [rendered] chunk {main} main.bundle.js (main) 713 kB [initial] [rendered] chunk {polyfills} polyfills.bundle.js (polyfills) 604 kB [initial] [rendered] chunk {scripts} scripts.bundle.js (scripts) 86.9 kB [initial] [rendered] chunk {styles} styles.bundle.js (styles) 588 kB [initial] [rendered] chunk {vendor} vendor.bundle.js (vendor) 22.2 MB [initial] [rendered] webpack: Compiled successfully. ``` Now the angular app is running on http://localhost:4200. I also deploy it on firebase cloud: https://firebase.google.com/ **Hosting link** :- :::info :point_right: https://ng-tabula.firebaseapp.com/ ::: Angular app look like: ![](https://i.imgur.com/LAyWbwg.png) ![](https://i.imgur.com/gsfxOG6.png) ![](https://i.imgur.com/BbOdfFd.png) ![](https://i.imgur.com/a0njljc.png) ### Running an Angular app image through Docker **Dockerfile Creation** *Dockerfile for angular app* ```Dockerfile FROM nginx COPY nginx.conf /etc/nginx/conf.d/default.conf COPY dist/angularCli/ /usr/share/nginx/html ``` As you can see we are copying all the files from our dist folder and we are also replacing the Nginx configuration with our own custom configuration (like the one below) Ngnix sample configuration server { listen 80; location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html =404; } } Assumption here is to already you have run the **ng build --prod**. **Building a Docker Image of angular app** After creation of Dockerfile, let's create it's image * In source directory, run the command ```shell $ ng build $ docker build -t angular_app_image . ``` **Running a Docker Image of angular app** To run the angular app image, run command ```shell $ docker run --rm --name angular_app_container -p 4200:80 angular_app_image ``` * Actually here -p specifies the port container:host mapping. In which our host machine (angular app) is listening port 80. Now it's running on http://localhost:4200. :tada: ### Linking Node server and Angular app Image Containers * Let's run our **Node server image** ```shell $ docker run --rm --name node_server_container -p 3001:3001 node_image (node:6) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect. Example app listening on port: 3001 ``` * Then run our **Angular app image**. While running angular_app_image image, we have to link with node_server_container. ```shell $ docker run --rm --name angular_app_container -p 4200:80 --link=node_server_container angular_app_image_test 172.17.0.1 - - [24/Mar/2019:12:54:13 +0000] "GET / HTTP/1.1" 200 711 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36" "-" 172.17.0.1 - - [24/Mar/2019:12:54:13 +0000] "GET /polyfills.bundle.js HTTP/1.1" 200 221728 "http://localhost:4200/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36" "-" 172.17.0.1 - - [24/Mar/2019:12:54:13 +0000] "GET /styles.bundle.js HTTP/1.1" 200 221328 "http://localhost:4200/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36" "-" 172.17.0.1 - - [24/Mar/2019:12:54:13 +0000] "GET /inline.bundle.js HTTP/1.1" 200 3887 "http://localhost:4200/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36" "-" 172.17.0.1 - - [24/Mar/2019:12:54:13 +0000] "GET /scripts.bundle.js HTTP/1.1" 200 86972 "http://localhost:4200/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36" "-" 172.17.0.1 - - [24/Mar/2019:12:54:13 +0000] "GET /main.bundle.js HTTP/1.1" 200 285438 "http://localhost:4200/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36" "-" 172.17.0.1 - - [24/Mar/2019:12:54:13 +0000] "GET /vendor.bundle.js HTTP/1.1" 200 8132087 "http://localhost:4200/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36" "-" ``` * Now the linking between angular_app_container and node_server_container is established . <i class="fa fa-eye fa-fw"></i> :::info I tried command to see the host information in angular_app_container after linking with node_server_container `docker exec -it angular_app_container cat /etc/hosts` `Output:` ```shell 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 node_server_container 2cc6e57181d8 172.17.0.3 d51fc67de038 ``` ::: Now both node server (http://localhost:3001) and angular app (http://localhost:4200) is running and linked. :tada: ## Build, Run and link all three Images From scratch Right now, we have both **Angular** and **Node** project are in **Git hub**. Let's pull both project and build it's image * **angular_app_image** ```shell $ git clone https://github.com/rohitCodeRed/angularCli.git $ cd angularCli $ npm install $ ng build $ docker build -t angular_app_image . ``` * **node_app_image** ```shell $ git clone https://github.com/rohitCodeRed/NodeServer.git $ cd NodeServer $ npm install $ docker build -t node_app_image . ``` * **mongo** For **mongo** image, we can directly pull from docker official page. ```shell $ docker pull mongo ``` Now we have all three images available at our local, let's create and run **docker-compose.yml** file. * Please install**docker-compose** before running. ``` services: node_app: container_name: node_app restart: always image: node_app_image ports: - "3001:3001" links: - mongo:database mongo: container_name: mongo image: mongo volumes: - ./data:/data/db ports: - "27017:27017" angular_app: container_name: angular_app restart: always image: angular_app_image ports: - "4200:80" links: - node_app ``` Let run the .yml file. ```shell $ docker-compose up ``` This above command will show all running container logs in one terminal. After that, Angular app will run on http://localhost:4200 and Node app will run on http://localhost:3001. ## Build, Run AngularCli and NodeServer Project with Jenkins Docker Image * After running jenkins with docker, got UI at http://localhost:8080 ![](https://i.imgur.com/74hx8Vy.png) * Created two new jobs **AngularCli_Project** and **NodeServer_Project** * Attach webhook in their git hub repository: **AngularCli_Project** : https://github.com/rohitCodeRed/angularCli.git **NodeServer_Project** : https://github.com/rohitCodeRed/NodeServer.git Like this in **Git Hub**: ![](https://i.imgur.com/UuWnxnD.png) * I used ngrok(https://ngrok.com/) software to make localhost:8080 online. ### Jenkinsfile in NodeServer project ```shell pipeline { agent { docker { image 'node:14.15.4' args '-p 3001:3001' } } environment { CI = 'true' } stages { stage('Build') { steps { sh 'npm install' } } stage('Deliver') { steps { sh './jenkins/scripts/deliver.sh' input message: 'Finished using the web site? (Click "Proceed" to continue)' sh './jenkins/scripts/kill.sh' } } } } ``` * Please refer to https://www.jenkins.io/doc/tutorials/build-a-node-js-and-react-app-with-npm/ * After any code push to master branch, it will trigger jenkins pipeline job **NodeServer_Project**. Screenshots are: ![](https://i.imgur.com/AFyMI4F.png) ![](https://i.imgur.com/6g1Q20A.png) ![](https://i.imgur.com/Qyk7tM9.png) ### Jekinsfile in angularCli project ```shell pipeline { agent { docker { image 'node:14.15.4' args '-p 4200:4200' } } environment { CI = 'true' } stages { stage('Build') { steps { sh 'npm install' sh 'npx -p @angular/cli@11.1.0 ng --help' sh 'npx -p @angular/cli@11.1.0 ng build' } } stage('Deliver') { steps { sh './jenkins/scripts/deliver.sh' input message: 'Finished using the web site? (Click "Proceed" to continue)' sh './jenkins/scripts/kill.sh' } } } } ``` * It uses docker image **node:14.15.4** to build and run AngularCli project. * After any code push to master branch, it will trigger jenkins pipeline job **AngularCli_Project**. Screenshots are: ![](https://i.imgur.com/AF65b8B.png) ![](https://i.imgur.com/HEdYLXA.png) ![](https://i.imgur.com/1NSvimG.png) ### Final Job View ![](https://i.imgur.com/Dv81QVJ.png) * All images regarding jenkins are pushed to docker hub repositories: 1. **docker0605/sabdkosh-jenkins-image** (https://hub.docker.com/r/docker0605/sabdkosh-jenkins-image) 2. **docker0605/sabdkosh-docker-dind** (https://hub.docker.com/r/docker0605/sabdkosh-docker-dind) ## Deployment Scripts Script which build and run docker images of mongoDB, nodeJs and angular project in one go. **Required Softaware installed** 1. *Docker* 2. *Node* 3. *Git* **Steps**: * Clone the git project: https://github.com/rohitCodeRed/sabdkosh-devOps-image.git ```shell $ git clone https://github.com/rohitCodeRed/sabdkosh-devOps-image.git ``` * Go to directory sabdkosh-devOps-image/ ```shell $ cd sabdkosh-devOps-image/ ``` * Run the deploymentScript.sh script ```shell $ sh deploymentScript.sh ``` Now above script automatically clone the project , build it and run it on local server. **Results** * **Node** project will run on http://localhost:3001 * **Angular** project will run on http://localhost:4200 * **MongoDb** will run on mongo://database:27017 ![Minion](https://octodex.github.com/images/minion.png =200x200) #### Thank you *[HTML]: Hyper Text Markup Language