So, what do we need to do to configure user access to persistent storage?
Well, let's put a few things together that we have seen in the previous videos.
While bind mounting directories on the host, file ownership on these directories is important.
Without the wrong file ownership, you don't get access.
If a container is started by the root user, UIDs and GIDs on the host match the UIDs and
GIDs in the container.
But you don't want to start the container by the root user.
That's a root full container.
And in a pop-in environment, that is really the worst thing that you can do.
So for a rootless container, that's what we should be talking about.
You will need to make sure that the UID of the user that runs the container application
is owner of the bind mounted directory.
As we have just seen, you can use pop-in inspect on a container image to find out if such a
user exists and if that is the case, which user it is.
Now rootless containers are launched in a namespace.
And the namespace provides isolation, which allows the container inside the namespace
to have root access, which does not exist outside the namespace.
And that's good.
And that means that inside the container namespace, different UIDs are used than outside of the
namespace.
And to ensure that access is working all right, UIDs are mapped between the namespace and
the host operating system.
We have already seen how the pop-in unshare command can be used to run commands inside
the container namespace.
To get the UID mapping, you can use pop-in unshare cat proc self UID map.
I'm not sure if you want to do that, but it's an option.
And you will see that the container root user maps to your host's ordinary user ID.
That's the default situation.
Now what you need to know is how to manage non-root user mappings.
To set appropriate directory ownership on bind-mounted directories for rootless containers,
you need to do something in addition.
First, you find the UID of the user that runs the main application.
And you may be able to find that using pop-in inspect image name, as we have seen in a previous
video.
Or otherwise, you might use pop-in exec on your container and grab the user on etc pass
wd.
Next, once you found it, you can use pop-in unshare chown, followed by the user colon
group ID on the directory.
And that will set the container UID as the owner of the directory on the host.
And notice that directory name must be in the user home directory, because otherwise
it would not be a part of the user namespace.
And you use pop-in unshare cat proc self UID map to verify the mapping if you want to.
And verify that the map user is owner on the host using ls minus ld slash directory name.
Sounds complicated?
Well, in fact, it's not that complicated.
Let me show you.
I'm skipping the pop-in search MariaDB part, because we already have found MariaDB.
And I'm going to use mkdir mydb.
Next, I'm using popman run minus d minus minus name mydb minus e mysql root password.
We've learned that before, this password and minus v slash home student mydb.
And we map that to var lib mysql.
Var lib mysql is where the database is by default.
Then I need the name of my image, which is registry.redhat.io slash rel 10 slash MariaDB
dash 10 11.
So let's give it a try.
And we will see that it has failed.
Popman ps minus a.
So why did it fail?
Well, for the same reason as the one before, permission issue.
So use popman logs.
If you want to verify that, popman logs in this case on mydb.
And here we can see the permission denied.
If you want to, you can use popman inspect to find the user ID.
I've already demonstrated that.
And let me just do a popman unshare to fix it.
So popman unshare shown 27 colon 27 mydb.
And then ls minus ld on mydb is showing this auto-generated user ID.
And popman unshare ls minus ld on mydb is showing user ID 27 27 within the container
namespace.
So as a first step, that's good enough.
Let's get back to the slide to tell you about the second step.
You remember our dear friend SELinux.
We need to take care of that as well.
So at this point, ownership is set correctly.
And now we need to make sure that we take care of SELinux.
To bind mount a host directory in a container, the container file T, SELinux context type,
must be used.
Fortunately, that is very easy.
Because if ownership on the host directory has been configured all right, you can use
a colon uppercase Z option to automatically set this context.
So your bind mount is modified.
There's only one thing that you change.
You add colon uppercase Z to the end.
And that will ensure that the container gets its own security label.
And only that security label will get access to the bind mounted directory.
Let me demonstrate.
So as file ownership has been taken care of in the preceding steps, we are now ready
to bind mount in a way where SELinux is considered as well.
And do notice that the directory inside the container is mapped to the home directory
of the user that runs the container main application.
I like repeating it because it's very important.
Let me start by using Popman stop mydb and Popman rm mydb.
And now it's really not complicated.
I am going to look up the previous command, this guy.
And to the end of the minus V option, that's a long option, I'm adding a colon Z.
And for the rest of it, I'm pressing Enter.
And then Popman PS is showing what?
It's showing that three seconds ago, mydb was started.
Well, that's good, isn't it?
Now if you use LS minus ZD on mydb, there we can see that container file T has been
set.
You also see something that you've never seen before, the C393 and the C1023.
The fine thing about it is that this corresponds to a context label that is set on the container
as well.
Because you might think, OK, container file T, how does that guarantee that other containers
don't have access to this directory?
Well, that is because of these categories here.
You call them categories.
So only containers that have category 393 and 1023 have access, and other containers
do not.
But if I look at the container processes from a host operating system view, I'm using PSZFAUX.
That's not a Z.
And I'm piping that through LES.
And then I'm going a little bit down, well, more than a little bit.
And what I'm looking for is right here.
So you can see a process CONMON.
CONMON is a container monitor.
That's the main process that starts a container.
And this CONMON has started a child process, use a libexec, mysqld.
That is my MariaDB container.
And you see what's going on.
The SELinux context label for that process is set right here.
So it's container underscore T, which has access to container file T.
And we have the C393, as well as the C1023, which is unique for this specific container.
If you compare that, for instance, to the NGINX container process, which we see here,
you see that this also has a category, but it's a completely different category.
For that reason, NGINX will never get access to this directory.
That will be denied by SELinux.
Now, that's a lot of background information for something as simple as, hey,
just add colon uppercase Z to the bind mount, and everything will be taken care of.
Maybe you prefer the simple approach.
So, wow, that was a lot of information.
Let's summarize.
While using a bind mount, the rootless container user needs access to the mapped directory on the host.
To organize that, first, you find the user defined in the container image.
Popman image inspect is a convenient way to do so.
And in the MariaDB case, we have found user 27.
Next, you create the directory in the rootless user home directory.
That's the home directory of the user that runs the container.
And then you use Popman unshared shown to set the user that you just found as the owner of that directory.
And then you verify.
You do that in two different ways.
First, you use Popman unshared ls-ld on that directory.
There you will see the user ID 27.
And then you use ls-ld without the Popman unshared to verify the same from the user home directory view.
And there you will see the dynamically generated user account.
And then you can run the bind mount with the minus Z option for SELinux.
We already talked about that.
Feel free to revisit that command in the previous.