1 00:00:00,000 --> 00:00:04,500 [Intro Music] 2 00:00:04,560 --> 00:00:06,570 Now we are running both services 3 00:00:06,570 --> 00:00:09,768 frontend and api using 'docker-compose'. 4 00:00:09,768 --> 00:00:12,000 And you know how to start 5 00:00:12,060 --> 00:00:14,130 all services simultaneously and how 6 00:00:14,130 --> 00:00:16,379 to stop them. Also, you know how to 7 00:00:16,379 --> 00:00:18,960 run them in background. But let's 8 00:00:18,960 --> 00:00:21,060 now try to do the following. I'm sure that 9 00:00:21,060 --> 00:00:22,260 you are now running both 10 00:00:22,260 --> 00:00:24,150 containers. If I enter 'docker 11 00:00:24,150 --> 00:00:25,680 ps', I will see those 12 00:00:25,680 --> 00:00:28,080 containers here up and running. Now 13 00:00:28,080 --> 00:00:30,600 let's go to code here. And let's 14 00:00:30,600 --> 00:00:32,460 modify for instance, frontend 15 00:00:32,460 --> 00:00:34,800 application. Let's go to frontend, 16 00:00:34,830 --> 00:00:37,050 let's go to 'components', and then 17 00:00:37,050 --> 00:00:39,750 let's open up 'Search.js' file. 18 00:00:40,290 --> 00:00:42,780 And here let's modify for example, 19 00:00:42,810 --> 00:00:44,760 text on the bottom, and let's 20 00:00:44,760 --> 00:00:47,280 modify it from 'Search' here to 21 00:00:47,310 --> 00:00:50,340 'Search Image', like that. Let's save 22 00:00:50,340 --> 00:00:53,130 changes, go to a browser and 23 00:00:53,130 --> 00:00:56,070 refresh the page here. And I still 24 00:00:56,070 --> 00:00:58,110 see here 'Search' text on this 25 00:00:58,110 --> 00:01:00,870 button, but I expect to see 'Search 26 00:01:00,990 --> 00:01:03,540 Image'. And now of course, those 27 00:01:03,540 --> 00:01:05,790 changes are not reflected inside of 28 00:01:05,790 --> 00:01:08,550 the container, because now inside 29 00:01:08,550 --> 00:01:10,620 of the 'docker-compose' file, we are 30 00:01:10,620 --> 00:01:13,290 basically running static images 31 00:01:13,380 --> 00:01:14,880 that we have built using 32 00:01:14,910 --> 00:01:17,640 corresponding Dockerfiles, here 33 00:01:17,670 --> 00:01:21,240 for api and here for frontend. But 34 00:01:21,270 --> 00:01:23,430 our goal is to use 'docker-compose' 35 00:01:23,430 --> 00:01:25,770 containers in order to proceed with 36 00:01:25,770 --> 00:01:27,690 further development. That's why 37 00:01:27,690 --> 00:01:30,120 such feature as hot reload is 38 00:01:30,150 --> 00:01:32,250 necessary for us. And we want to 39 00:01:32,250 --> 00:01:34,320 see changes made in the code base 40 00:01:34,380 --> 00:01:36,870 immediately here. Same applies to 41 00:01:36,870 --> 00:01:39,150 the api service and in Docker 42 00:01:39,150 --> 00:01:40,530 world, we could achieve that by 43 00:01:40,530 --> 00:01:43,620 using 'volumes', and we could map 44 00:01:43,680 --> 00:01:47,160 folders from our computer, namely, 45 00:01:47,340 --> 00:01:50,880 'frontend' folder and 'api' folder to 46 00:01:50,880 --> 00:01:53,610 the corresponding containers, and 47 00:01:53,610 --> 00:01:56,520 after such mapping any changes, for 48 00:01:56,520 --> 00:01:58,500 instance in Search.js file 49 00:01:58,770 --> 00:02:01,020 will be reflected in corresponding 50 00:02:01,050 --> 00:02:02,970 Search.js file inside of the 51 00:02:02,970 --> 00:02:05,220 container. And if you use Docker 52 00:02:05,220 --> 00:02:06,900 volume mapping, Docker will 53 00:02:06,900 --> 00:02:08,310 overwrite contents of a 54 00:02:08,310 --> 00:02:10,139 specific folder inside of the 55 00:02:10,139 --> 00:02:12,750 container by contents on your 56 00:02:12,750 --> 00:02:15,870 computer. Let's first map volume to 57 00:02:15,870 --> 00:02:18,360 our frontend application, and 58 00:02:18,360 --> 00:02:20,160 let's add one more instruction 59 00:02:20,160 --> 00:02:22,950 here that is called 'volumes', like 60 00:02:22,950 --> 00:02:26,130 that. Here on the next line, let's 61 00:02:26,160 --> 00:02:29,190 add following mapping, '-', here 62 00:02:29,220 --> 00:02:32,880 will be './frontend', like 63 00:02:32,880 --> 00:02:35,700 that, next please add ':', and 64 00:02:35,700 --> 00:02:38,610 here will be '/app', we get the 65 00:02:38,640 --> 00:02:41,130 such folder is working directory 66 00:02:41,160 --> 00:02:43,050 inside of the container. We 67 00:02:43,050 --> 00:02:44,730 specified it using 68 00:02:44,730 --> 00:02:47,275 instruction in corresponding Dockerfiles. 69 00:02:47,275 --> 00:02:48,810 And notice that here is 70 00:02:48,870 --> 00:02:51,570 absolute path to this folder inside 71 00:02:51,570 --> 00:02:54,000 of the container. And here was a 72 00:02:54,000 --> 00:02:56,700 relative path to the folder with 73 00:02:56,730 --> 00:02:59,280 application files. This is where for 74 00:02:59,280 --> 00:03:01,230 instance, Search.js file is 75 00:03:01,230 --> 00:03:02,880 located inside of the frontend 76 00:03:02,880 --> 00:03:05,070 folder. And now using such 77 00:03:05,070 --> 00:03:07,530 instruction, we actually map our 78 00:03:07,530 --> 00:03:09,990 local frontend folder on our 79 00:03:09,990 --> 00:03:13,020 computers to the 'app' folder inside 80 00:03:13,020 --> 00:03:15,210 of the container. And after such 81 00:03:15,210 --> 00:03:17,340 instruction, contents of the 'app' 82 00:03:17,340 --> 00:03:19,680 folder inside of the container will 83 00:03:19,680 --> 00:03:22,170 be actually overridden by contents 84 00:03:22,260 --> 00:03:24,210 of the frontend folder, and 85 00:03:24,210 --> 00:03:25,920 changes of the files inside of the 86 00:03:25,920 --> 00:03:27,570 frontend folder will be 87 00:03:27,600 --> 00:03:29,370 immediately reflected inside of the 88 00:03:29,370 --> 00:03:31,890 container. That's what volumes 89 00:03:31,920 --> 00:03:35,310 mapping does for us. Also, except this 90 00:03:35,340 --> 00:03:37,440 instruction, we need to add one 91 00:03:37,440 --> 00:03:39,660 more instruction, and let's add it 92 00:03:39,660 --> 00:03:42,000 here before this one, and it will 93 00:03:42,000 --> 00:03:46,327 be '-/app/node_modules' 94 00:03:46,327 --> 00:03:47,900 like that, and with such 95 00:03:47,900 --> 00:03:51,200 instruction in place we will keep 'node_modules' 96 00:03:51,200 --> 00:03:53,300 folder inside of the 'app' 97 00:03:53,310 --> 00:03:55,080 folder inside of the container. 98 00:03:55,500 --> 00:03:57,300 Contents of this 'node_modules' 99 00:03:57,300 --> 00:04:00,810 folder will not be overridden by 100 00:04:00,810 --> 00:04:02,640 contents of the node_modules folder 101 00:04:02,640 --> 00:04:04,860 from the frontend folder. Sounds 102 00:04:04,860 --> 00:04:06,660 complicated, but that's what we 103 00:04:06,660 --> 00:04:08,430 need to do in order to correctly 104 00:04:08,430 --> 00:04:10,620 handle node_modules folder inside 105 00:04:10,620 --> 00:04:12,750 of the container. Look at that we 106 00:04:12,750 --> 00:04:14,430 created node_modules folder inside 107 00:04:14,430 --> 00:04:17,519 of the container. After this step in 108 00:04:17,519 --> 00:04:19,920 the Dockerfile, we installed all 109 00:04:19,920 --> 00:04:21,870 the dependencies inside of the image. 110 00:04:22,000 --> 00:04:24,600 And that's why we need to keep node_modules 111 00:04:24,600 --> 00:04:25,500 folder inside of the 112 00:04:25,589 --> 00:04:28,500 container as it was during image 113 00:04:28,500 --> 00:04:30,900 build process. And we should not 114 00:04:30,930 --> 00:04:33,300 override node_modules folder inside 115 00:04:33,300 --> 00:04:35,820 of the container by node_modules 116 00:04:35,820 --> 00:04:37,950 folder from the frontend folder. 117 00:04:38,970 --> 00:04:40,980 That's why we should add such 118 00:04:40,980 --> 00:04:44,600 instruction here '/app/node_modules'. 119 00:04:45,270 --> 00:04:47,220 This is how we could perform volumes 120 00:04:47,220 --> 00:04:49,980 mapping for frontend application. 121 00:04:50,490 --> 00:04:52,140 Let's save changes here in this 122 00:04:52,140 --> 00:04:54,480 'docker-compose.yml' file. And now 123 00:04:54,480 --> 00:04:56,580 we need to use 'docker-compose down' 124 00:04:56,640 --> 00:04:58,830 and 'up' commands in order to apply 125 00:04:58,890 --> 00:05:00,750 this change. Let's go to the 126 00:05:00,750 --> 00:05:03,000 terminal. And here in the 'images- 127 00:05:03,000 --> 00:05:06,870 gallery' folder, type 'docker-compose 128 00:05:07,080 --> 00:05:09,540 down'. Let's bring down both 129 00:05:09,540 --> 00:05:11,880 containers, 'Stopping images-gallery_ 130 00:05:11,910 --> 00:05:14,160 api', and 'Stopping images-gallery_ 131 00:05:14,160 --> 00:05:17,040 frontend'; 'done' here; 'done' here, 132 00:05:17,280 --> 00:05:19,620 removing both containers, removing 133 00:05:19,620 --> 00:05:21,360 network. You've seen this process 134 00:05:21,360 --> 00:05:23,340 before. And now let's start 135 00:05:23,340 --> 00:05:25,200 containers over again, 'docker- 136 00:05:25,200 --> 00:05:27,390 compose up', and let's run them in the 137 00:05:27,390 --> 00:05:29,100 background, '-d' option. 138 00:05:29,580 --> 00:05:31,500 'Creating network'. Now, you will see 139 00:05:31,500 --> 00:05:33,150 message as 'Creating containers', 140 00:05:33,450 --> 00:05:35,280 'Creating images-gallery_api_1, 141 00:05:35,550 --> 00:05:37,530 'Creating images-gallery_frontend_1'. 142 00:05:38,640 --> 00:05:40,320 Here, I see prompt, "Docker" would 143 00:05:40,320 --> 00:05:41,970 like to access files in your 144 00:05:41,970 --> 00:05:44,070 Desktop folder; and that means that 145 00:05:44,070 --> 00:05:46,740 now Docker tries to access files 146 00:05:46,770 --> 00:05:48,300 inside of the images-gallery 147 00:05:48,300 --> 00:05:49,800 folder actually, that is located on 148 00:05:49,800 --> 00:05:51,540 the Desktop in my case. Let's 149 00:05:51,540 --> 00:05:54,450 grant access. 'OK'. And frontend 150 00:05:54,450 --> 00:05:55,710 container was started 151 00:05:55,710 --> 00:05:57,930 successfully. Let's have a look at 152 00:05:57,930 --> 00:05:59,850 the current containers, 'docker ps', 153 00:06:00,180 --> 00:06:02,100 and I see two containers up and 154 00:06:02,100 --> 00:06:04,170 running. Let's now check what has 155 00:06:04,170 --> 00:06:06,330 changed after this volumes mapping. 156 00:06:07,050 --> 00:06:08,700 Let's go first to web browser, 157 00:06:08,790 --> 00:06:11,370 and refresh page here. As usually 158 00:06:11,370 --> 00:06:13,020 after every 'docker-compose up' 159 00:06:13,020 --> 00:06:14,670 command, when containers are 160 00:06:14,670 --> 00:06:16,470 created from scratch, you need to 161 00:06:16,470 --> 00:06:18,480 wait a bit until React scripts 162 00:06:18,510 --> 00:06:20,130 finishes creation of the 163 00:06:20,130 --> 00:06:22,620 development build. And now finally, 164 00:06:22,620 --> 00:06:24,600 I see that web page was updated, 165 00:06:24,720 --> 00:06:26,760 and text on this button is now 166 00:06:26,760 --> 00:06:29,430 'Search Image'. But notice that we 167 00:06:29,460 --> 00:06:32,340 did not rebuild actual image for 168 00:06:32,340 --> 00:06:35,040 our frontend application, we just 169 00:06:35,040 --> 00:06:36,960 mapped files from our local 170 00:06:36,960 --> 00:06:39,810 computer to the container. Let's 171 00:06:39,810 --> 00:06:41,520 now try to modify text on this 172 00:06:41,520 --> 00:06:43,770 button once again. Let's go to 173 00:06:43,770 --> 00:06:46,500 Search.js, and modify it to 174 00:06:46,500 --> 00:06:48,990 'Search' back again, like that. We'll 175 00:06:48,990 --> 00:06:51,390 save changes in this file, go back 176 00:06:51,390 --> 00:06:54,300 to a browser, and in a while I see 177 00:06:54,300 --> 00:06:56,370 the text on the button was changed 178 00:06:56,610 --> 00:06:58,890 and it was actually live reload. 179 00:06:59,340 --> 00:07:01,170 React scripts using hot reload 180 00:07:01,200 --> 00:07:03,300 just applied those changes that 181 00:07:03,300 --> 00:07:04,950 were made in the Search.js 182 00:07:04,950 --> 00:07:07,050 file. For better clarity, let's 183 00:07:07,050 --> 00:07:08,730 connect to the container and 184 00:07:08,730 --> 00:07:10,770 observe contents of the 'app' folder 185 00:07:10,770 --> 00:07:12,900 inside of it. Let's list 186 00:07:12,900 --> 00:07:15,390 containers now. And using such 187 00:07:15,390 --> 00:07:17,250 container name as 'images-gallery_ 188 00:07:17,250 --> 00:07:19,440 frontend_1', connect to this 189 00:07:19,440 --> 00:07:21,420 container. And we already know that 190 00:07:21,450 --> 00:07:23,010 there was no bash executable 191 00:07:23,040 --> 00:07:25,590 available in this Node.js Alpine 192 00:07:25,620 --> 00:07:27,390 image that we used as base image 193 00:07:27,390 --> 00:07:29,670 for this image. That's why we will 194 00:07:29,670 --> 00:07:32,460 use 'sh' shell. So, let's connect to the 195 00:07:32,460 --> 00:07:34,770 frontend container, 'docker exec 196 00:07:34,860 --> 00:07:36,780 -it', here will be the name of 197 00:07:36,780 --> 00:07:39,217 the container, 'images-gallery_frontend_1' 198 00:07:39,217 --> 00:07:40,230 In your case 199 00:07:40,349 --> 00:07:42,119 if you have the same folder name, 200 00:07:42,149 --> 00:07:44,249 'images-gallery', and same service 201 00:07:44,249 --> 00:07:46,439 name, this container name will be 202 00:07:46,469 --> 00:07:48,719 exactly the same as you see here. 203 00:07:49,229 --> 00:07:51,959 And here type 'sh'. We are starting 204 00:07:51,989 --> 00:07:54,209 'sh' shell process here as additional 205 00:07:54,209 --> 00:07:57,119 process in running container. And now 206 00:07:57,119 --> 00:07:58,649 I'm inside of the 'app' working 207 00:07:58,649 --> 00:08:00,359 directory inside of the container. 208 00:08:01,169 --> 00:08:03,119 As before, it contains different 209 00:08:03,119 --> 00:08:05,009 files like Dockerfile, package. 210 00:08:05,009 --> 00:08:07,529 json, and others. And also there was 211 00:08:07,559 --> 00:08:10,289 'src' folder. Let's now try to 212 00:08:10,289 --> 00:08:12,372 observe contents of the Search.js' 213 00:08:12,372 --> 00:08:14,819 file inside of the 'src' folder. 214 00:08:15,569 --> 00:08:18,269 Let's use 'cat' command, 'cat src 215 00:08:18,389 --> 00:08:21,989 /components/Search.js'; 216 00:08:22,919 --> 00:08:25,679 and here I see 'Search' text inside 217 00:08:25,679 --> 00:08:29,399 of the 'button' 'jsx' tag. Let's now go 218 00:08:29,399 --> 00:08:32,219 to the VS Code and modify this text 219 00:08:32,279 --> 00:08:35,969 again, 'Search Image' like that. And 220 00:08:35,969 --> 00:08:37,739 let's go back here. And with 221 00:08:37,739 --> 00:08:39,539 contents of the Search.js file 222 00:08:39,568 --> 00:08:42,688 again. And now I see modified 223 00:08:42,688 --> 00:08:44,969 contents. And that is because now 224 00:08:44,999 --> 00:08:47,639 container actually has mapping to 225 00:08:47,639 --> 00:08:50,849 the file Search.js on your computer 226 00:08:51,389 --> 00:08:54,239 due to volumes mapping. And all 227 00:08:54,239 --> 00:08:56,009 changes in the files on your local 228 00:08:56,009 --> 00:08:58,559 computer here are immediately 229 00:08:58,559 --> 00:09:00,779 reflected inside of the container. 230 00:09:01,439 --> 00:09:03,599 That's what we achieved by using 231 00:09:03,719 --> 00:09:07,872 such instructions as here. But node_modules 232 00:09:07,872 --> 00:09:10,049 folder remains same as it 233 00:09:10,049 --> 00:09:12,029 was during the build process of the 234 00:09:12,029 --> 00:09:14,999 actual frontend image. That's what 235 00:09:15,029 --> 00:09:18,029 this line actually does for us. But 236 00:09:18,059 --> 00:09:19,769 all remaining files inside of the 237 00:09:19,769 --> 00:09:21,779 frontend folder on your computer 238 00:09:22,169 --> 00:09:24,599 are now mapped to the 'app' folder 239 00:09:24,629 --> 00:09:27,089 inside of the container. I hope 240 00:09:27,089 --> 00:09:28,739 that idea is clear. And now we are 241 00:09:28,769 --> 00:09:30,179 able to proceed with further 242 00:09:30,179 --> 00:09:31,559 development of the frontend 243 00:09:31,559 --> 00:09:34,199 application without rebuilds of 244 00:09:34,199 --> 00:09:36,809 actual image after each change of 245 00:09:36,809 --> 00:09:39,119 the code base. Now let's undo 246 00:09:39,119 --> 00:09:40,900 changes made in the Search.js 247 00:09:40,900 --> 00:09:42,900 file, and let's go back to text 248 00:09:42,959 --> 00:09:45,209 'Search' on the button, save changes, 249 00:09:45,329 --> 00:09:46,829 go back to the web browser, and 250 00:09:46,829 --> 00:09:48,959 ensure that 'Search Image' will be 251 00:09:48,959 --> 00:09:51,299 changed to 'Search'. Let's wait a 252 00:09:51,299 --> 00:09:54,089 bit. Actually now I don't see 253 00:09:54,089 --> 00:09:55,889 changes of the text on this button. 254 00:09:56,249 --> 00:09:57,749 And from time to time it might 255 00:09:57,749 --> 00:10:00,539 happen, and it is possible to fix 256 00:10:00,569 --> 00:10:02,789 this issue if it happens on your 257 00:10:02,789 --> 00:10:04,529 computer as well using an 258 00:10:04,529 --> 00:10:06,539 environment variable setup that we 259 00:10:06,539 --> 00:10:08,099 could add in the 'docker-compose' 260 00:10:08,099 --> 00:10:10,049 file; and let me demonstrate to you 261 00:10:10,049 --> 00:10:12,100 how to fix that after the small pause. 262 00:10:12,100 --> 00:10:13,824 [no audio]