1
00:00:02,350 --> 00:00:05,370
So with that, we added these two features

2
00:00:05,370 --> 00:00:07,920
to the database, MongoDB container.

3
00:00:07,920 --> 00:00:10,330
Now, let's work on the node backend,

4
00:00:10,330 --> 00:00:14,600
and there we also wanna ensure that data persists

5
00:00:14,600 --> 00:00:18,380
in this case, the log files, this container writes,

6
00:00:18,380 --> 00:00:22,310
and we wanna have life source code updates

7
00:00:22,310 --> 00:00:24,560
so that when we change our source code

8
00:00:24,560 --> 00:00:27,180
in our local host project folder,

9
00:00:27,180 --> 00:00:31,513
the latest source code is also available in the container.

10
00:00:33,420 --> 00:00:34,700
For this, I'll first of all,

11
00:00:34,700 --> 00:00:38,130
stop my goals backend container again.

12
00:00:38,130 --> 00:00:41,320
So this node container, so that we can restart it

13
00:00:41,320 --> 00:00:43,200
with a different configuration

14
00:00:43,200 --> 00:00:45,950
because we now also wanna add a volume there,

15
00:00:45,950 --> 00:00:49,030
or actually two volumes.

16
00:00:49,030 --> 00:00:51,990
We wanna run our goal backend with docker run,

17
00:00:51,990 --> 00:00:54,020
but we need volumes.

18
00:00:54,020 --> 00:00:57,120
We need one volume for the log files.

19
00:00:57,120 --> 00:01:01,450
Now we can go for a name volume to not know

20
00:01:01,450 --> 00:01:03,400
where they are stored on the host machine,

21
00:01:03,400 --> 00:01:06,880
but to ensure that they survive container tear down,

22
00:01:06,880 --> 00:01:10,520
or we go for a bind mount so that we can also read

23
00:01:10,520 --> 00:01:14,870
the log files from inside our hosting machine.

24
00:01:14,870 --> 00:01:16,290
Now you could do either way.

25
00:01:16,290 --> 00:01:18,590
I'll go for a named module here,

26
00:01:18,590 --> 00:01:21,400
so that we don't have easy access to these files

27
00:01:21,400 --> 00:01:22,570
from the host machine,

28
00:01:22,570 --> 00:01:25,313
but just to practice using volumes again.

29
00:01:26,250 --> 00:01:28,420
And for that, I'll name this logs

30
00:01:28,420 --> 00:01:33,420
and bind this to /app/logs in the container.

31
00:01:33,720 --> 00:01:36,670
/app is our working directory

32
00:01:36,670 --> 00:01:39,180
as specified in the docker file.

33
00:01:39,180 --> 00:01:43,170
So that is where the entire application is copied to.

34
00:01:43,170 --> 00:01:45,910
And then we have the logs folder in there

35
00:01:45,910 --> 00:01:48,380
to which this application writes the logs

36
00:01:48,380 --> 00:01:53,050
and therefore, it's /app/logs internally

37
00:01:53,050 --> 00:01:55,410
in the container where logs are written to

38
00:01:55,410 --> 00:01:59,053
and that's there for the path we wanna bind to our volume.

39
00:01:59,950 --> 00:02:02,860
Now that's one volume, but we need another one,

40
00:02:02,860 --> 00:02:05,330
or to be precise, we need a bind mount

41
00:02:05,330 --> 00:02:08,600
which we also create with /v build.

42
00:02:08,600 --> 00:02:12,580
I wanna bind everything in the app folder

43
00:02:12,580 --> 00:02:17,150
to my local hosting directory here,

44
00:02:17,150 --> 00:02:19,950
simply to ensure that whenever I change something

45
00:02:19,950 --> 00:02:21,460
in my source code here,

46
00:02:21,460 --> 00:02:24,130
it's reflected inside of the container.

47
00:02:24,130 --> 00:02:26,010
Now for such a bind mount,

48
00:02:26,010 --> 00:02:29,670
you need the full path to your folder here,

49
00:02:29,670 --> 00:02:34,060
which you bind as a name to the container internal path.

