Skip to content

Commit

Permalink
Merge pull request #30 from shyim/add-fpm-base-image
Browse files Browse the repository at this point in the history
feat: add base image for fpm
  • Loading branch information
shyim authored Apr 7, 2024
2 parents f0e6b5e + 5757cec commit 560f889
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 46 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,38 @@ jobs:

- name: Sign image
run: cosign sign --yes ghcr.io/shyim/wolfi-php/frankenphp:${{ matrix.php }}

fpm:
runs-on: ubuntu-latest
strategy:
matrix:
php:
- 8.2
- 8.3
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Cosign
uses: sigstore/cosign-installer@v3

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login into Github Docker Registery
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

- uses: docker/build-push-action@v5
with:
tags: ghcr.io/shyim/wolfi-php/fpm:${{ matrix.php }}
platforms: linux/amd64,linux/arm64
context: images/fpm
build-args: PHP_VERSION=${{ matrix.php }}
push: true
provenance: false

- name: Sign image
run: cosign sign --yes ghcr.io/shyim/wolfi-php/fpm:${{ matrix.php }}
52 changes: 6 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,54 +94,14 @@ CMD [ "--config", "/etc/caddy/Caddyfile" ]

After building the image, you can run the container with `docker run -p 8000:8000 <image>` and it should show a PHP info page.

### "Drop-in" replacement for official FrankenPHP image
To learn more about FrankenPHP, [see here](./images/frankenphp)

We provide also a replacement like the official FrankenPHP image same Caddyfile, but with Wolfi.
## Base images

```dockerfile
# 8.2 is also available
FROM ghcr.io/shyim/wolfi-php/frankenphp:8.3

# copy source code to /app/public
COPY . /app/public
```

To run the container, as a non-root user, you can do the following:

```dockerfile
FROM ghcr.io/shyim/wolfi-php/frankenphp:8.3

ARG USER=www-data

RUN \
mkdir -p /data/caddy && mkdir -p /config/caddy; \
apk add --no-cache libcap-utils; \
adduser -D ${USER}; \
# Add additional capability to bind to port 80 and 443
setcap CAP_NET_BIND_SERVICE=+eip /usr/bin/frankenphp; \
# Give write access to /data/caddy and /config/caddy
chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy; \
apk del libcap-utils

USER ${USER}
```

### Installing extensions

To install PHP extensions, you can use the `apk` package manager. For example, to install the `gd` extension, you can run:

```dockerfile
# pick one of these
FROM ghcr.io/shyim/wolfi-php/base:latest
# frankenphp one, bases on the base image
FROM ghcr.io/shyim/wolfi-php/frankenphp:8.3


RUN apk add --no-cache php-frankenphp-8.3-gd
```

It's important that you only install extensions matching to your PHP version and with the `php-frankenphp` prefix.
We provide also base image for ready to start without touching configuration:

- [FrankenPHP](./images/frankenphp)
- [FPM](./images/fpm)

### Pinning package versions

Expand All @@ -161,4 +121,4 @@ To get the excact current version of a package, you can run `apk info php-8.2`.

- [Symfony Demo with FrankenPHP](examples/frankenphp-symfony-demo/README.md)
- [Nginx + PHP-FPM](examples/nginx-php-fpm/README.md)
- [FPM standalone](examples/fpm/README.md)
- [FPM standalone](examples/fpm/README.md)
38 changes: 38 additions & 0 deletions images/fpm/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM ghcr.io/shyim/wolfi-php/base:latest

ARG PHP_VERSION=8.3

RUN <<EOF
set -eo pipefail
apk add --no-cache \
php-${PHP_VERSION}-fpm
adduser -u 82 www-data -D
mkdir -p /var/www/html
EOF

WORKDIR /var/www/html
ENV PHP_FPM_USER=www-data \
PHP_FPM_GROUP=www-data \
PHP_FPM_LISTEN=[::]:9000 \
PHP_FPM_PM=dynamic \
PHP_FPM_PM_MAX_CHILDREN=5 \
PHP_FPM_PM_START_SERVERS=2 \
PHP_FPM_PM_MIN_SPARE_SERVERS=1 \
PHP_FPM_PM_MAX_SPARE_SERVERS=3 \
PHP_FPM_PM_MAX_REQUESTS=0 \
PHP_FPM_PM_STATUS_PATH=/-/fpm/status \
PHP_FPM_PING_PATH=/-/fpm/ping \
PHP_ERROR_REPORTING= \
PHP_DISPLAY_ERRORS=On \
PHP_DISPLAY_STARTUP_ERRORS=On \
PHP_UPLOAD_MAX_FILESIZE=2M \
PHP_POST_MAX_SIZE=2M \
PHP_MAX_EXECUTION_TIME=30 \
PHP_MEMORY_LIMIT=128M \
PHP_SESSION_HANDLER=files \
PHP_SESSION_SAVE_PATH= \
PHP_SESSION_GC_PROBABILITY=1

