After putting RHEL on one of my workstations, I started playing with containers. I never was an adopter of docker as I’ve been plenty happy with running VirtualBox images under Vagrant. Coming from that ecosystem, my first impression of podman containers was a little shaky.
I work inside virtual machine (VM) environments every day. There are a LOT of components to serving a modern web site, and it isn’t feasible to take a lot of time to set up each individual environment a website might live in.
Enter the LAMP stack. A LAMP stack contains all the necessary components that run most sites without much tweaking. We’ve been working with LAMPReady for a few years now which includes some extra scripting to make that job even easier.
One of the major differences in working with podman containers is the lack of persistent data. Once a container is shut down, any new data generated within the container is lost.
Working with Persistent Data
At its core the container is designed to run from a fixed state that never changes. There are two important use cases for this behavior. During development, the container can be experimented on without adversely affecting stability. When the container is restarted, it is placed back into the original state it started in.
In the production environment, applications can be distributed in a state that is designed to be immutable. MacOS does it. Now we have Flatpak and Snap packs for Linux. Even Windows is moving more towards this type of application distribution. Podman containers are important, because they mark a major shift in website deployment that follows that same pattern.
However, one of the hallmarks of a LAMP stack is maintaining a persistent state. Developers are constantly changing, testing and comparing different saved states of data. So why would we ever consider using a container as a LAMP stack?
A LAMP Stack All in One Container
The LAMP stack most developers are familiar with is designed for troubleshooting. In most cases, they are not meant for production environments. Even a moderately busy website might span across several servers which all provide different functionality.
One server might hold the database and another serves static files such as images. There may be other servers in between that balance the load of requests made to the website. This is an over simplification, but we find similarities in container logic designed for specific tasks.
Traditionally, a LAMP stack is designed to do it all so that code can easily be managed and manipulated for the sake of debugging. Although podman has the option to pool containers together to fulfill a cohesive function, one container can also run multiple processes! A single podman container can run the Apache web server, Mysql database and any number of processes needed to serve a dynamic website.
As Scott McCarty mentioned in his article , this is completely possible. Housing certain data outside the container allows it to remain persistent after being shut down the same way any VM works. The overhead of running a container is much less than a VM, so there is some added performance boost there too.
Understanding the Container Permissions
If we agree that a LAMP is not a production environment then it shouldn’t matter how we set it up; just so long as it is not hindering the process of debugging code. That brings us to an area where some will disagree how containers are being used.
When data is saved outside the container, there are permissions stamped on that data from both sides. Like the VM there are different permissions on shared files within the container than the what host operating system recognizes. While Vagrant can manipulate all shared data regardless of permissions, a podman container actually uses a single user to override permissions. What user is best suited for that task? root is.
For the purposes of creating a LAMP stack, it is NOT advantageous to use the –user flag to handle permissions. Instead, saving a file as the default root user will assume the proper permissions of the files in the host environment. So that means, Apache, Mysql, PHP-FPM, etc. all need to be running as root if any part of those configuration files are to be saved on the host machine for persistence or user interactivity.
There are no other use cases for this. A web server would never run any of these services as root in a production environment. For the containered LAMP stack it’s a necessary part of the process.
This one departure from standard practice turns a single container into a powerful, versatile tool for development. Environments can be woke up in Docker style and remain persistent. There is no longer a need to shelter images on repositories as the environment can be easily tweaked at run time.
The Host Network Mode
There are two different types of podman containers: rootfull and rootless. All this means is that one container is created by the root user of the host operating system and the other isn’t.
I honestly can’t think of any use cases for rootfull containers other than system administrators testing configuration ideas before implementing them. I’m new to this game, so please fill me in?
A rootfull container has full access to the network. It can be assigned an IP address in the same manner most VM’s work. The rootfull container has a lot of tools to build network interfacing at runtime. The rootless container can’t access any of these tools, but it does have access to the full system network!
One good reason for giving a rootless container access to the host network is implementing Xdebug, a popular tool for debugging PHP code. Xdebug needs an open port to communicate back and forth to complete an integrated development environment.
Regardless of what the standard practices are, a rootless container can do that! There is an example of this process at LAMPready. The “–network host” option is the key component to make this work.
The documentation says that this flag is unsafe – and it is. It might not be a great idea to work with compromised code if we have Apache running as the root user inside the container.
Realistically though, the only configurations exposed to the container are the host file and local network. As far as the normal implementation of PHP code, this information is rarely discovered unless done purposely so.
The box script example will require Podman to to be logged into the registry.access.redhat.com. However there may be a suitable substitute on one of the non-subscription repositories. In either case, this example is designed to work with RHEL.
Right now, Red Hat is allowing access to this repository at no charge. Anyone can register as a developer. Since CentOS is moving out of the production space, this is a good way to see websites working in the RHEL environment. Thankfully, there’s not much difference.
As a side note, the default container does not use a deployment slot. The container already has anonymous access to the main repository.
Podman is a very effective tool for building a complete LAMP stack. System admins and developers needed a tool to quickly assess the feasibility of transitioning to a new environment. This affects a LOT of web sites, and a speedy solution is essential under the adjusted CentOS end-of-life timeline.