 Hello guys, this is Arun and this talk I'm going to talk about the best and recommended practices to start building containers. Let's go ahead. All right, so this is my terminal and I've got my Docker client and server installed. So if I want to spin up a container, so what can I do is Docker run-dit then I could give the name of the container and then the image name which is stdbd. So in this case, I'm going to start Apache container. All right, so the container is up and running and then let's validate that Docker InSpec web and if I do a graph of IPAD, I could get the IP address of this container and if I do a curl over it, let's say is 200, so which means the container is totally working fine. But here, there are a few glitches. If I want to see what exactly are the privileges attached to this container, I could always use PSCAP which is a part of lib and the utils and can be installed with the help of apcat. All right. So what I'm going to do, I'm going to see the capabilities attached to this container Apache. All right. So these are the capabilities attached to this stdbd container by default and these privileges are coming by default. Okay. But do I really think that I need all these capabilities? No. Not at all. All right. So what if I drop each and every capabilities added to this container? All right. But before that, I would like to give you a brief about the Linux capabilities. So basically for a process as the container is a process and in order to do something or achieve something with the help of kernel, a process has to have few privileges attached to it so that it can talk to the kernel via system call and can use the specific functionalities of the kernel with that attached privileges. So this is all about the Linux privileges. All right. So let's build a container with no privileges. So what I could do is kept drop equals to all. So this is a flag which is coming out of the box from the Docker and can be leveraged to drop each and everything coming by default for a container. All right. So I'm going to give a different name to this container. Let's say web 01 and I'm going to use the same image. All right. So it says the container is up. Okay. Let's see Docker PS. Okay. I could see only one container and if I do Docker PS-A so you could see there is a container which just got exited. All right. So this was a container which got exited. As you could see this is the hash ID of that container which we spawn with no capabilities basically by dropping all the capabilities. All right. So in order to see what exactly has happened with that container we could always say Docker looks in the hash ID of the container basically or the container ID or the name of the container. All right. So if I see here there is an error which says could not bind to this address 0000 call an AT. So basically Apache leverage this port and this container basically is not able to bind to this address basically to this socket and why exactly is that happening because we have dropped each and everything and the capability basically the privileges for this container to bind to any of the address was coming with some of the privileges from here and in order to tell you this was the privileges. This was the exact privilege which allow a process or basically a container to bind itself to a certain port or address and as we could see we have dropped each and everything. So that's why this error. All right. So now I have dropped each and everything and on the contrary I could have these many capabilities attached to my container by default. So how could I know what exactly do I need in order to spin up a container with the minimal privileges or minimal capabilities. All right. So for that there is a utility system tab which has been introduced by your dad and which can be used to trace system call process thread or memory allocation. All right. So here we're going to trace this process basically. All right. So yep. So I have kept each and everything in a documentation over GitHub so that it could be accessible to each and everybody after this talk. All right. So this is how you could trace a process. There is a steepie script we have to write and this is the best script basically. There are certain examples given on the redhead side which I have documented here in my documentation here here. So you could always use a script and all we need to trace is a process which is user has been as a DVD. And if you go down it would give you the studio and later at some point it would give the capabilities which are being used by this process. So if you could see the DVD process is using the capability set GID set UID and net bind service basically for binding itself to a certain port or an address. So basically we need these three capabilities. Nothing else. If we compare to a list of capabilities which are getting added by default. All right. So what if I start a container with only these capabilities. Let's see. Docker run hyphen DIT I'm going to say a name web 02 and I could see STDPD. But before that I would say cap drop equals to all. They start with dropping each and everything and then add one by one set UID hyphen cap and it goes to set GID and cap add. What was that net bind service net underscore bind underscore service. Okay. Let's say this container is up and running. Let's see. Okay. So web 02 is up and running with this container ID. Let's see. Docker inspect what was that web 02 and grab for the IP AD. Okay. So this is IP address for that container and if I do I could see that my container is up and running. And if you do a PS cap of STDPD you can see two containers side by side. So this is the one which we just spin up which is web 02 with minimal capabilities and the first initial one with the default capabilities. So now you could decide what exactly would be the recommended way for your service basically to get a container up and running with the minimal capabilities as to it. So that you know if in case there are vulnerabilities in your container at least there are minimal privileges and nobody could escape out of your container. All right. So this is all about you know privileges and yep. The next thing I'm going to talk about C group and after that name spaces. All right. So I have kept each and everything on the documentation. So I would need to go to that to see what exactly is there on that page. All right. So we're going to see the C groups. Okay. So for that let's start a simple container first. I'm going to copy paste the whole command in order to save the time as I've got a minimal time here. All right. So my container is up and running and I am into the container shell. All right. But before that I would want to see what exactly is the amount of memory attached to this container or basically the amount of memory allocated to this particular container. All right. So how can I see that catches FSC group then Docker C groups memory then Docker then basically the container ID okay container ID and then memory and memory limits in bite. Okay. So this is the number in bites as you could see the name of the file is in bite. So this is the number in bites which is allocated to this container here and I'm sure this change number is something which my machine you know would not be having. So if I do free have an image my machine is only having 15 GB of RAM and I'm sure this time number is all the way beyond this 15 GB. All right. So do you really think that your container would be needing that much of memory for sure or not if this is not the case that you are going to run a single container on a bare metal machine which is unlikely the case. All right. So I have got this memory and let's see if I could leverage or use any of this memory. So what I'm going to do here is I'm going to start to worker which would use 250 MB of RAM with within 5 second. All right. So I'm dispatching the hooks and you could see so basically this is a stress test which we are going to do. All right. So it says this container can use 250 MB of RAM with to process or to worker running side by side for a time out of 5 seconds. Okay. But after that, let's see if I'm able to do that same for 500 MB. Okay. I'm sure that it would be able to do that. Okay. Yeah. Successful and complete and it would do until I'm getting out of this number which I really don't want at any cost. Okay. So is there any way I could limit or I could give the threshold. Or the upper limit on the amount of frame which can be allocated to a container. Oh yes. There is a way and Docker provides that out of the box. All right. What exactly is that? Let's see on the recommendation. Okay. So you can always say, okay, I need only 10 MB of RAM. That's it. This is the flag you need to give. Let's see. Okay. Shell of the container and let's try to run the same stress test which we ran here. But here I'm going to do with 50, let's say. So it says failed. Okay. What about 12? It says failed. What about something under 10? Let's say 8. So it says successful. So as you could see, the 8 MB is under the limit which we have given, which is 10 MB. All right. So the stress test is failing if these two workers basically are using more than 10 MB of RAM together. So the test is failing. But if it is within the limit, so they are getting the test successful. So that's how you can limit the amount of RAM being allocated to a container, basically marking a threshold on the memory. So same way you can do it for disk, network or IO. So this example I have shown only for memory. So let's go back to the recommendation and see what exactly we have. Okay. So the next thing is name spaces. All right. So let's run a simple container here. Okay. So my container is up and running and basically the alpine container. And if I go here, Docker, exact, this is the container ID. And if I attach a pen, okay. So bash is not there. Let's say shell. Okay. So if I do PSF, so you could see the sleep command which I have given as the argument is running as a net process with PID one and as a user root. But what if I go to the host and do PSI funny if crap of sleep. So as you could see, this is the exact same command here. And it is running with the process ID 8 4 2 0 and with the user root. So that's how whatever you're seeing inside a container, which is running as a net process is running with some other user ID on the host level. So that's how the mapping of the user ID is being done and a Docker container. All right. So let's let's run a MariaDB container here and see, okay, MariaDB. So MariaDB is up and running. And if I would want to go into this Docker exact hyphen IT and then bash, okay, I'm inside the container. And if I do PSIU X W W, you could see the MySQL D Damon is running as the net process with MySQL user. Okay. If I do ID MySQL, it says the ID of the MySQL is triple line here on this inside the container. Okay. So if I go in the host and if I do PSIU hyphen EF prep of MySQL, okay, nothing is in here. MySQL. Okay. So here's the Damon MySQL D running the same Damon, which is running inside the container. But on the host, it is running with some other user ID and the user which is accountable for this process is MFE. It is not the one which is here, which is MySQL. And for MySQL or MariaDB, the user which is the control user for this process should be MySQL in any case. And I really don't want any other user to be the control user of my MySQL Damon. And what exactly is this MFE here? So let's see. Get it is vast ability and grab 999. Okay. So as you could see here, so the idea of the MySQL inside the container was triple line and on the host, the triple line ID has been taken by some other user, which is MFE. So I have been running McAfee, McAfee services on the host. And this is the user which is responsible for taking care of those services. And the MySQL process is attached to this user at the host level. And this is something which could have the consequences in near future. So in order to overcome these type of problem, what you could do is you could do a certain modification in your Docker file. So what exactly are those? Let's see here. So either you could say a group add MySQL and then user add MySQL. But here with this, you would see the problem which we are seeing here. So instead of that, you could say group add with group ID, then give the MySQL name and then user add with user ID for MySQL. But this is the short term solution, which you have to do everywhere in your Docker file or everywhere in the code, wherever you are spinning up a MySQL or a MySQL container. So what exactly is the long term solution? So there is a username space which has been introduced by Docker and it's still in the experimental phase, but I have explored it and it is working quite nice. So let's see how exactly that is going to work. So the long term solution would be to start the Docker daemon itself in some other name space. So let's say we want to start the Docker daemon in a Swapy name space. So for that, we should have a user with the name Swapy and group already present. OK, so we have got the user and group for the same. And when we are going to instruct the Docker daemon to start in this Swapy name space, we would need the subordinate UID. OK, so we have defined here for this user, the subordinate UID range, which is 165536 and the next set of integer for this user. So whenever the Docker daemon is running in this Swapy name space, it would start using the UID of this range, unless like earlier, which was triple line. And same way, we would need subordinate GID for Swapy, the same thing. And after assigning the subordinate UID and subordinate GID for the name space wherein you want to run the Docker, you would want to instruct the Docker daemon as well. OK, for that Docker daemon.json, you have to say you have to remap yourself in the name space, which is Swapy, and then you could always start the Docker daemon. OK, so we have restarted the Docker daemon after instructing the Docker daemon that we have to run in Swapy name space. And let's try to see if we are able to run the MySQL. OK, so it says myDB is not here locally, all right, fine. And it is trying to pull the images or basically the layers for that image. I'll take a bit. OK, so our container is up and running. Let's try to get into that container, Docker exec-it-bash. OK, I'm inside the container. And if I do psax-w-w, you could say the MySQL daemon is running with the user MySQL and with process ID, one which is an installation process. And if I go here, and if I do ps-ef and grep of MySQL-de-