COPY --link rootfs /

CMD [ "/usr/sbin/php-fpm" ]
116 changes: 116 additions & 0 deletions images/fpm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# FPM only image

## Image information

- Build for PHP 8.2 and 8.3
- Build for amd64/arm64
- Pretty small with just PHP-FPM installed

## Usage

```dockerfile
FROM ghcr.io/shyim/wolfi-php/fpm:8.3

# Install missing extensions
RUN apk add --no-cache php-8.3-redis php-8.3-gd

# Copy your files
COPY . /var/www/html
```

> [!IMPORTANT]
> When you use only FPM, you will need a webserver like Caddy/Nginx to serve HTTP requests and proxy them to PHP-FPM.
## Available environment variables

The image has some environment variables to configure PHP-FPM or PHP. This should cover all common use cases.

### FPM

- `PHP_FPM_USER` - FPM is running as this user (default: www-data)
- `PHP_FPM_GROUP` - FPM is running as this group (default: www-data)
- `PHP_FPM_LISTEN` - FPM listen address (default: :9000)
- `PHP_FPM_PM` - FPM process manager (default: dynamic)
- `PHP_FPM_PM_MAX_CHILDREN` - FPM max children (default: 5)
- `PHP_FPM_PM_START_SERVERS` - FPM start servers (default: 2)
- `PHP_FPM_PM_MIN_SPARE_SERVERS` - FPM min spare servers (default: 1)
- `PHP_FPM_PM_MAX_SPARE_SERVERS` - FPM max spare servers (default: 3)
- `PHP_FPM_PM_MAX_REQUESTS` - FPM max requests (default: 500)

These FPM settings are the default one from PHP, you may want to change them based on your available resources and application.

### PHP

- `PHP_ERROR_REPORTING` - PHP error reporting (default: "")
- `PHP_DISPLAY_ERRORS` - PHP display errors (default: On)
- `PHP_DISPLAY_STARTUP_ERRORS` - PHP display startup errors (default: On)
- `PHP_UPLOAD_MAX_FILESIZE` - PHP upload max filesize (default: 2M)
- `PHP_POST_MAX_SIZE` - PHP post max size (default: 8M)
- `PHP_MAX_EXECUTION_TIME` - PHP max execution time (default: 30)
- `PHP_MEMORY_LIMIT` - PHP memory limit (default: 128M)
- `PHP_SESSION_HANDLER` - PHP session handler (default: files)
- `PHP_SESSION_SAVE_PATH` - PHP session save path (default: "")
- `PHP_SESSION_GC_PROBABILITY` - PHP session gc probability (default: 1)

These PHP settings are the default one from PHP, you may want to change them based on your application requirements.

### Changing those variables

You can configure them before starting your container:

```shell
docker run \
--rm \
-e PHP_MEMORY_LIMIT=256M \
your-image
```

or in your Dockerfile:

```dockerfile
FROM ghcr.io/shyim/wolfi-php/fpm:8.3

ENV PHP_MEMORY_LIMIT=256M
```

### Using Redis session

To use Redis as session handler, you need to install the Redis extension and set the session handler to redis:

```dockerfile
FROM ghcr.io/shyim/wolfi-php/fpm:8.3

RUN apk add --no-cache php-8.3-redis

# Set session handler to redis
ENV PHP_SESSION_HANDLER=redis \
PHP_SESSION_SAVE_PATH=tcp://redis:6379
```

## Adding custom PHP/FPM configuration

To add custom PHP, create a file `/etc/php/conf.d/zz-custom.ini` and add your configuration there:

```dockerfile
FROM ghcr.io/shyim/wolfi-php/fpm:8.3

COPY custom.ini /etc/php/conf.d/zz-custom.ini
```

for FPM you can do the same with the path `/etc/php/php-fpm.d/zz-custom.conf`:

```dockerfile
FROM ghcr.io/shyim/wolfi-php/fpm:8.3

COPY custom.conf /etc/php/php-fpm.d/zz-custom.conf
```

