Try PHP 8.0 beta features with Docker / Kubernetes
Tags: php, beta, docker, kubernetes
Published: 2020-02-03 10:47:13



PHP 8.0's development had started one year ago. With many promising features like: Union types, JIT, Static return type, Weak maps, ..., probably you'd like to give it a try. Or simply, you just want to know if your codebase will run fines with future PHP version. So I've created PHP 8.0 beta Docker images for you :) 

The base image `martinpham/php8:fpm-alpine` contains PHP 8.0 FPM, built from PHP source code, and based on Alpine Linux, so it's quite small and fast. It also supports multiple architectures (linux/amd64, linux/arm64, linux/386, linux/arm/v7, linux/arm/v6), so you can run it even on a small Raspberry Pi!

Docker
===
You can try to run it now:

```bash
docker run -p 9000:9000 --rm martinpham/php8:fpm-alpine
```

Docker will pull the image, and creates a new container with this image, also exposes port 9000 for PHP-FPM server. (Note: The `--rm` option tells Docker to remove the container after it finishes).

If everything goes fine, you'd see logs from Docker:

```bash
NOTICE: fpm is running, pid 1
NOTICE: ready to handle connections
```

To make sure, you could also try to send request to the PHP-FPM server:

```bash
REQUEST_METHOD=GET cgi-fcgi -bind -connect localhost:9000
```

(Replace localhost with your Docker's Host IP)

PHP-FPM will respond:

```
X-Powered-By: PHP/8.0.0-dev
Content-type: text/html; charset=UTF-8
```

Everything is good! You are running your first PHP 8.0 beta - FPM server!

Kubernetes
===
If you were following [my Kuberetes tutorial](https://www.martinpham.com/2019/12/07/having-fun-with-kubernetes-1/) before, probably you'd like to deploy it on your Kubernetes cluster :). 
Well it's very easy, here is a sample configuration, with:

- A persistent volume (`code-pvc`) for storing application code
- A config map (`nginx-config`) for nginx configuration
- A deployment (`app-deployment`) with PHP 8 FPM server and NGINX web server
- A service (`app-service`) to expose deployed pod (tagged with `name: app-pod`)

```yaml
## App code volume
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: code-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

---

## Nginx config
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
data:
  nginx.conf: |
    events {
    }
    http {
      server {
        listen 80;
        listen [::]:80;
        
        root /var/www/html;
        index index.html index.htm index.php;
        
        location / {
          try_files $uri $uri/ =404;
        }

        location ~ \.php$ {
          include fastcgi_params;
          fastcgi_param REQUEST_METHOD $request_method;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_pass 127.0.0.1:9000;
        }
      }
    }

---

## App deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 1
  strategy:
    type: Recreate    
  selector:
    matchLabels:
      name: app-pod
  template:
    metadata:
      name: app-pod
      labels:
        name: app-pod
    spec:
      volumes:
        - name: app-files-volume
          persistentVolumeClaim:
            claimName: code-pvc
    
        - name: nginx-config-volume
          configMap:
            name: nginx-config
    
      containers:

        # php-fpm
        - name: phpfpm
          image: martinpham/php8:fpm-alpine
          volumeMounts:
            - name: app-files-volume
              mountPath: /var/www/html
          resources:
            limits:
              cpu: 100m
            requests:
              cpu: 50m

        # nginx
        - name: nginx
          image: nginx:alpine
          volumeMounts:
            - name: app-files-volume
              mountPath: /var/www/html
            - name: nginx-config-volume
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf
          resources:
            limits:
              cpu: 100m
            requests:
              cpu: 50m

          ports:
          - containerPort: 80
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 3
            periodSeconds: 3
            successThreshold: 1

---

## App service
apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  selector:
    name: app-pod
  ports:  
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP

```


Additionally, I've also built an "extra" image, called `martinpham/php8:fpm-extra-alpine`, which extends from the base image, with mysqli, gd, pdo_mysql and opcache extensions, so you can start to try other extensions with PHP 8.0.

---

PS: All images above are open-sourced, you can find it here [https://github.com/MartinPham/php8-docker](https://github.com/MartinPham/php8-docker)