 It's a good time appropriate greeting everyone. I am Scott McBrien and you'll notice that there is neither a person to my left or right today because I am running the show solo which you shall be extremely scared of. So, let's start off by just talking about what our show is going to look like today. So we are on episode 47. And we're going to talk about containerizing your application. If you're interested in our show notes last time where we covered key lime. Let's go over those out at our show notes or review the episode on YouTube. All right, so today I thought we might kind of roll back a little bit and talk about containerizing applications. When we started the level of our actually when Langdon started to level up our year plus ago. The goal was to take like practitioners of containers and talk about how we can move from individualized containers into a more orchestrated environment like Kubernetes and open shift. That is still our intent and you'll notice that several of our shows in the recent past have been talking about some of the technologies to get us into open shift like the CI CD pipelines that we talked about a couple episodes ago, or attestation like we talked about with key lime just the last episode. But today I thought we might kick it a little bit old school and talk about, well, how do you build a container. And there are a couple different ways that you can do that. You can certainly use some open shift technologies like sourced image where you take your source code and through a CI CD build pipeline, build yourself a container image all the way down through deployment. But maybe you're not ready for that maybe you're just starting your container deployment journey or container engineering journey. So that's what we're going to talk about today. So, if you would like to follow along. I'm going to throw a URL in the chat. I'm kind of going through this lab exercise that I've written on taking a existing RPM application and containerizing it. So let me go ahead and share my screen again. So what we're looking at here is a virtual machine. I've run several of the red hat container tools. So the first thing I want to do is I want to pull down a base image now I could build this through scratch, but red hat provides several really handy base images for me to use through the universal base image program, or we also shift rail images if you are a real subscriber with different things like databases and whatnot. The nice thing about universal base images that we ship is that they are freely redistributable. So while they have a subset of the red hat enterprise next contact content available for them. You can build your container off of them and then give it to other people without the need for a red hat subscription. So what I'm going to do is I'm just going to use build up to pull down a UBI eight image. We had Scott McCarty on a couple shows ago we talked about UBI micro which is one of the four UBI images. I'm using the standard UBI image here just UBI. So the others are micro which we talked about it's really small has about 13 packages that make it up. Which has a micro DNF implementation in it so you can still install software from it. I'm using standard the regular UBI and there's also one called UBI net, which we named the multi service image which includes a full system de deployment inside the base image so that you can start up multiple services at the same time. Alright so when I pulled it down. I have this working container created for me so build a one ahead and pulled it from the image registry, and then has mounted it into my directory structure so that I can place files and work with it. And at its core a container is really just a collection of application files. Right so we're going to run this on our container host, and we'll see it show up as processes in the container hosts process management. That's a little bit different than how virtual machines act with a virtual machine, the host hypervisor of the virtual machine sees a process for the virtual machine it has like a whole bunch of memory and CPU dedicated to it. We're not able to see visibility of what's actually happening within that virtual machine from the hypervisor. It's completely segregated off into a separate environment. But with containers, we're actually using the container host, and we're executing processes on the container host which means the container host is able to get visibility into what's going on inside of the containers that are running. The containers themselves are partitioned off from the host operating system. So the inside of the container image when it's executing in its container environment. It's not able to see other containers, or the host operating system either. It's, it thinks that it's kind of a world into itself. And in reality, we can see it from behind the double sided mirror on the container host operating system. So I've got this UBI working container mounted into my directory. And for this first example, I'm just going to take an existing application that's built into an RPM, and I'm going to install it in the container and then I'm going to run it. If this was a Red Hat RPM, the UBI images already have the Red Hat repositories configured for them so I could do a yum install whatever, and it would install it from the Red Hat repose. But I want to take my third party application and install in this container. And since the container or the application is already RPMized, I could pull down the RPM and then locally install it, but maybe it needs dependencies too. So I'm going to go ahead and install a repo inside the container that references where my software is going to come from. And the software I've chosen for my example is from EPL, the extra packages for Enterprise Linux, which is a huge repository of extra software that you can run on top of REL distributions or REL based distributions includes things like language libraries and different applications and utilities. And here we're going to install this like doofy text based video game. That's the application that we're going to containerize today. All right, so when I ran my command here. Okay, so I'm using Builder to help me build my container image. I want to run a command inside the UBI working container. And so what's going to happen with this command is we actually change root into the file system that's been mounted for our working container. And then we're going to execute this yum install inside that change rooted environment. So when we're executing this command, it's actually happening inside the container image, not outside on the host system. And so you can see that it installed the EPL release and we're all good there. But just to prove that right if I'm on the host operating system. And I look to see if the EPL release RPMs installed the host operating system reports that it is not right because I actually installed it within my containerized build environment. If I do this build a run. I'm going to run a command inside my working container image right inside the container image it says yes I have successfully installed this RPM right so not changing the host change rooting and operating within this contained container environment. So my next thing is I'm going to install the software that I have from the EPL repo. So again I'm using a build a run command to do a yum installation. And it's pulling down all of the packages it needs and because it had some dependencies. It also had some dependencies from the Red Hat Enterprise Linux repos provided by UBI. It also had some dependency repos from Apple. So because I had installed that repo definition in the container. When I did a yum install of this RPM went ahead was able to resolve all the dependencies that RPM required. All right, and then I'm about to commit this image. I want to reduce I want to make sure it's as small as I can make it because as I start to ship this from my local image repository to either a shared image repository for other people to use, or other systems for them to use. I don't want to transfer around useless data. So I'm just going to inside my working container do a yum. I'm just going to clean up the cash inside of that containerized environment. All right, so I'm not carrying around all these RPM files and data files that were downloaded to support those yum transactions that I executed. All right. So now I've got my container image, got my software in the container image, and now I'm ready to make a runnable container image. So I'm going to use build a commit to create from the UBI working container that I've been working within. I'm going to create an image called moon buggy right and that's the RPM that I have installed in it. All right, if I do a pod man images. Right there's my new container that I just created. So now that I have a container image, I can then use pod man to execute that image on the host system. So I'm going to run pod man run. And I'll go back and talk about that command just second. But this is the container image that's running. Here's my little application. Go ahead and run it. It's a text based moon patrol clone. So there's a crater coming up. Let me jump my moon rover. Oh, got to do it again. And again, and I didn't make it my moon rover. All right, so when I close the executable. Which is the application and then it closes the container because the application running within the container was terminated. All right, so when I ran it. I ran it like this. Pub man run when I execute my container it means it's interactive. So I actually want to use the the terminal that I'm connected to to show me the contents of the running container and that was important for moon buggy because it was actually interactive application. And then the executable that I want to run inside that container is this user been moon buggy executable. So I started this interactive session with my container. And then behind that I ran the moon buggy application. All right, so that that's pretty much containerization and that shall right get your container image place your files within it we used a RPM to make our to position our files right we installed the RPM which then put the executable contents wherever and then we ran it. I mentioned earlier that when we run it, we actually get visibility into that from the host operating system. We'll just recall it from history. All right, so here it is running again inside my container. I'm going to go over this other terminal on the container host. All right, and we can see that when I look at the process status of what's running on the container host. This is my cod man run right so that's the container execution environment running. And then, if I look for the actual executable that I want to run, I can see from the host that there's this application right there too. So we're executing the container environment and then within that containerized environment that partitioned off area of memory CPU file access. This application underneath that as well. And when I quit out of my executed container. If I take a look at the same process status, right that that process was killed, because I terminated the container which terminated the processes running within it which then wipes it out of the host operating system. Okay. So that's if you have an already existing RPM that you're trying to run inside a container so if you've already taken your software. And you're running it natively on a Linux distribution today, you can take that already packaged software and just like installing the container and there you go you've containerized your application. In the core containers are really a file archive. If you think about it, what do we do there we took our RPM and we installed the container which then sprinkled files around in this change rooted file environment of inside of our container. And so containerization one of the reasons people cite to do containers is portability of your application. If all your application contents is in the container, and everything that needs is provided by the container image all the libraries it needs all the executables it needs all the configuration files it needs. You can take that bundle of stuff and execute it on other host operating systems to. And then you're not reliant on things like what version of some other software is running on. The container host system right if you're bringing all of your requirements with you. Then you don't have to worry about what the host operating system is providing because you've brought all the things with you. And so it's like, traditionally, we had like a potluck picnic right where everybody who attends the picnic brings a dish. And if you wanted to desert at the picnic. And bring that dessert dish. If you were responsible for the, the potato salad or the hamburgers like you brought your thing and everybody else had to bring their thing in order to get a full menu at your, at your event. But in container world, you actually go and get all of the things that you need for your happiness, and you bring the entire meal yourself. It doesn't matter what the other people at the event are bringing, you've brought everything you need, or everything that you want to have a successful and fun time. So, you know, that goes beyond, you know, bringing cookies or whatever maybe you bring a pinata to because you enjoy having that at your picnic. So, that's really what containers are there at archive file archive and a way of running executables to stay within that archive, all of the provided files. All right, so if it's really just an archive. Then, why do we need an RPM. So let me reload this box so I got a fresh system. And I'm going to do another one. But this time, I'm going to slurp a bunch of files down from GitHub. And I'm just going to put them into the container. And so I'm not going to have a pre packaged RPM is application. I'm literally going to have a collection of executable files that I need to position within the container in order to then have everything set the way I want and deploy it out into the world. All right. So while we're waiting for this just a quick plug. I rely on you, the audience members to provide some direction on what you would like to see happen here. So I'm doing some demos but as you have questions, please post in the chat. If you would like to see something I'm not showing you, please put it in chat. And I see that we've got a few people watching so let's tell me what you want to see. Let's go through this and then we'll see what you guys want to know about. All right, so first things first, I'm going to pull down my, my base image again. And for this one I'm also going to use the standard UBI rel 8 image. All right, and just like before it created this this working container image melted it in the file system so I could work with the contents of that container image. And because I know that I'm going to be positioning a web application. I'm just going to run a yum install. So I'm pulling the Apache RPM out of the UBI repos and installing it within my UBI working container image. And then unlike last time where I like to hold it what thing to execute this time when I run the container I'm going to do it in a disconnected So when it's disconnected I don't have a shell into it by default I'm just going to start it up and I expect all the stuff that it needs to start up. And because this is a web application, and it is using Apache as its web server. I'm going to go ahead and inside the container image. I'm going to change my configuration so that system D will go ahead and start the HTTP process when the container starts. So I'm going to do another build a run inside of my container. So when it when the container starts. Apache will also start. All right. So now I've got my base container image kind of where I want it. It's got the prerequisite software that I needed to support my workload in it because I'm just going to be positioning web application. And so the next thing I'm going to do is I'm going to pull down a copy of that web application and then move those files over into my container. So I'm going to get to actually hold on. There's one more thing I want to do to bear with me as I redo a couple of steps here. This time I'm going to also do it as a regular person, instead of building and executing my containers route because that gives us some interesting stuff there in a bit. So let me redo my container image is this individual person. So we'll install Apache in there. And then I'll go ahead and enable Apache there too so when I run the container image it automatically starts up the service. And I see our production saying hello and chat hello our production shout out. So system CTL. Okay, so now we're back to where we were before. So I'm going to go ahead and get cloned. This software that I've got out in GitHub. Well it's not mine. I'm using someone else's as an exemplar course. So what we're looking at is this, this JavaScript based application called clumsy bird, which is just a JavaScript app that you can run. It's a video game, a really simple video game. All right, so now here I pulled it down from GitHub. And this is on the host style the JavaScript and all the index content all the web content I need, but I need to get this content from my local working directory into the container image. So I'm going to build a copy. So I'm going to copy from my host operating system into my UBI working container. And so we're looking at is I'm going to copy from my local directory clumsy bird which is right GitHub, cloned that repo, and I'm going to take all those files, and I'm going to put them in var www HTML inside the container image. The other thing I'm going to do is I'm going to configure a port. So, the process that starts up a boot is going to listen on port 80 right so my Apache web server is going to listen on port 80 inside the container. And now let's do a build a commit. And I see more people wanting shout outs like Anna mesh saying, so I'm going to take my UBI working container I'm going to commit it as a new container image called clumsy bird. So now if I do a pod man in the list. Yep, there it is. So here's the UBI that I started with. And then here's my new committed clumsy bird container that I've just built. Alright, so the last thing I'm going to do is I'm going to run my container. All right, so, last time I containerized my image I had an interactive application and I want to run so when I ran the container I use dash it to indicate that it was an interactive executable that I wanted to run I wanted to have that terminal session and be passed through to the content inside the container. This time on Pogmat running dash D detached from it just going to run out there, kind of like a Damon, and whatever is running in it is going to be running in it. Additionally, because this is a web application. I need to be able to get traffic to that web application in the container. So dash piece that's a big port mapping. So that port 8080 on the host operating system. When I receive connections to port 8080 on the host operating system. It's really going to redirect that to port 80 on the container clumsy bird. That's interesting that I typo something in my creation. So he says that he doesn't recognize that, which is weird. Let's do this. Instead of in it, let's do. Maybe that's right. Alright, let's try one more time. There we go. Alright, so we're running. So what I'm going to do is I'm going to open up for 8080. Oh, so that's no bueno. I'm completely flummoxing this demo. What could possibly go wrong with a live demonstration you ask while you're looking at it. All right, so let's let's just see what's happening here. All right, so we're going to move PS. Interesting. All right, so this guy ran, but then he exited immediately, which would be a problem. And he exited immediately. Okay, so it looks like my change to Apache is not working. I like our show producer is telling everyone to like and subscribe and share when my demo goes down in complete flames. Oh, let me try one other thing. Let me go back to being rude. Maybe it's a permissions thing. I don't think so, but let's double check. Okay, so we're looking good there. I pulled out my get clone and I'll copy my contents into my root owned container. And then I'll do my config. I'll do my commit. And then, so that's working. Let's see if I do it to 8080. Let's try one more time to look at port 8080. Oh, and there he is. So it's complaining about a knit from my non root container. So let's see if we can figure out what's happening there. Oh, by the way, this is me playing my video game inside my container. All right. So what we're seeing is a differential between the container image running as a regular person and the container image running as root as we're just working fine as a regular person it's not running fine. So let's see what that might be. And I wonder just for curiosity, my container over here. So if I run a sudo where I escalate the privileges as root to see if that no longer has the problem so if I basically sudo run my container so the containers running as root. If that alleviates my problem that I know it's a rootless versus root container, instead of a problem with the container image that I had built as a non privileged user. So that's where I'm going with this. And the reason I'm stopping these root owned containers is how am I going to bind to port 8080. If I already have something bound for 8080. So I'm going to kill off these containers that are over here and run my container as a non privileged user. All right, so that looks like it might be working. So he's running let's make sure that it is operating correctly. So we're looking at as a problem between running as a un privileged user versus running as a privileged user. All right, so let me kill this off and we'll figure out why that might be the case. Okay. But if I'm a regular person I bet it's something as dumb as we can't execute the knit command inside our working container. Hmm. I wonder if I pull down my the bull UBI eight multi service image. If that's the problem, let's try that. So what I'm thinking is maybe the problem is that my non root owned container is trying to do in its stuff using the hosts system D. And as a non root user you can't do those things helps me spell your registry correct. Okay, so now our container images called UBI networking container and I'll just go through and add the same things as before. Oh, and I see that Jonathan Tucker is giving me some advice. He created the Apache config, then told the OS to auto run a HTTP it would be at the root level connecting the port, connecting via the port you up so I'm using a port 8080 in the, in the starting of the service. And as an unprivileged user I should be able to attach for 8080 and that's actually like thing that I want to talk about later. When I get to actually working on my thing. And this is one of the, I think the challenges of doing rootless containers, which is pretty fantastic from a security perspective, but just like when you're running. It does route and you can do what you want and then you switch over to being a regular person all of a sudden you can't do what you want. That's where we're, that's where we're into some problems. Let's position our software. All right so let me. So, just to make sure that we're all kind of thinking the same thing. I'm going to change this. No, that's correct. I'm going to admit it. If you switch off the auto run, then in the call from the user. Okay. So, yeah, that might be a good thing to let's, let's see this through and when it blows up in my face then I'll go back and adjust the, the other non system d image. And let me just before I run this I just want to make sure. Okay, let's see if it's running. So he's running. And if I connect to the port, or we're making progress. All right, so. So, Jonathan suggests that what we should do is turn off the auto run instead make it so that when we make our executable here. We want to run our Apache service. So, you want to run. Oh, before I do this, I need to kill off my other one free up report. Good job then I think this is what you're suggesting. Subdetach let's run it interactively. Still no. All right, so here we are inside the container I. Right here. Interactively ran the bash shell. This is user. That's been HTT PD. Yep. Well, this is really frustrating. All right, well let me. Let me back up and like, put a pin in this and go okay, I clearly need to do a little bit more research on my demos before I, before I run them. It's my own fault for trying to get fancy and do rootless containers without preparing or testing in advance because it's a live demo would possibly go wrong. What I was trying to get to is to show you what it looks like when people run containers as non root users. So let me reload this to get a fresh box one more time. And we're going to do the RPM example so I can show you what it looks like for non root users. I clearly my container worked because at one point I ran the. Oh, sorry Jonathan I switched gears before I saw your chat. So that that is a good idea. We can build the box back after I do this one quick thing, because it should be running and I also want to talk about like offering ports to non root users, because one of the consistent problems with running rootless. Is that, you know, inside our container environment, we were attaching port 8080 a non root owned port to port 80, which is a inside the container that's where the services running. And a lot of people want to direct port mapping right port 80 on the whole should go to port 80 in the container. And that has been a challenge for rootless containers for a while but we've got a really interesting solve for that now. All right, so let me just quickly pull down my image. All right, and let's install my, so my software again. And this is reverting back to the text based moon patrol example. I'm just setting up a container with that. All right, all right so now we're running it. And then of course I did this incorrectly didn't I did it all as a root for that search users. And there's some of you who might be following along using the lab. Those boxes are, they last for about 30 minutes. And you can see that when I wanted to get a fresh one I just reloaded the page and that gets you a fresh one. It's good to see your rescue. So, I think we're about back to where we were with the. Thank you for bearing with me. Alright, so I'm saving my image. This is a container called moon buggy. All right, and then I'm going to run it. All right. So, I did all these steps as a non privilege user named well. And we remember earlier when we were running the container image we could look at the host operating system and see the process. Well, when you do the running of containers as a non root user. We're running on the host operating system as the same person as who's executing the container right so because I executed this container as the real user. All processes spawned from within the container happen on the host operating system as the real user, which means this application only has the permissions and capabilities of this person. So that's what's causing our problem that we're having with my web application one is that we're running with the rights and privileges of this unprivileged user, and we're trying to do something in our container not accounting for that. So, either we're trying to make make a call to system D on the host which we're not allowed to do as a regular person, or something. So I have to go back and kind of figure out what that is. I'm not live. And with with folks watching what's happening and I'll provide an update on our next show just quick like what I was able to determine, and why it was a problem. So I'll get to doing that in the next week. But so one of the other things that we have with with rootless running containers like it's cool that we get to run as an unprivileged user because then as a systems administrator running in the operating world. I don't have to worry about container developers running their apps as root, and not knowing what those apps are doing on my host operating system. So running as a non privileged user, I can feel comfortable that like they're allowed to do whatever a non privileged user is allowed to do, which I'm less concerned with than what they would be allowed to do, running with root authority. So one of the tagging problems is that we have this like port mapping that we have to do when running it, because if you're running as a non privileged user, you have to attach to a non privileged port. So that means that anything under port number 1024 was off limits for you as an unprivileged user. So we now have a sis control. We now have a sis control. All right, called IP unprivileged port start, which identifies where the unprivileged ports are sorry where the privileged reports. We'll try that again, where the unprivileged ports will begin. So if you're a regular person, as long as you're using a port over 1024. You're good to 25 to 26, all the way up next self out. But if we tried to bind ourselves to port 80 as an unprivileged user, because that's under this setting, or under this value of 1024 we'd be told no as a regular person. Well as root, you can change this. So by changing this sis control value on the host operating system for your containers, you're now allowing unprivileged users to bind a ports higher than this one. So from port one to 79 only root can attach those but port 80 and up anyone on the system can attach services to listen on those ports. This is a sis control. So it is dynamically changed in the colonel's memory. And if you wanted it to change permanently, you'd go over to Etsy CTO.com or use a parameter like a tune D profile to change it persistently. And I'd refer you to the red hat Enterprise Linux presents live stream if you're interested in more rel stuff. So this is in proxies net IPv4 and it was called it's unprivileged port start IP under privileged port start and typically is not serious slashes. All right so that would make this a persistent change and every time the system will reboot it'll go ahead and adjust that unprivileged board range for you. All right. So I think that's roughly it. Lots of stuff I will I'll figure out what I was doing loosely incorrect and and provide an update on our next show quickly at the beginning before we get into our guest. I will also have at least one co host with me next time to maybe save me for myself because like demos what could possibly go wrong. And before we leave. I wanted to talk about sweet sweet internet points. So for those of you who have watched the show before we have this thing called sweet sweet internet points where you can go out to the URLs below and put in your level up our code and it will give you the ability to accumulate sweet sweet internet points and this is our leaderboard as it stands today. So last episode you may recall that Narendra and NLH ACM were tied at 6300 points apiece and at one point Narendra was so far ahead of everyone. No one could possibly challenge them. But somebody closed the gap. But now Narendra is narrowly in the lead by a mere 100 sweet sweet internet points over his closest competitor. Also we see that folks like Noah friction and bacon fork are starting to accumulate points and are moving into a position to maybe challenge the leader. Bacon fork has moved up from further down in the in the standing so congratulations bacon fork on that great progress and making it higher up on the leaderboard. Who knows what sweet sweet internet points are good for. But we we now as you may have noticed my shirt have actual swag that says level up our I know that we have been promising that for years and years. It exists. We have it. But yes, so for now we're still doing sweet sweet internet points. So join us next week for another episode of the level up our hopefully at least one of my companions. I think Mr. Randy Russell will be with us and hopefully Jafar will feel well enough to return with us as well. I think that'll do it by everybody appreciates coming today.