50
00:02:34,060 --> 00:02:36,390
So, therefore, here, we can, for example, right-lick

51
00:02:36,390 --> 00:02:41,390
on app.js and copy the path and paste this in here.

52
00:02:41,440 --> 00:02:43,863
However, delete app.js at the end.

53
00:02:44,880 --> 00:02:48,230
So that I just paste the full path to backend

54
00:02:48,230 --> 00:02:51,023
and bind this to the internal app folder.

55
00:02:52,270 --> 00:02:55,270
Now also keep in mind what you learned about volumes

56
00:02:55,270 --> 00:02:58,590
and files overwriting each other in the container.

57
00:02:58,590 --> 00:03:02,990
Longer container internal paths have precedents

58
00:03:02,990 --> 00:03:05,550
and overwrite shorter paths.

59
00:03:05,550 --> 00:03:07,520
So in the example of logs here,

60
00:03:07,520 --> 00:03:11,400
we already do ensure that logs written by the container

61
00:03:11,400 --> 00:03:15,350
are not overwritten by the local logs folder

62
00:03:15,350 --> 00:03:17,560
in my local host project folder.

63
00:03:17,560 --> 00:03:21,490
So that's good. The logs in the container will survive.

64
00:03:21,490 --> 00:03:24,220
But we also learned that we should do something similar

65
00:03:24,220 --> 00:03:27,960
about node modules to ensure that if we didn't have

66
00:03:27,960 --> 00:03:31,420
node modules here on the local host machine,

67
00:03:31,420 --> 00:03:34,240
we don't overwrite the existing node modules

68
00:03:34,240 --> 00:03:37,430
in the container with the non-existing ones here,

69
00:03:37,430 --> 00:03:40,120
which would cause our container to crash

70
00:03:40,120 --> 00:03:42,450
because dependencies would be missing.

71
00:03:42,450 --> 00:03:44,640
So therefore we should add another volume,

72
00:03:44,640 --> 00:03:47,460
and here we can simply use an anonymous one

73
00:03:47,460 --> 00:03:50,410
and point at app node_modules

74
00:03:50,410 --> 00:03:52,330
to basically tell the container

75
00:03:52,330 --> 00:03:54,900
that the existing node modules folder

76
00:03:54,900 --> 00:03:58,030
inside of the container should stay there

77
00:03:58,030 --> 00:04:00,070
and should not be overwritten

78
00:04:00,070 --> 00:04:03,130
by the non-existing node modules folder

79
00:04:03,130 --> 00:04:07,820
in our host machine folder, which we bind to the app folder.

80
00:04:07,820 --> 00:04:11,740
And I did talk about this in the volumes course section.

81
00:04:11,740 --> 00:04:14,320
So definitely make sure you go through that again

82
00:04:14,320 --> 00:04:16,713
in case this doesn't tell you anything.

83
00:04:17,930 --> 00:04:20,540
With that though, we should be starting

84
00:04:20,540 --> 00:04:24,870
this node server here with our volumes added,

85
00:04:24,870 --> 00:04:28,410
and I'm again, going to run it in detached mode now

86
00:04:28,410 --> 00:04:30,140
and start it.

87
00:04:30,140 --> 00:04:34,380
And it is up and running. So that's looking good.

88
00:04:34,380 --> 00:04:38,620
If I reload my application, my React application here,

89
00:04:38,620 --> 00:04:41,590
it also is still able to fetch data,

90
00:04:41,590 --> 00:04:45,397
and deleting all the words and adding again all the words,

91
00:04:45,397 --> 00:04:47,760
so that also is looking good.

92
00:04:47,760 --> 00:04:50,910
All is got no errors here in the developer tools.

93
00:04:50,910 --> 00:04:54,820
And that proves that indeed our containers

94
00:04:54,820 --> 00:04:56,830
are up and running successfully.

95
00:04:56,830 --> 00:05:00,870
Now, although the node container with our bind mount

96
00:05:00,870 --> 00:05:05,050
and the upper volumes, however, we're not done yet.

97
00:05:05,050 --> 00:05:08,900
Yes, we do put our latest source code

