Using podman to set up a PHP development environment 2021-04-30 on Kenneth Dodrill

There are many ways to set up a PHP development environment, but using containers is a good way to ensure reciprocity across local dev machines and production/dev servers.

You will, of course, need podman installed in order for this to work.

Before following the steps below, try and list out all of the services your project needs. It's important to pull their images and open the ports they require.

It's a good idea to keep a notepad open to write out your commands, then edit them if they don't work out and copy/paste to your terminal.

I am using nginx and mysql for this.

Create the pod:

podman pod create --name webdev

If you are using nginx, you'll want the -p 8080:80 port arg. If you're using mysql you'll want the -p 33060:3306 arg. Add other ports you may need if you're using other services - you need to do this when creating the pod, otherwise you'll have to start over.

Pull your images. I am using docker hub images.

podman pull php:7.4-fpm-alpine && podman pull nginx:alpine && podman pull mysql

Create nginx confs.

Create a folder somewhere to keep your nginx confs (I use ~/.podman-nginx-confs).

A typical conf file might look something like the one below. The key thing is to point fastcgi_pass to localhost:9000, or whatever port php-fpm is at.

server {
    listen 80;
    server_name localhost;
    root /var/www/project-name;

    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
        index index.php index.html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass    localhost:9000;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
        fastcgi_param   PATH_INFO $fastcgi_path_info;
    } 

    location ~ /\.ht {
        deny all;
    }
}

Run the nginx container and attach it to pod you created above.

podman run -dt \
--name nginx \
--pod webdev \
--volume <nginx-conf-dir>:/etc/nginx/conf.d:ro \
# add more volumes here to serve more websites.
--volume <website-src-files>:/var/www/<website-name> \
--restart on-failure \
docker.io/library/nginx:alpine

Run the php 7.4 container and attach it to the pod.

podman run -dt \
--name php7 \
--pod <some_pod> \
# just like with nginx, add more volumes here to serve more websites.
--volume <website-src-files>:/var/www/<website-name>:rw \
--restart on-failure \
docker.io/library/php:7.4-fpm-alpine

Finally, do the same with the mysql container.

podman run -dt \
--name mysql \
--pod webdev \
--volume mysql:/var/lib/mysql \
--restart on-failure \
--env MYSQL_ROOT_PASSWORD=<root-pass> \
docker.io/library/mysql

You can easily halt everything by running podman pod stop webdev, and easily run everything by issuing podman pod start webdev.

You can interact with any container you create by issuing podman exec -it <container_name> /bin/bash. You'll want to use /bin/ash if it's an alpine container. From there, you can install more packages, change any configurations, and set up your databases.