1 00:00:00,840 --> 00:00:02,870 Well, let's get this party started, shall we? 2 00:00:02,870 --> 00:00:05,730 I'm going to walk you through using Docker containers. 3 00:00:05,730 --> 00:00:10,300 Specifically, we'll do Windows Server containers in Windows Server 2022. 4 00:00:10,300 --> 00:00:12,080 A lot to do here, so let's get started. 5 00:00:12,080 --> 00:00:17,450 I'm going to bring up VS Code and mention that in order to work most efficiently 6 00:00:17,450 --> 00:00:21,500 in this context there's some extensions here on the Extensions gallery that 7 00:00:21,500 --> 00:00:23,700 you'll want to install just so that you're covered. 8 00:00:23,700 --> 00:00:27,550 There's an official Microsoft Docker extension that gives you 9 00:00:27,550 --> 00:00:30,100 Dockerfile syntax and this kind of stuff. 10 00:00:30,100 --> 00:00:33,930 Some other extensions you'll want are the PowerShell extension 11 00:00:33,930 --> 00:00:36,270 to give you language support for PowerShell. 12 00:00:36,270 --> 00:00:39,180 We're going to be working with the Azure command line interface, 13 00:00:39,180 --> 00:00:42,190 so you'll want the Azure CLI tools as well. 14 00:00:42,190 --> 00:00:44,170 And I think that's good for now. 15 00:00:44,170 --> 00:00:49,860 So let me collapse my extensions, let me right‑click and do a Close to the Right. 16 00:00:49,860 --> 00:00:50,770 And, of course, 17 00:00:50,770 --> 00:00:53,430 I give you this PowerShell file along with the 18 00:00:53,430 --> 00:00:56,670 supplemental work files in the exercise files. 19 00:00:56,670 --> 00:01:00,360 So what I've got here is first of all taking you from soup to nuts. 20 00:01:00,360 --> 00:01:03,650 Let's say we want to set up this Windows Server 2022 21 00:01:03,650 --> 00:01:06,540 machine as a Docker container host. 22 00:01:06,540 --> 00:01:09,720 So what we'll want to do, if we want to support Hyper‑V containers, 23 00:01:09,720 --> 00:01:10,620 on line 4 here, 24 00:01:10,620 --> 00:01:14,560 we'll do an Install‑WindowsFeature to install the Hyper‑V feature, 25 00:01:14,560 --> 00:01:15,920 and that'll require a restart. 26 00:01:15,920 --> 00:01:19,030 To set up the server for container support, 27 00:01:19,030 --> 00:01:21,130 there's just a couple of commands here. 28 00:01:21,130 --> 00:01:23,480 Assuming that your host is connected to the Internet, 29 00:01:23,480 --> 00:01:27,990 we'll want to install the DockerMsftProvider from the PowerShell Gallery. 30 00:01:27,990 --> 00:01:33,340 That will then give you the ability to tap into packages like you see here on 8, 31 00:01:33,340 --> 00:01:35,970 line 8, Install‑Package Name docker. 32 00:01:35,970 --> 00:01:38,570 Both of these commands are going to install the 33 00:01:38,570 --> 00:01:41,460 containers feature on your Windows Server, 34 00:01:41,460 --> 00:01:44,440 but line 8 in particular is going to install the Docker 35 00:01:44,440 --> 00:01:46,560 CLI and the build tools that you need, 36 00:01:46,560 --> 00:01:50,330 and also it'll install the Docker Service on your system. 37 00:01:50,330 --> 00:01:53,310 After you install those binaries, you'll want to definitely, 38 00:01:53,310 --> 00:01:55,580 in fact, you have to restart your computer, 39 00:01:55,580 --> 00:01:58,950 and then you'll find that the Docker Service should already be running. 40 00:01:58,950 --> 00:02:02,060 Let me quickly check that on my terminal environment. 41 00:02:02,060 --> 00:02:03,900 I'll do a get‑service Docker. 42 00:02:03,900 --> 00:02:07,000 Yep, so my Docker Engine is running here, I'm all set. 43 00:02:07,000 --> 00:02:09,510 So at this point, we're ready to rock and roll. 44 00:02:09,510 --> 00:02:12,410 So what we're going to use is, for the most part, 45 00:02:12,410 --> 00:02:14,620 the native Docker command line tooling, 46 00:02:14,620 --> 00:02:17,900 and what we can do is pull images directly from the 47 00:02:17,900 --> 00:02:23,390 Docker Hub by using docker pull, and then you just need the syntax for the image. 48 00:02:23,390 --> 00:02:26,770 And you can go out to the Pluralsight library to get 49 00:02:26,770 --> 00:02:28,930 details on working with Docker Hub. 50 00:02:28,930 --> 00:02:30,780 It's hub.docker.com. 51 00:02:30,780 --> 00:02:33,240 You'll need to sign in with your Docker account, 52 00:02:33,240 --> 00:02:34,420 it's a free account, 53 00:02:34,420 --> 00:02:38,410 and that will give you access to all of the public image galleries. 54 00:02:38,410 --> 00:02:42,040 Microsoft has a whole bunch of them, as you can expect. 55 00:02:42,040 --> 00:02:44,990 So pull is going to download the image to your system, 56 00:02:44,990 --> 00:02:47,970 and then you can run docker images to get a list of 57 00:02:47,970 --> 00:02:50,120 all images available on your system. 58 00:02:50,120 --> 00:02:54,900 And I've pulled down both the nano server and the IIS image. 59 00:02:54,900 --> 00:02:58,220 Nano is just one of the core base images. 60 00:02:58,220 --> 00:03:00,440 It's the thinnest, slimmest one. 61 00:03:00,440 --> 00:03:05,020 An IIS is a servercore image that already has the Internet Information 62 00:03:05,020 --> 00:03:08,500 Services server role installed on it for convenience. 63 00:03:08,500 --> 00:03:10,750 And then here this shows us how we can just start 64 00:03:10,750 --> 00:03:12,660 to go ahead and run containers. 65 00:03:12,660 --> 00:03:13,770 So what are we doing here? 66 00:03:13,770 --> 00:03:15,680 It looks like docker run it. 67 00:03:15,680 --> 00:03:18,530 Now it is an alternative to ‑d. 68 00:03:18,530 --> 00:03:20,900 If you want to run a container in the background, 69 00:03:20,900 --> 00:03:22,690 you'll detach it from your console. 70 00:03:22,690 --> 00:03:24,460 You just do docker run ‑d. 71 00:03:24,460 --> 00:03:28,670 If you want to actually sign into it, in that case you'll do it. 72 00:03:28,670 --> 00:03:31,250 That's going to bind you to the terminal. 73 00:03:31,250 --> 00:03:32,330 Now let me see here. 74 00:03:32,330 --> 00:03:34,700 I don't actually have an image called nano1, 75 00:03:34,700 --> 00:03:38,170 so I'm going to do a fully qualified path here. 76 00:03:38,170 --> 00:03:41,960 Now this first piece is the label of the container, 77 00:03:41,960 --> 00:03:43,460 and this is just the default one. 78 00:03:43,460 --> 00:03:43,790 Yes, 79 00:03:43,790 --> 00:03:46,370 you can rename the images so you don't have to type 80 00:03:46,370 --> 00:03:48,480 those long paths if you don't want to. 81 00:03:48,480 --> 00:03:51,570 And then the tag syntax is to do the label, 82 00:03:51,570 --> 00:03:54,460 colon, and then this could be a version number, 83 00:03:54,460 --> 00:03:59,000 and ltsc is a long‑term support Windows Server 2022 image. 84 00:03:59,000 --> 00:03:59,340 Alright, 85 00:03:59,340 --> 00:04:04,370 so we're going to start an image interactively using this nano server image, 86 00:04:04,370 --> 00:04:07,450 and then here's the exam alert with regard to isolation. 87 00:04:07,450 --> 00:04:14,120 You do ‑‑isolation=, and the options are either going to be hyperv or process. 88 00:04:14,120 --> 00:04:16,490 And it looks like I done goofed, 89 00:04:16,490 --> 00:04:19,920 and I'm going to leave this in the recording rather than snip it out, 90 00:04:19,920 --> 00:04:21,640 because life isn't perfect. 91 00:04:21,640 --> 00:04:22,720 I forgot about this. 92 00:04:22,720 --> 00:04:26,880 This name is where you can give your container a friendly name. 93 00:04:26,880 --> 00:04:30,940 So it looks like I was referencing the container initially just fine, 94 00:04:30,940 --> 00:04:33,070 and I said no nano 2, there's not, yeah, 95 00:04:33,070 --> 00:04:34,570 well, that's just the friendly name. 96 00:04:34,570 --> 00:04:36,360 I'm going to call this servernano, 97 00:04:36,360 --> 00:04:41,550 and this just gives your container an easier handle for you to interact with, 98 00:04:41,550 --> 00:04:41,780 okay. 99 00:04:41,780 --> 00:04:43,310 So let me clear the screen. 100 00:04:43,310 --> 00:04:45,840 Let me right‑click, run the selection. 101 00:04:45,840 --> 00:04:50,170 Another value proposition of containers is that they start almost immediately. 102 00:04:50,170 --> 00:04:54,030 You notice that in less than 3 seconds we're now at a C prompt. 103 00:04:54,030 --> 00:04:58,630 If I do a hostname, this is just the ID of the running container, 104 00:04:58,630 --> 00:05:02,520 but it is a CMD session in this nano image. 105 00:05:02,520 --> 00:05:06,440 And if I do a Directory listing, there's a Users folder and the Windows folder. 106 00:05:06,440 --> 00:05:07,780 You might be thinking, well, 107 00:05:07,780 --> 00:05:11,460 what if we wanted to install software to run on this image? 108 00:05:11,460 --> 00:05:13,820 That's where we get into the build process, 109 00:05:13,820 --> 00:05:16,500 and I'm glad that I thought of segueing that way, 110 00:05:16,500 --> 00:05:17,850 because it makes a lot of sense. 111 00:05:17,850 --> 00:05:20,180 By the way, a common newcomer question is, 112 00:05:20,180 --> 00:05:22,930 once you're in the terminal session like I am, 113 00:05:22,930 --> 00:05:24,080 how do you get out of it? 114 00:05:24,080 --> 00:05:25,650 You can't just do an exit. 115 00:05:25,650 --> 00:05:26,630 It's kind of annoying. 116 00:05:26,630 --> 00:05:29,270 You do a Ctrl+P and Ctrl+Q. 117 00:05:29,270 --> 00:05:32,440 And if you try to do that in VS Code, 118 00:05:32,440 --> 00:05:36,170 there are already key bindings that are mapped to Ctrl+P and Ctrl+Q, 119 00:05:36,170 --> 00:05:40,560 so you'll need to go into your Command Palette and go into key bindings. 120 00:05:40,560 --> 00:05:43,280 I give you some instructions in the exercise files 121 00:05:43,280 --> 00:05:44,830 if you want to know about that. 122 00:05:44,830 --> 00:05:47,860 But now if I do a hostname, we should see I'm on arc2, 123 00:05:47,860 --> 00:05:49,920 so I'm detached from that container. 124 00:05:49,920 --> 00:05:53,570 I can see my running containers by doing docker ps. 125 00:05:53,570 --> 00:05:56,210 And if I want to get rid of this container, 126 00:05:56,210 --> 00:05:58,510 I'm actually going to not only stop the container, 127 00:05:58,510 --> 00:05:59,640 I'm going to delete it. 128 00:05:59,640 --> 00:06:02,100 I'm going to do a docker rm ‑f, 129 00:06:02,100 --> 00:06:04,700 and then I can reference the name of the container, 130 00:06:04,700 --> 00:06:05,750 servernano. 131 00:06:05,750 --> 00:06:09,970 And now if I do up arrow a couple of times, docker ps, it's gone. 132 00:06:09,970 --> 00:06:11,950 Now I do have a note on 21. 133 00:06:11,950 --> 00:06:13,750 I'm not going to go into it in this demo, 134 00:06:13,750 --> 00:06:16,860 but you should know that Windows Admin Center also has a 135 00:06:16,860 --> 00:06:19,640 graphical overlay for working with containers. 136 00:06:19,640 --> 00:06:22,740 Check the exercise files for some more details on that. 137 00:06:22,740 --> 00:06:25,740 I'm going to stay with the command line interface, 138 00:06:25,740 --> 00:06:29,860 because this is much more likely what you'll be quizzed on on your AZ‑800, 139 00:06:29,860 --> 00:06:33,550 but just know that there is a nice graphical front end to the containers 140 00:06:33,550 --> 00:06:36,300 feature that you can add into Windows Admin Center. 141 00:06:36,300 --> 00:06:39,710 Alright, so the way you'll set up your build environment is as follows. 142 00:06:39,710 --> 00:06:41,940 I already have it set up in VS Code. 143 00:06:41,940 --> 00:06:45,140 I've created a work folder called iis‑website. 144 00:06:45,140 --> 00:06:49,990 My goal here is to deploy a container that has IIS installed, 145 00:06:49,990 --> 00:06:53,350 and not only that, I want to pre‑stage it with content. 146 00:06:53,350 --> 00:06:56,760 So I have in my work folder a file with no extension 147 00:06:56,760 --> 00:06:59,060 called Dockerfile with a capital D. 148 00:06:59,060 --> 00:07:02,010 Now the reason it shows up with a correct icon here is 149 00:07:02,010 --> 00:07:05,020 because I set a custom File Icon Theme. 150 00:07:05,020 --> 00:07:06,110 These are just extras. 151 00:07:06,110 --> 00:07:07,330 I love VS Code, 152 00:07:07,330 --> 00:07:12,560 and I will take any and every excuse I can to teach people about it. 153 00:07:12,560 --> 00:07:15,580 And the reason why we get syntax highlighting and 154 00:07:15,580 --> 00:07:19,170 auto‑complete and snippets here, it may be small on your screen, 155 00:07:19,170 --> 00:07:22,580 but in the lower right corner, the Language Mode is set to Auto Detect. 156 00:07:22,580 --> 00:07:25,290 And because I have the Docker extension, 157 00:07:25,290 --> 00:07:28,360 VS Code is recognizing this as a Dockerfile, 158 00:07:28,360 --> 00:07:31,060 so you do get IntelliSense and all that good stuff. 159 00:07:31,060 --> 00:07:35,470 Now this is about as simple of a Dockerfile as I could possibly think of. 160 00:07:35,470 --> 00:07:38,610 You always start with a FROM where you get your base image. 161 00:07:38,610 --> 00:07:39,370 In this case, 162 00:07:39,370 --> 00:07:42,210 we're going to grab the servercore/iis image that 163 00:07:42,210 --> 00:07:44,080 I've got already on my machine, 164 00:07:44,080 --> 00:07:48,310 and then we're going to use the ADD keyword to take the wwwroot 165 00:07:48,310 --> 00:07:51,500 directory that I have in my work folder and copy it into the 166 00:07:51,500 --> 00:07:54,940 container under the path root /inetpubwwwroot. 167 00:07:54,940 --> 00:07:57,320 And you know if you've worked with IIS that that's the 168 00:07:57,320 --> 00:07:59,640 default content directory in IIS. 169 00:07:59,640 --> 00:08:00,650 So that's how that works. 170 00:08:00,650 --> 00:08:04,780 And in wwwroot, I just have an index.html file. 171 00:08:04,780 --> 00:08:07,680 Actually, it looks like it doesn't have any content in it right now. 172 00:08:07,680 --> 00:08:08,650 Let me fix that. 173 00:08:08,650 --> 00:08:11,480 And this is just a hello world page, as you can see. 174 00:08:11,480 --> 00:08:14,270 It's got a head and it's got an h1, 175 00:08:14,270 --> 00:08:17,520 just to let us know as a proof of concept that it's working. 176 00:08:17,520 --> 00:08:20,090 But you presumably would have all the scaffolding, 177 00:08:20,090 --> 00:08:24,070 the file system artifacts for your website staged in that folder. 178 00:08:24,070 --> 00:08:25,330 Now just for completeness, 179 00:08:25,330 --> 00:08:28,800 I have a couple other Dockerfiles that are a bit more complex. 180 00:08:28,800 --> 00:08:31,650 Here in this example we're grabbing it looks like a 181 00:08:31,650 --> 00:08:33,480 servercore as our base image, 182 00:08:33,480 --> 00:08:37,040 and then we're using the Docker CLI RUN command to 183 00:08:37,040 --> 00:08:38,550 run a command into the container, 184 00:08:38,550 --> 00:08:42,440 so this would allow us to do things like setting up server roles, 185 00:08:42,440 --> 00:08:44,370 downloading stuff, etc. 186 00:08:44,370 --> 00:08:47,480 There's an EXPOSE keyword, where you can expose ports, 187 00:08:47,480 --> 00:08:48,550 networking ports, 188 00:08:48,550 --> 00:08:53,100 and then you can define an ENTRYPOINT for that container as well. 189 00:08:53,100 --> 00:08:56,640 Lastly, I have a much longer sample Dockerfile here. 190 00:08:56,640 --> 00:09:00,090 Again, this looks like it's starting from the servercore base image. 191 00:09:00,090 --> 00:09:03,140 We've got several RUN commands to enable features. 192 00:09:03,140 --> 00:09:05,140 Again, there's not too much to this, 193 00:09:05,140 --> 00:09:09,000 but I just want to transmit the fact that in these Dockerfiles we're using a 194 00:09:09,000 --> 00:09:14,330 domain‑specific language from Docker that allows us just to declaratively 195 00:09:14,330 --> 00:09:17,950 define how we want the resulting image to look. 196 00:09:17,950 --> 00:09:20,790 So let's come back to our containers.ps1. 197 00:09:20,790 --> 00:09:22,020 Let me clean up my tabs. 198 00:09:22,020 --> 00:09:25,190 And the way you do this, assuming you're in that directory, 199 00:09:25,190 --> 00:09:28,000 which I'm not actually, so let me do a, 200 00:09:28,000 --> 00:09:30,280 I've got a neat extension here that allows us to 201 00:09:30,280 --> 00:09:32,050 copy file path to the clipboard. 202 00:09:32,050 --> 00:09:35,390 So let me copy the current file path to the clipboard, 203 00:09:35,390 --> 00:09:40,780 and let me do a cd, and then I want to cd into my iis‑website. 204 00:09:40,780 --> 00:09:43,520 We want to be in the context of our build folder, 205 00:09:43,520 --> 00:09:46,280 in other words, the folder that our Dockerfile is in. 206 00:09:46,280 --> 00:09:48,180 And what we do here is docker build, 207 00:09:48,180 --> 00:09:50,640 and then I'm going to add a tag with the t keyword, 208 00:09:50,640 --> 00:09:54,000 and I'm going to call this docker build ‑t tim, 209 00:09:54,000 --> 00:10:00,360 that's me, the owner, /iis:, and then I'm going to do v2022, 210 00:10:00,360 --> 00:10:04,080 space, and then the path to where your assets are. 211 00:10:04,080 --> 00:10:05,560 I'm in the current directory. 212 00:10:05,560 --> 00:10:08,400 You don't have to be, you just specify the correct path. 213 00:10:08,400 --> 00:10:11,320 I put myself in the current directory to make this work. 214 00:10:11,320 --> 00:10:14,230 So let me right‑click, run the selection, and there you go. 215 00:10:14,230 --> 00:10:18,560 So if I do a docker images, I should be able to see that. 216 00:10:18,560 --> 00:10:24,330 Yeah, right up here, tim/iis:v2022, and each image gets its own unique ID. 217 00:10:24,330 --> 00:10:26,070 Now as far as the networking stuff, 218 00:10:26,070 --> 00:10:28,100 we don't need to get too deep in the weeds there. 219 00:10:28,100 --> 00:10:33,500 We can see the Docker network topology on our host by running docker network ls. 220 00:10:33,500 --> 00:10:38,050 And I have a Hyper‑V External Switch that I've set up for my server. 221 00:10:38,050 --> 00:10:40,030 If I go to Virtual Switch Manager, 222 00:10:40,030 --> 00:10:44,460 I have my External Switch that's bound to the network interface on the host. 223 00:10:44,460 --> 00:10:47,710 That's called transparent networking in Docker syntax. 224 00:10:47,710 --> 00:10:50,170 You can create your own transparent switch by doing 225 00:10:50,170 --> 00:10:54,240 docker network create d transparent, and then giving it a friendly name. 226 00:10:54,240 --> 00:10:57,290 But I'm actually going to reference the mapping that's 227 00:10:57,290 --> 00:11:00,510 already here to my Hyper‑V External Switch, 228 00:11:00,510 --> 00:11:03,080 which, as you see, is using the transparent driver. 229 00:11:03,080 --> 00:11:06,930 Lastly, to run our new image, we can do a docker run, 230 00:11:06,930 --> 00:11:13,380 and I'm going to call this az800‑iis to give it a nice user friendly name, 231 00:11:13,380 --> 00:11:19,880 d for detached, isolation is hyperv, network maps to the desired network, 232 00:11:19,880 --> 00:11:24,290 p 80:80 means that I'm mapping port 80 into the container, 233 00:11:24,290 --> 00:11:26,880 and out of the container on 80, and then lastly, 234 00:11:26,880 --> 00:11:30,970 the name of the container is tim/iss:v2022. 235 00:11:30,970 --> 00:11:36,110 There, and let me right‑click this and run the selection. 236 00:11:36,110 --> 00:11:41,140 Now the problem here testing this is that because we're doing External Switch, 237 00:11:41,140 --> 00:11:44,680 then this container is going to pick up an IP address 238 00:11:44,680 --> 00:11:47,370 from my host network's DHCP server, 239 00:11:47,370 --> 00:11:50,740 so it's going to be a little bit of work to try to track down 240 00:11:50,740 --> 00:11:53,270 that IP address that I don't want to mess with. 241 00:11:53,270 --> 00:12:00,540 So let me start over, let me do first of all a docker rm ‑f az800‑iis. 242 00:12:00,540 --> 00:12:05,450 And then let's start this again just using the default NAT networking. 243 00:12:05,450 --> 00:12:09,650 I'll call this az800 iis2, run this selection. 244 00:12:09,650 --> 00:12:13,310 Now if I bring up Edge and make a connection to localhost, 245 00:12:13,310 --> 00:12:15,250 I can see the page right there. 246 00:12:15,250 --> 00:12:16,580 Proof of concept, right? 247 00:12:16,580 --> 00:12:21,380 Let me do again a docker rm f az800‑iis2. 248 00:12:21,380 --> 00:12:24,470 Now you don't need to do docker rm ‑f. 249 00:12:24,470 --> 00:12:27,490 That just assumes that you want to stop and kill the container. 250 00:12:27,490 --> 00:12:33,240 We could do docker kill az800‑iis2, and that would stop the running container. 251 00:12:33,240 --> 00:12:35,740 If we do a docker ps, there's nothing running, 252 00:12:35,740 --> 00:12:40,000 but if I do a docker ps ‑a, I can see that it's still there, 253 00:12:40,000 --> 00:12:46,000 it's just stopped, it's Exited. We can do a docker rm to get rid of it, and were cleaned up.