98
00:05:08,900 --> 00:05:12,160
from the local host folder into the node container,

99
00:05:12,160 --> 00:05:14,860
but currently that doesn't do much

100
00:05:14,860 --> 00:05:16,890
because when we start the container,

101
00:05:16,890 --> 00:05:19,540
we run app.js with the node command,

102
00:05:19,540 --> 00:05:22,580
and that basically logs in the code

103
00:05:22,580 --> 00:05:25,580
at the point of time this containers starts.

104
00:05:25,580 --> 00:05:28,010
The node process loads all the code,

105
00:05:28,010 --> 00:05:31,210
and then starts that code, so to say.

106
00:05:31,210 --> 00:05:33,310
So, if the code changes their author,

107
00:05:33,310 --> 00:05:37,670
this has no impact on the already running node server.

108
00:05:37,670 --> 00:05:39,900
And that's of course not what we want here.

109
00:05:39,900 --> 00:05:42,650
We want the node server to restart

110
00:05:42,650 --> 00:05:44,890
whenever the code changes.

111
00:05:44,890 --> 00:05:47,713
Yes, we could stop and restart the container,

112
00:05:47,713 --> 00:05:51,100
that would do the trick, but even better than that,

113
00:05:51,100 --> 00:05:54,700
we can add the extra dependency to this project,

114
00:05:54,700 --> 00:05:57,230
which then actually will restart the server

115
00:05:57,230 --> 00:06:00,263
automatically for us when the code changes.

116
00:06:01,640 --> 00:06:04,060
For this, I'll delete package log JSON,

117
00:06:04,060 --> 00:06:08,457
and here in packaged.js, I'll add a new devDependencies node

118
00:06:09,540 --> 00:06:14,540
below dependencies, and add nodemon here as a dependency,

119
00:06:15,080 --> 00:06:16,463
and I'll pick version 2.0.4.

120
00:06:19,091 --> 00:06:21,150
Nodemon is an extra tool,

121
00:06:21,150 --> 00:06:24,010
which I already covered early in the course,

122
00:06:24,010 --> 00:06:27,610
which watches the project folder for file changes

123
00:06:27,610 --> 00:06:29,650
in JavaScript files,

124
00:06:29,650 --> 00:06:32,380
and if such a JavaScript file does change,

125
00:06:32,380 --> 00:06:35,100
it restarts the node server.

126
00:06:35,100 --> 00:06:38,020
We just have to ensure that to utilize nodemon,

127
00:06:38,020 --> 00:06:41,030
we can do that by adding a start script here

128
00:06:41,030 --> 00:06:42,800
to the scripts section.

129
00:06:42,800 --> 00:06:46,780
And there, I wanna run nodemon app.js

130
00:06:46,780 --> 00:06:49,310
to use nodemon to run app.js,

131
00:06:49,310 --> 00:06:52,010
and under the hood nodemon uses node,

132
00:06:52,010 --> 00:06:56,630
but it restarts the node server whenever any JavaScript file

133
00:06:56,630 --> 00:06:58,070
in the project folder,

134
00:06:58,070 --> 00:07:00,583
so in this case, in the backend folder changes.

135
00:07:02,330 --> 00:07:05,520
So these are changes we need to make to package.js,

136
00:07:05,520 --> 00:07:08,320
in the docker file of the backend project,

137
00:07:08,320 --> 00:07:11,320
we now need to run this start script,

138
00:07:11,320 --> 00:07:14,880
and can start like this to utilize nodemon.

139
00:07:15,890 --> 00:07:18,320
And that of course now means that we need to stop

140
00:07:18,320 --> 00:07:20,420
our goals backend container,

141
00:07:20,420 --> 00:07:23,960
so there's node application container we started,

142
00:07:23,960 --> 00:07:28,960
and then restart it, but based on a rebuilt image

143
00:07:29,010 --> 00:07:31,283
because we changed the docker file.

144
00:07:32,130 --> 00:07:35,193
So we built this goals node image again,

145
00:07:37,540 --> 00:07:40,280
and it installs all new dependencies ends on