## Running as non-root

The image is running as root by default. You can just need to switch the USER in the Dockerfile:

```dockerfile
USER www-data
```

If you want to use a custom user, you don't need to change the configuration. When PHP-FPM is started as a non-root user, the user and group configuration is automatically set to the user you are running PHP-FPM as.
13 changes: 13 additions & 0 deletions images/fpm/rootfs/etc/php/conf.d/default.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
expose_php = Off
error_reporting = ${PHP_ERROR_REPORTING}
display_errors = ${PHP_DISPLAY_ERRORS}
display_startup_errors = ${PHP_DISPLAY_ERRORS}

upload_max_filesize = ${PHP_UPLOAD_MAX_FILESIZE}
post_max_size = ${PHP_POST_MAX_SIZE}
max_execution_time = ${PHP_MAX_EXECUTION_TIME}
memory_limit = ${PHP_MEMORY_LIMIT}

session.save_handler = ${PHP_SESSION_HANDLER}
session.save_path = ${PHP_SESSION_SAVE_PATH}
session.gc_probability = ${PHP_SESSION_GC_PROBABILITY}
10 changes: 10 additions & 0 deletions images/fpm/rootfs/etc/php/php-fpm.d/zz-b-default.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[www]
user = ${PHP_FPM_USER}
group = ${PHP_FPM_GROUP}
listen = ${PHP_FPM_LISTEN}
pm = ${PHP_FPM_PM}
pm.max_children = ${PHP_FPM_PM_MAX_CHILDREN}
pm.start_servers = ${PHP_FPM_PM_START_SERVERS}
pm.min_spare_servers = ${PHP_FPM_PM_MIN_SPARE_SERVERS}
pm.max_spare_servers = ${PHP_FPM_PM_MAX_SPARE_SERVERS}
pm.max_requests = ${PHP_FPM_PM_MAX_REQUESTS}
74 changes: 74 additions & 0 deletions images/frankenphp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# FrankenPHP

We provide also a replacement like the official FrankenPHP image same Caddyfile, but with Wolfi.

## Usage example

```dockerfile
# 8.2 is also available
FROM ghcr.io/shyim/wolfi-php/frankenphp:8.3

# copy source code to /app/public
COPY . /app/public
```

```bash
docker build -t my-image .
docker run --rm -p 80:80 -p 443:443 my-image
```

## Disabling HTTPS

If you want to disable HTTPS, you can use the following environment variable:

```bash
dockr run \
--rm \
-e SERVER_NAME=:80 \
-p 80:80 my-image
```

## Available environment variables

- `SERVER_NAME` - The server name for Caddy. Default is `localhost` - This controls also the listing port of Caddy, use `:8000` as example for port `8000`
- `FRANKENPHP_CONFIG` - Allows to set configuration for FrankenPHP specific like: `worker ./public/index.php`
- `CADDY_GLOBAL_OPTIONS` - Allows to set global options for Caddy like: `debug`
- `CADDY_EXTRA_CONFIG` - Allows to set extra Caddy configuration like add new virtual host: `foo.com { root /app/public }`
- `CADDY_SERVER_EXTRA_DIRECTIVES` - Allows to set extra Caddy configuration for the default virtual host. [See here for all options](https://caddyserver.com/docs/caddyfile/directives)

## Rootless

To run the container, as a non-root user, you can do the following:

```dockerfile
FROM ghcr.io/shyim/wolfi-php/frankenphp:8.3

ARG USER=www-data

RUN \
mkdir -p /data/caddy && mkdir -p /config/caddy; \
apk add --no-cache libcap-utils; \
adduser -D ${USER}; \
# Add additional capability to bind to port 80 and 443
setcap CAP_NET_BIND_SERVICE=+eip /usr/bin/frankenphp; \
# Give write access to /data/caddy and /config/caddy
chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy; \
apk del libcap-utils

USER ${USER}
```

## Installing extensions

To install PHP extensions, you can use the `apk` package manager. For example, to install the `gd` extension, you can run:

```dockerfile
# pick one of these
FROM ghcr.io/shyim/wolfi-php/base:latest
# frankenphp one, bases on the base image
FROM ghcr.io/shyim/wolfi-php/frankenphp:8.3

RUN apk add --no-cache php-frankenphp-8.3-gd
```

It's important that you only install extensions matching to your PHP version and with the `php-frankenphp` prefix.

0 comments on commit 560f889

Please sign in to comment.