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.
/src
/mysqldb
etc
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.
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 the src
folder in the current directory to /var/www/html
in 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
.
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.