146
00:07:40,280 --> 00:07:42,460
because the package.js file changed

147
00:07:43,560 --> 00:07:46,880
and thereafter, we can run this container

148
00:07:46,880 --> 00:07:49,653
with the same configuration as before.

149
00:07:50,740 --> 00:07:52,070
And if you'd run docker, PS,

150
00:07:52,070 --> 00:07:55,130
it should be up and running, and it is,

151
00:07:55,130 --> 00:07:58,370
but now it uses nodemon internally.

152
00:07:58,370 --> 00:08:02,920
And we can verify this by running docker logs goals-backend,

153
00:08:02,920 --> 00:08:04,390
which was our container name.

154
00:08:04,390 --> 00:08:07,050
Here, we see the nodemon log.

155
00:08:07,050 --> 00:08:09,913
And now if we change something in our code here,

156
00:08:11,070 --> 00:08:15,320
for example, here, when we say connected to MongoDB,

157
00:08:15,320 --> 00:08:17,300
I add two exclamation marks.

158
00:08:17,300 --> 00:08:22,040
If I save this and we log our goals back in logs again,

159
00:08:22,040 --> 00:08:24,570
we see it restarted because of changes,

160
00:08:24,570 --> 00:08:26,700
and we see that latest log

161
00:08:26,700 --> 00:08:29,360
and our application also still works.

162
00:08:29,360 --> 00:08:34,360
So now we also successfully provide life source code updates

163
00:08:34,429 --> 00:08:38,130
to our node application with help of our bind mount.

164
00:08:38,130 --> 00:08:41,059
And in this case with help of nodemon,

165
00:08:41,059 --> 00:08:45,330
which watches for file changes and restarts the node server

166
00:08:45,330 --> 00:08:49,480
without us being required to manually restart the container,

167
00:08:49,480 --> 00:08:52,663
which would be an option, but of course is less convenient.

168
00:08:54,250 --> 00:08:57,180
Now, there are two last things which I wanna tweak

169
00:08:57,180 --> 00:08:59,220
about this node application.

170
00:08:59,220 --> 00:09:01,540
One is this connection string.

171
00:09:01,540 --> 00:09:05,540
I had coded username and password into this string here,

172
00:09:05,540 --> 00:09:09,770
but of course that means that whenever I change that

173
00:09:09,770 --> 00:09:12,770
when I start my MongoDB container,

174
00:09:12,770 --> 00:09:17,300
so if I run MongoDB here with a different username

175
00:09:17,300 --> 00:09:18,950
or a different secret,

176
00:09:18,950 --> 00:09:21,790
which definitely is something that could happen,

177
00:09:21,790 --> 00:09:25,400
I need to change it in my code here, which is not horrible,

178
00:09:25,400 --> 00:09:28,170
but we could utilize environment variables here

179
00:09:28,170 --> 00:09:32,410
to inject dynamic values here and actually set

180
00:09:32,410 --> 00:09:34,660
the username and password we do use

181
00:09:34,660 --> 00:09:37,860
when we start this node container.

182
00:09:37,860 --> 00:09:39,820
And that's something I wanna do here.

183
00:09:39,820 --> 00:09:41,740
For data and the docker file,

184
00:09:41,740 --> 00:09:46,700
I'll add environment variables with the nth instruction,

185
00:09:46,700 --> 00:09:51,030
and I'll add one which will name MONGODB_USERNAME.

186
00:09:51,030 --> 00:09:52,853
The name is totally up to you here,

187
00:09:53,760 --> 00:09:57,380
and I'll set this to a default value of root,

188
00:09:57,380 --> 00:10:00,743
and add a second one, which I'll name MONGODB_PASSWORD,

189
00:10:02,910 --> 00:10:07,100
which I'll set to secret as a default value.

190
00:10:07,100 --> 00:10:10,000
Now these environment variables are available

191
00:10:10,000 --> 00:10:13,803
in the container environment and also in the running code.

192
00:10:14,700 --> 00:10:17,000
Now in app.js, we can utilize that.

