diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 6e87ec0..735f388 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -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 }} diff --git a/README.md b/README.md index d26ef22..59a452a 100644 --- a/README.md +++ b/README.md @@ -94,54 +94,14 @@ CMD [ "--config", "/etc/caddy/Caddyfile" ] After building the image, you can run the container with `docker run -p 8000:8000 ` 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 @@ -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) \ No newline at end of file +- [FPM standalone](examples/fpm/README.md) diff --git a/images/fpm/Dockerfile b/images/fpm/Dockerfile new file mode 100644 index 0000000..f177d6f --- /dev/null +++ b/images/fpm/Dockerfile @@ -0,0 +1,38 @@ +FROM ghcr.io/shyim/wolfi-php/base:latest + +ARG PHP_VERSION=8.3 + +RUN < [!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. diff --git a/images/fpm/rootfs/etc/php/conf.d/default.ini b/images/fpm/rootfs/etc/php/conf.d/default.ini new file mode 100644 index 0000000..1f32db0 --- /dev/null +++ b/images/fpm/rootfs/etc/php/conf.d/default.ini @@ -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} diff --git a/images/fpm/rootfs/etc/php/php-fpm.d/zz-b-default.conf b/images/fpm/rootfs/etc/php/php-fpm.d/zz-b-default.conf new file mode 100644 index 0000000..44b7ecc --- /dev/null +++ b/images/fpm/rootfs/etc/php/php-fpm.d/zz-b-default.conf @@ -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} diff --git a/images/frankenphp/README.md b/images/frankenphp/README.md new file mode 100644 index 0000000..ed5c8ed --- /dev/null +++ b/images/frankenphp/README.md @@ -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.