1 00:00:00,000 --> 00:00:08,952 [Intro music] 2 00:00:08,952 --> 00:00:10,280 Hello and welcome to this demo. 3 00:00:10,290 --> 00:00:13,850 In this demo, we're going to look at the example-voting-app. 4 00:00:13,860 --> 00:00:18,485 The example-voting-app is available in GitHub under the dockersamples 5 00:00:18,485 --> 00:00:23,581 repository, and it is available at example-voting-app. 6 00:00:23,581 --> 00:00:26,240 I will add a link to this in the resources section. 7 00:00:26,360 --> 00:00:30,230 In this demo, we're going to look at the architecture of 8 00:00:30,240 --> 00:00:33,049 this. We're going to look at the source code a little bit, 9 00:00:33,259 --> 00:00:37,430 understand how it's put together, and we will try and deploy 10 00:00:37,460 --> 00:00:39,800 this application using Docker. 11 00:00:39,950 --> 00:00:44,660 But to start with, we're just going to deposit the application 12 00:00:44,670 --> 00:00:47,480 with docker run just to make it really simple. 13 00:00:47,600 --> 00:00:52,370 And then in the next demo, we'll try to use Docker Compose, 14 00:00:52,490 --> 00:00:55,970 and going forward, we'll use Docker stack and services to 15 00:00:56,570 --> 00:00:58,640 deploy it on Swarm. 16 00:00:58,970 --> 00:01:04,069 So as a first step, let's try and just understand the application. 17 00:01:04,340 --> 00:01:08,840 So the source code is available on GitHub, and you can see 18 00:01:08,850 --> 00:01:10,970 basic documentation here. 19 00:01:11,240 --> 00:01:14,300 If you look at the architecture, as we discussed in the lecture, 20 00:01:14,310 --> 00:01:17,270 you have a voting-app which is based in Python, and then 21 00:01:17,280 --> 00:01:19,880 you have a redis messaging system. 22 00:01:20,410 --> 00:01:24,920 The vote is cast, and it goes to the worker, which is based 23 00:01:24,920 --> 00:01:29,570 on .NET, and then the vote is updated in a Postgres database, 24 00:01:29,580 --> 00:01:33,440 and then finally, the result is displayed in a Node.js based 25 00:01:33,800 --> 00:01:35,540 result web application. 26 00:01:36,140 --> 00:01:39,830 Out of these two of the components are Redis and Postgres, 27 00:01:39,840 --> 00:01:41,420 so we don't have to worry about that. 28 00:01:41,430 --> 00:01:46,670 The three other components are the applications that we developed. 29 00:01:46,700 --> 00:01:50,300 So there are three folders in this code repository. 30 00:01:50,300 --> 00:01:52,300 [No audio] 31 00:01:52,305 --> 00:01:54,940 We'll first look at the voting-app, so if you click on the 32 00:01:54,950 --> 00:01:58,900 vote directory, you will be able to see the source code of 33 00:01:58,910 --> 00:02:00,790 it. And it's a Python based application. 34 00:02:00,800 --> 00:02:04,810 So you have the app.py with the Python code in it. 35 00:02:05,260 --> 00:02:08,080 If you open the Python code, it's a flask based application. 36 00:02:08,110 --> 00:02:09,639 It's a very simple application. 37 00:02:10,720 --> 00:02:14,050 It has a post and a get request. 38 00:02:14,410 --> 00:02:18,400 The GET request sent an index.html which shows the actual 39 00:02:18,820 --> 00:02:21,460 web page where a user can cast a vote. 40 00:02:21,730 --> 00:02:27,610 And when the user cast a vote, it comes to this POST section, 41 00:02:27,640 --> 00:02:32,380 and that is where it establishes connectivity to Redis and 42 00:02:33,790 --> 00:02:38,630 tries to store the vote information in Redis. 43 00:02:39,290 --> 00:02:43,670 So that's all that this particular voting-application is. 44 00:02:43,790 --> 00:02:48,770 And one thing to take note here is the host that it tries 45 00:02:48,780 --> 00:02:52,850 to, it tries to connect to a host named redis. 46 00:02:52,860 --> 00:02:56,180 Okay, now, alongside the code, we also have the Dockerfile, 47 00:02:56,760 --> 00:03:01,980 so it creates it from a python :2.7-alpine image and then 48 00:03:01,990 --> 00:03:06,660 set the working directory to app, installs the Python requirements. 49 00:03:06,660 --> 00:03:09,383 [No audio] 50 00:03:09,421 --> 00:03:13,570 The next step is where it copies the application code into 51 00:03:13,580 --> 00:03:18,310 the app folder, and finally the Entrypoint for the application. 52 00:03:18,850 --> 00:03:21,370 Next, we will take a look at the worker. 53 00:03:21,720 --> 00:03:25,920 So go to the worker folder, and the source code of the application 54 00:03:25,930 --> 00:03:32,082 is under the main/java/worker folder, and there is a Worker.java. 55 00:03:32,082 --> 00:03:35,790 If you look at this code, this is .NET based application. 56 00:03:35,800 --> 00:03:39,750 So at the top it tries to connect to the Redis and the Postgres 57 00:03:39,760 --> 00:03:45,180 database. And there's a while loop where it waits for the 58 00:03:45,190 --> 00:03:46,320 votes from redis. 59 00:03:46,500 --> 00:03:49,770 And whenever a vote is cast and it's available in redis, 60 00:03:49,780 --> 00:03:54,690 it takes that vote and updates the table in the Postgres 61 00:03:54,700 --> 00:03:57,600 database. If you're interested, go through and take a look 62 00:03:57,610 --> 00:03:58,770 at the remainder of the code. 63 00:04:00,090 --> 00:04:01,800 We will then look at the Dockerfile. 64 00:04:01,810 --> 00:04:07,340 So the Dockerfile is based on Microsoft dotnet SDK, and that 65 00:04:07,350 --> 00:04:10,430 is where it adds the source code of the application to the 66 00:04:10,440 --> 00:04:14,540 worker folder and finally updates the command required to 67 00:04:15,170 --> 00:04:16,265 start the worker. 68 00:04:17,160 --> 00:04:22,914 Next, we will look at the result-app, which is based in Node.js. 69 00:04:23,070 --> 00:04:27,750 So that is under the result folder and open the server.js. 70 00:04:27,870 --> 00:04:32,388 This is an express based server, and you can see the source code for that. 71 00:04:32,580 --> 00:04:35,640 And all this does is it establishes a connectivity to the 72 00:04:35,650 --> 00:04:36,630 Postgres database. 73 00:04:36,640 --> 00:04:41,400 And as you can see, the Postgres database, that host that 74 00:04:41,410 --> 00:04:45,940 tries to connect to is db. So that's the host name that it tries 75 00:04:45,950 --> 00:04:49,630 to connect to, and then it reads the database and reads the 76 00:04:49,640 --> 00:04:54,280 values from the database and displays that on the UI. 77 00:04:54,280 --> 00:04:57,259 [No audio] 78 00:04:57,259 --> 00:05:00,250 And if you look at the Dockerfile for that, it starts from 79 00:05:00,260 --> 00:05:06,790 the Docker image, starts from a Node.js slim image, and then 80 00:05:06,800 --> 00:05:10,630 adds the package.json, which has the dependencies, runs npm 81 00:05:10,630 --> 00:05:14,740 install to install those dependencies, copies the source code 82 00:05:14,740 --> 00:05:19,630 over, and finally specifies the node server.js command that 83 00:05:19,640 --> 00:05:22,330 is to be run when the application starts. 84 00:05:22,690 --> 00:05:26,620 And then there are also, in the source code repository 85 00:05:26,630 --> 00:05:29,440 there are also some docker-compose and docker-stack files. 86 00:05:29,450 --> 00:05:31,330 But we will not look at that right now. 87 00:05:31,870 --> 00:05:34,000 We will be creating those ourselves. 88 00:05:34,030 --> 00:05:35,530 So we will just ignore that. 89 00:05:36,100 --> 00:05:40,630 So what we're going to do now is we'll just go try and deploy 90 00:05:40,690 --> 00:05:43,420 this application ourselves with Docker. 91 00:05:43,820 --> 00:05:47,510 But the first thing that we need to do is build these images, 92 00:05:47,520 --> 00:05:52,400 because we know that the Redis and Postgres databases already 93 00:05:52,410 --> 00:05:55,580 have images available on the Docker Hub, but the three others 94 00:05:55,700 --> 00:05:57,860 are the applications that we are developing. 95 00:05:57,860 --> 00:06:02,052 So we do not have images built for those, so we'll have to build them. 96 00:06:02,480 --> 00:06:06,230 So I'm going to first clone the source code repository 97 00:06:07,049 --> 00:06:08,330 to my local system. 98 00:06:08,340 --> 00:06:13,970 So I will do a git clone and then paste the address, and 99 00:06:13,980 --> 00:06:16,520 that will clone the source. 100 00:06:18,200 --> 00:06:20,660 It is cloned it into example-voting-app. 101 00:06:20,670 --> 00:06:24,110 And when I go into example-voting-app, I have all the code 102 00:06:24,110 --> 00:06:26,240 that we just walked through. 103 00:06:26,240 --> 00:06:29,810 Okay, so we will start with deploying the voting-app. 104 00:06:29,840 --> 00:06:35,460 For that, we need to create a Docker image for the voting-app. 105 00:06:35,460 --> 00:06:37,751 [No audio] 106 00:06:37,751 --> 00:06:42,150 So we will go into the vote directory and we look at 107 00:06:42,160 --> 00:06:45,339 the Dockerfile. The Dockerfile looks intact. 108 00:06:45,558 --> 00:06:50,070 So we're just going to go ahead and build the Docker image 109 00:06:50,130 --> 00:06:54,330 by running the docker build command, and we will tag it with 110 00:06:54,340 --> 00:06:55,891 a name voting-app. 111 00:06:56,790 --> 00:07:00,628 Okay, so the Docker image is built. 112 00:07:01,950 --> 00:07:05,890 If you run the docker images command, you can see that it 113 00:07:05,920 --> 00:07:09,730 has the voting-app image built. 114 00:07:10,930 --> 00:07:14,140 So now that I have the voting-app image built, I can run 115 00:07:14,150 --> 00:07:17,170 a Container by running the docker run voting-app command, 116 00:07:17,180 --> 00:07:21,490 and I'm going to publish a Port 5000 to 80. 117 00:07:21,553 --> 00:07:24,330 So the, the Container, 118 00:07:24,810 --> 00:07:28,410 the voting-app Container runs on Port 80, and I'm going to 119 00:07:28,420 --> 00:07:33,778 map that to Port 5000 on my host so that I can access it from a browser. 120 00:07:34,680 --> 00:07:38,970 So it looks like the Container is running. 121 00:07:38,980 --> 00:07:43,390 So I'm going to try and open a browser and go to the address 122 00:07:43,400 --> 00:07:47,890 with Port 5000, and I can see that the web application is 123 00:07:47,900 --> 00:07:52,531 displayed, and I can see two options to cast my vote, CATS and DOGS. 124 00:07:53,680 --> 00:07:56,950 Now, if I try to cast a vote by clicking on one of the button, 125 00:07:57,430 --> 00:08:02,590 you can see it tries to, it takes a while, and after a while, it fails. 126 00:08:02,590 --> 00:08:05,410 And I can now see that there's an internal server error. 127 00:08:05,950 --> 00:08:08,830 It says the server encountered and internal error and was 128 00:08:08,840 --> 00:08:11,350 unable to complete your request. 129 00:08:12,100 --> 00:08:15,520 If I go back and look at the logs, I see that it failed at 130 00:08:15,530 --> 00:08:17,465 the line redis.rpush. 131 00:08:17,500 --> 00:08:21,850 So basically it's unable to establish a connectivity to the 132 00:08:21,860 --> 00:08:25,780 Redis, obviously, because we haven't run a Redis instance. 133 00:08:25,780 --> 00:08:27,910 [No audio] 134 00:08:27,910 --> 00:08:30,950 So what we're going to do now is I'm just going to kill that 135 00:08:31,270 --> 00:08:37,808 instance, and I will first start a redis Container. 136 00:08:37,820 --> 00:08:42,070 So I will run an instance of redis, and I will name it redis 137 00:08:42,070 --> 00:08:45,900 [No audio] 138 00:08:45,900 --> 00:08:50,900 So it's pulling down the redis image and it's run an instance of Redis. 139 00:08:50,950 --> 00:08:55,679 I forgot to run it in the background, so I'll stop that and run it again. 140 00:08:55,840 --> 00:08:58,570 The -d for the detach option. 141 00:08:59,650 --> 00:09:03,290 Okay, so when I tried that, it failed again because I had 142 00:09:03,300 --> 00:09:06,590 already run it without the detached option. 143 00:09:06,600 --> 00:09:10,970 So it already created a Container with the name redis. 144 00:09:10,970 --> 00:09:13,910 And I'm trying to create another Container with the same 145 00:09:13,920 --> 00:09:16,490 name, so it's preventing me from doing that. 146 00:09:16,820 --> 00:09:20,210 So I'll have to delete that the previously created Containers. 147 00:09:20,220 --> 00:09:24,440 So I'm going to run a docker rm command to delete the previously 148 00:09:24,450 --> 00:09:27,740 created Container, and I'll run the same command again to 149 00:09:28,070 --> 00:09:29,870 start a new instance of redis. 150 00:09:30,200 --> 00:09:32,630 So I now have a redis instance running. 151 00:09:32,640 --> 00:09:36,770 I'm now going to start an instance of my voting-app. 152 00:09:37,060 --> 00:09:40,390 So I will run the docker run command with voting-app, and 153 00:09:40,400 --> 00:09:43,570 I will publish the Port 5000. 154 00:09:43,600 --> 00:09:49,540 I will also this time add a link to the redis server. 155 00:09:50,140 --> 00:09:55,620 So I'm running a voting-app and and added a link using the 156 00:09:55,630 --> 00:10:01,320 --link option and specified redis as we discussed in the 157 00:10:01,330 --> 00:10:04,720 lecture. Okay, so it's running now. 158 00:10:04,730 --> 00:10:09,250 I'm back to my web portal, and when I now try to cast a vote, 159 00:10:09,580 --> 00:10:13,300 you see that it goes successfully and I get a tick mark back. 160 00:10:13,360 --> 00:10:21,090 Now, this is because my Container I was now able to run establish 161 00:10:21,120 --> 00:10:22,980 a connectivity to Redis. 162 00:10:23,300 --> 00:10:28,640 So now we have successfully deployed Redis as well as the 163 00:10:28,650 --> 00:10:29,690 voting-application. 164 00:10:30,380 --> 00:10:37,850 We will now proceed to the worker and for the worker prerequisite 165 00:10:37,860 --> 00:10:40,430 is to have a Postgres database. 166 00:10:40,440 --> 00:10:45,020 So we will first deploy a postgres database instance. 167 00:10:46,100 --> 00:10:49,370 I'm not really sure what is the version of Postgres that 168 00:10:49,380 --> 00:10:51,500 this application requires. 169 00:10:51,860 --> 00:10:54,830 So I'm going to go into one of the files here. 170 00:10:55,580 --> 00:11:00,745 For example, if I go into the docker-stack file or a docker-compose file, 171 00:11:00,831 --> 00:11:03,310 I should be able to find the image that they 172 00:11:03,310 --> 00:11:06,330 used. So it's image 9.4. 173 00:11:07,530 --> 00:11:11,130 So I'm just going to use that here. 174 00:11:11,440 --> 00:11:14,200 I will name the instance db. 175 00:11:14,590 --> 00:11:17,440 And so later on, I can use that to create a link. 176 00:11:17,990 --> 00:11:24,390 And now, as you can see, it's running, the Postgres database 177 00:11:24,400 --> 00:11:27,420 is now started, and it's running successfully. 178 00:11:27,600 --> 00:11:31,990 I forgot to run in the background, so I'm just going to kill 179 00:11:31,990 --> 00:11:33,490 that runs in the background. 180 00:11:34,190 --> 00:11:35,150 Okay. 181 00:11:35,160 --> 00:11:39,380 I hit the issue again about the duplicate name. 182 00:11:39,390 --> 00:11:42,890 So I'm just going to delete the one that I created using 183 00:11:42,900 --> 00:11:44,120 the docker rm command. 184 00:11:44,150 --> 00:11:48,020 And I'm going to rerun the Postgres database in the detached 185 00:11:48,020 --> 00:11:51,230 mode. So I now have the Postgres database running. 186 00:11:51,240 --> 00:11:54,290 So if I do a docker ps, I see that there are three Containers 187 00:11:54,300 --> 00:11:57,830 running. One is my voting-app, one is my redis, and the third 188 00:11:57,840 --> 00:11:59,900 one is the postgres database. 189 00:11:59,910 --> 00:12:02,810 I can now go ahead and deploy the worker. 190 00:12:03,100 --> 00:12:05,710 So first I'll have to build the worker. 191 00:12:05,720 --> 00:12:10,600 So if I go to the worker directory and I can see the contents 192 00:12:10,610 --> 00:12:12,700 of the Dockerfile, make sure it's intact. 193 00:12:13,150 --> 00:12:17,320 And I'm going to run the docker build command to create and 194 00:12:17,800 --> 00:12:21,220 to build the Docker image for the worker. 195 00:12:21,230 --> 00:12:23,200 And we'll just wait for that to finish. 196 00:12:23,210 --> 00:12:26,830 Once that is finished, when we run the docker images command, 197 00:12:27,370 --> 00:12:31,240 we are able to see all the images that are available and 198 00:12:31,250 --> 00:12:33,190 our newly created worker-app image. 199 00:12:33,460 --> 00:12:36,670 We will now run an instance of the worker-app. 200 00:12:36,970 --> 00:12:39,730 Now, the worker-app needs two links. 201 00:12:40,000 --> 00:12:44,110 1 is to the redis and another link to the postgres database. 202 00:12:44,110 --> 00:12:46,820 [No audio] 203 00:12:46,820 --> 00:12:51,168 Okay, so as soon as it runs, you can see that it's processed one vote. 204 00:12:51,740 --> 00:12:53,900 So that is the vote that we casted earlier. 205 00:12:54,890 --> 00:12:58,560 Okay. So now when I run docker ps command, I can see that there 206 00:12:58,570 --> 00:13:00,480 are four Containers running. 207 00:13:00,490 --> 00:13:02,550 So we have the worker-app ready. 208 00:13:02,800 --> 00:13:08,620 The next step is to build and deploy the result-app. 209 00:13:08,860 --> 00:13:11,230 So that's the last step. 210 00:13:12,360 --> 00:13:15,690 So we will create an image for the result-app. 211 00:13:15,990 --> 00:13:21,600 We will deploy it and link it to the Postgres database. 212 00:13:21,860 --> 00:13:26,360 So we go into the code repository for result. 213 00:13:27,420 --> 00:13:31,500 And I have all the application and Dockerfiles there. 214 00:13:31,510 --> 00:13:33,750 I will make sure the Dockerfile is intact. 215 00:13:33,810 --> 00:13:37,920 And then I'm going to run the docker build command to create 216 00:13:38,340 --> 00:13:44,340 an image for this result-app, and I will tag it results-app. 217 00:13:46,210 --> 00:13:51,590 It goes through all the Node.js related installation steps, 218 00:13:51,890 --> 00:13:53,360 and finally it's completed. 219 00:13:53,420 --> 00:13:56,390 So now I have a new image, which is the result-app. 220 00:13:56,400 --> 00:14:01,310 I'm now going to run the result-app, but since it is a web 221 00:14:01,310 --> 00:14:04,430 server, it has a Port requirement. 222 00:14:04,440 --> 00:14:09,500 So it exposes Port 80, and that's where it listens, I'm going 223 00:14:09,510 --> 00:14:14,570 to map Port 80 to Port 5001 because Port 5,000 on my local 224 00:14:14,570 --> 00:14:18,170 host is already occupied by the voting-app. 225 00:14:18,320 --> 00:14:23,450 So my result-app, I'd like to see it on Port 5001, so I'll 226 00:14:23,460 --> 00:14:28,930 map, I'll publish the Port 80 to 5001, and I also need to 227 00:14:28,940 --> 00:14:31,960 add a link because the result-app is linked to the db. 228 00:14:33,100 --> 00:14:35,020 So I'll add a link for that. 229 00:14:35,300 --> 00:14:38,090 Okay, so that should be it. 230 00:14:38,100 --> 00:14:45,980 And I'm now going to hit enter, and I can see that the application 231 00:14:45,990 --> 00:14:49,640 has started and it's connected to db, which is good. 232 00:14:50,390 --> 00:14:56,830 And if I go to the web browser and and establish a connectivity 233 00:14:56,840 --> 00:14:59,980 to Port 5001, and I can see the result page. 234 00:14:59,990 --> 00:15:01,210 So this is the result page. 235 00:15:01,270 --> 00:15:05,470 Since my vote was for cats, I see the 100% wards for CATS. 236 00:15:06,730 --> 00:15:09,490 I could also go back and change my vote. 237 00:15:09,760 --> 00:15:15,890 So if I go back and change my vote to DOGS, I see it's changed 238 00:15:15,980 --> 00:15:21,493 immediately. So every time I change my vote, it goes through the full cycle. 239 00:15:21,920 --> 00:15:26,330 The data goes through Redis, the worker processes it, updates 240 00:15:26,340 --> 00:15:29,630 the database, and then it's finally shown in this result 241 00:15:29,630 --> 00:15:35,000 page. So that's it for this demo, we took a look at the example-voting-app. 242 00:15:35,070 --> 00:15:38,750 We understood the architecture of it, how it works, and we 243 00:15:38,760 --> 00:15:46,656 also successfully deployed it with docker run commands using links. 244 00:15:46,656 --> 00:15:48,530 Thank you very much for your time. 245 00:15:48,540 --> 00:15:53,416 And in the next demo, we'll look at how to do the same with Docker Compose. 246 00:15:53,416 --> 00:15:57,708 [Outro music]