193
00:10:17,000 --> 00:10:19,610
I wanna replace max with the values stored

194
00:10:19,610 --> 00:10:21,980
in the username environment variable

195
00:10:21,980 --> 00:10:24,799
and use the password environment variable to get

196
00:10:24,799 --> 00:10:28,780
to the value for the password and disconnection string.

197
00:10:28,780 --> 00:10:31,290
To conveniently add this in JavaScript,

198
00:10:31,290 --> 00:10:35,020
we can replace these single quote here with a backtick,

199
00:10:35,020 --> 00:10:37,690
which is a different character on your keyboard

200
00:10:37,690 --> 00:10:40,600
and do that all at the end of the string here.

201
00:10:40,600 --> 00:10:43,280
And that's just a special JavaScript syntax,

202
00:10:43,280 --> 00:10:45,340
has nothing to do with docker,

203
00:10:45,340 --> 00:10:49,500
which makes injecting dynamic values into a string easier.

204
00:10:49,500 --> 00:10:53,220
Now we can add dollar sign curly braces here,

205
00:10:53,220 --> 00:10:56,500
and then add a dynamically resolved value here,

206
00:10:56,500 --> 00:11:00,260
which is then combined into one long string.

207
00:11:00,260 --> 00:11:04,083
And here it's process.env, and then MONGODB_USERNAME.

208
00:11:05,520 --> 00:11:08,210
And here you should make sure that you really use

209
00:11:08,210 --> 00:11:10,700
the exact same environment variable

210
00:11:10,700 --> 00:11:13,570
as you specified in docker file,

211
00:11:13,570 --> 00:11:16,420
and do the same here for the password,

212
00:11:16,420 --> 00:11:20,560
dollar sign curly braces, which is just JavaScript syntax,

213
00:11:20,560 --> 00:11:24,083
has nothing to do with docker and then process.env,

214
00:11:25,090 --> 00:11:27,053
and then here it's MONGODB_PASSWORD,

215
00:11:27,960 --> 00:11:29,660
which I wanna access.

216
00:11:29,660 --> 00:11:32,750
And now these values will be injected dynamically,

217
00:11:32,750 --> 00:11:35,103
and we can set them when the container starts.

218
00:11:36,300 --> 00:11:41,170
So therefore here, I'll now stop my goals backend container,

219
00:11:41,170 --> 00:11:42,837
this node application container,

220
00:11:42,837 --> 00:11:46,900
and then I wanna restart it with specific values passed

221
00:11:46,900 --> 00:11:48,790
for these environment variables.

222
00:11:48,790 --> 00:11:52,690
The default values will not work because of root and secret

223
00:11:52,690 --> 00:11:55,220
are not the username and password I chose

224
00:11:55,220 --> 00:11:57,210
on my MongoDB database.

225
00:11:57,210 --> 00:12:01,290
There, I did choose max as a username, not root.

226
00:12:01,290 --> 00:12:04,940
So therefore, when I read on this container now,

227
00:12:04,940 --> 00:12:07,730
I will add an environment variable here, for example,

228
00:12:07,730 --> 00:12:12,623
with -d, and set MONGODB_USERNAME equal to max.

229
00:12:13,880 --> 00:12:17,640
We could also set MONGODB_PASSWORD to a different value,

230
00:12:17,640 --> 00:12:19,040
but here in my case,

231
00:12:19,040 --> 00:12:21,803
the default value I assigned will actually work.

232
00:12:22,680 --> 00:12:24,440
And of course I could have also used max

233
00:12:24,440 --> 00:12:25,920
as a default value here,

234
00:12:25,920 --> 00:12:28,430
and we wouldn't need to set any environment variable

235
00:12:28,430 --> 00:12:31,020
at all then, but I also want to practice again

236
00:12:31,020 --> 00:12:34,510
how we set our own environment variables.

237
00:12:34,510 --> 00:12:37,870
So with that, this should not work.

238
00:12:37,870 --> 00:12:41,750
And if we inspect the logs of this container,

239
00:12:41,750 --> 00:12:45,380
we see authentication failed.

