Setting Up a PHP Development Environment with Podman
Oct 16, 2020
Recently I’ve been taking an online course through Coursera on PHP. In my early experiments with PHP I generally got along fine with php’s built in web server. This course however, uses a traditional LAMP (Linux, Apache, MySQL, PHP) stack for assignments. Now I could just install those things on my computer, but I like to keep my computer clean and cluttering it up with various config files and databases is not particularly appealing to me. I want a solution that I can easily setup/teardown and purge from my machine when done. Containers are perfectly suited to this.
I have used Docker in the past, but the experience with Docker on Fedora 32 is pretty bad. I thought this was a good opportunity to finally learn podman beyond just installing podman-docker and calling it a day.
Creating the PHP and MySQL Images
For this step, you’ll need both podman and buildah. On Fedora or CentOS 8 this is as easy as sudo dnf install podman buildah. Just like docker, podman supports the use of Dockerfiles via the podman build command. However, I have heard good things about buildah so I wanted to see the difference for myself. buildah allows you to build images from the command line, or using normal shell scripts. If you’re familiar with Dockerfiles, buildah is a pretty easy transition.
So lets get started by building the php apache image. Luckily there is a really nice image on DockerHub. Run:
id=$(buildah from --pull php:7.4.10-apache-buster
buildah from --pull will search various repositories, including DockerHub, for matching images and return a ID. We will store this ID in the variable id.
Next, since we will be connecting this to a MySQL instance we need to install the necessary php extensions to our image. Luckily, the php image from DockerHub has a handy built-in utility to install php extensions called docker-php-ext-install. We will need the pdo and pdo_mysql extensions.
buildah run $id docker-php-ext-install pdo pdo_mysql
This command will install pdo and pdo_mysql in the image. Now all that’s left is to commit the changes to save the image.
buildah commit $id php-apache
This will save the image with $id as php-apache. Now that we have the php image lets create our mysql image, this one is simple.
id=$(buildah from --pull mysql:8)
buildah commit $id php-mysql
Now if you run podman images you should see our two newly created images php-apache and php-mysql. At this point, we could run our new images as containers with podman run -p 8080:80 php-apache, but I’ve got something better in mind.
Group the Images in a Pod
Ideally we want both of these containers to run as a group. In the Docker world we would use something like docker-compose, but podman has a build in concept called pods which allows us to orchestrate many containers their own mini kubernetes cluster. All containers in a pod can be started, and stopped together with the podman pod start <pod-name> and podman pod stop <pod-name> commands respectively. Also, all containers in a pod share the same private network, so all containers in a pod can easily access each other without opening any ports outside the pod. There are several ways to add a new pod, but podman offers an easy way through podman run.
podman run \
--detach \
--pod new:php-lamp \
--publish 127.0.0.1:8080:80 \
--name php-dev \
--security-opt label=disable \
--volume ./src:/var/www/html \
php-apache
Let’s break this command down:
--detach: detach the container from this shell session.--pod new:php-lamp: Add this container to a new pod called php-lamp.--publish 127.0.0.1:8080:80: Publish the container’s port 80 to localhost port 8080.--name php-dev: Name this container php-dev.--security-opt label=disable: This will allow the volume mounting to work correctly.--security-opt label=disable: This will allow the volume mounting to work correctly.--volume ./src:/var/www/html: Mount thesrcfolder in the current directory to/var/www/htmlin the container.php-apache: The name of the image from which to create a container.
Now you should be able to see a new pod called php-lamp when running podman pod ls. The container is also running so pointing your browser to localhost:8080 should bring up the phpinfo page. Now all we need to do is add the mysql container to the pod.
podman run \
--detach \
--pod php-lamp \
--name mysql-dev \
--env MYSQL_ROOT_PASSWORD=dev \
--security-opt label=disable \
--volume ./mysqldb:/var/lib/mysql \
php-mysql
This will add a new container mysql-dev to the php-lamp pod. Now you can stop and start both containers together using podman pod stop php-lamp and podman pod start php-lamp.
Putting it all Together
The beauty of all these shell commands, is we can put them in a script like mklamp.sh
#!/bin/sh
echo -e "Building Apache PHP image"
id=$(buildah from --pull php:7.4.10-apache-buster)
buildah run $id docker-php-ext-install pdo pdo_mysql
buildah commit $id php-apache
echo -e "\nBuilding MySQL image"
id=$(buildah from --pull mysql:8)
buildah commit $id php-mysql
podman run \
--detach \
--pod new:php-lamp \
--publish 127.0.0.1:8080:80 \
--name php-dev \
--security-opt label=disable \
--volume ./src:/var/www/html \
php-apache
podman run \
--detach \
--pod php-lamp \
--name mysql-dev \
--env MYSQL_ROOT_PASSWORD=dev \
--security-opt label=disable \
--volume ./mysqldb:/var/lib/mysql \
php-mysql
Now simply running sh mklamp.sh will build an run a nice php dev environment. This is obviously very similar to building a docker-compose file, but and we get to reap the benefits of not having Docker daemon running in the background.