240
00:12:45,380 --> 00:12:48,160
And the reason for that can be found in the docker file.

241
00:12:48,160 --> 00:12:50,410
We should assign a default value like this

242
00:12:50,410 --> 00:12:51,653
with an equal sign.

243
00:12:52,700 --> 00:12:53,533
My bad.

244
00:12:53,533 --> 00:12:55,790
We should add the default value like this

245
00:12:55,790 --> 00:12:57,310
with an equal sign.

246
00:12:57,310 --> 00:13:01,670
And if we do that, we can now stop the goals backend,

247
00:13:01,670 --> 00:13:03,550
so this running container,

248
00:13:03,550 --> 00:13:05,950
and since we changed the docker file, again,

249
00:13:05,950 --> 00:13:09,343
rebuild the image to pick up this latest docker file.

250
00:13:10,520 --> 00:13:13,410
So rebuild the image with docker build goals-node

251
00:13:14,380 --> 00:13:16,320
and then run the container again

252
00:13:16,320 --> 00:13:20,780
with our MONGODB_USERNAME being set, but not the password.

253
00:13:20,780 --> 00:13:22,183
And if we do this,

254
00:13:24,300 --> 00:13:26,850
we can again, look into the logs here,

255
00:13:26,850 --> 00:13:29,450
and now you see this connected.

256
00:13:29,450 --> 00:13:30,860
And hence, if I reload here,

257
00:13:30,860 --> 00:13:33,363
this application also again works.

258
00:13:34,720 --> 00:13:37,170
So that is working here, and that's how we can add

259
00:13:37,170 --> 00:13:39,540
our own environment variables.

260
00:13:39,540 --> 00:13:41,730
Now with the environment variables out of the way,

261
00:13:41,730 --> 00:13:45,230
there is one last thing I wanna take care of.

262
00:13:45,230 --> 00:13:47,910
At the moment, thanks to the stalker file,

263
00:13:47,910 --> 00:13:51,030
I copied everything from this backend folder

264
00:13:51,030 --> 00:13:53,690
into the container, after the dependencies

265
00:13:53,690 --> 00:13:55,610
have been installed in there.

266
00:13:55,610 --> 00:13:58,970
This is okay, but there are files I'm copying

267
00:13:58,970 --> 00:14:02,820
into the container, which I might not wanna copy in here.

268
00:14:02,820 --> 00:14:05,910
And for that, I'll add a .dockerignore file.

269
00:14:05,910 --> 00:14:08,823
I also covered this earlier in the course already.

270
00:14:09,670 --> 00:14:12,460
Here, I, for example, want to exclude node modules.

271
00:14:12,460 --> 00:14:14,610
If I had this folder here,

272
00:14:14,610 --> 00:14:17,320
I'll also exclude the docker file itself

273
00:14:17,320 --> 00:14:21,570
and exclude a .git folder if it should exist.

274
00:14:21,570 --> 00:14:24,910
And these are some folders which are now simply won't copy

275
00:14:24,910 --> 00:14:26,500
into the existing container,

276
00:14:26,500 --> 00:14:29,430
and the node modules folder is the most important one

277
00:14:29,430 --> 00:14:32,470
simply to ensure that I'm not unnecessarily copying

278
00:14:32,470 --> 00:14:36,410
all my dependencies again after I already did install them

279
00:14:36,410 --> 00:14:38,410
inside of the container.

280
00:14:38,410 --> 00:14:40,510
And that is now really all.

281
00:14:40,510 --> 00:14:42,340
Now, if we would rebuild the image,

282
00:14:42,340 --> 00:14:44,500
we would ensure that the image gets built

283
00:14:44,500 --> 00:14:47,630
without these redundant files being copied in.

284
00:14:47,630 --> 00:14:50,070
And we now have our node application

285
00:14:50,070 --> 00:14:51,440
where we can change the code

286
00:14:51,440 --> 00:14:53,620
and it will be picked up automatically

287
00:14:53,620 --> 00:14:56,490
and where we also use environment variables.

288
00:14:56,490 --> 00:14:59,443
So therefore, let's now move on to the React application.

