Giter Club home page Giter Club logo

kubephp's Introduction

KubePHP - Production Grade, Rootless, Optimized, PHP Container Image for Cloud Native PHP Apps ๐Ÿณ

Compatible with popular PHP Frameworks such as Laravel 5+ & Symfony 4+ and their variants.
Typically deployed on Kubernetes.

Build PHP >=7^ | >=8^ GitHub forks GitHub issues GitHub license contributions welcome

Introduction

Production Grade Image for PHP 7+ Applications running Nginx + PHP FPM based on PHP & Nginx Official Images, compatible with popular PHP Frameworks such as Laravel 5+ & Symfony 4+ and their variants.

  • This is a pre-configured template image for your PHP Application, and you shall extend and edit it according to your app requirements. (instructions below)
  • The Image utilizes multistage builds to create multiple targets optimized for production and development usecases.
  • Image designed to be run in Kubernetes.
  • Supports PHP applications that uses a single-entrypoint framework in public/index.php, such as Laravel, Symfony, and all their variants.

Features ๐Ÿ“œ

  • Designed to run in orchestrated environments like Kubernetes.
  • Uses Alpine based images and multistage builds for minimal images. (~130 MB)
  • Multi-Container setup with Nginx & PHP-FPM communicating via TCP.
  • Productions Image that are immutable and fully contained.
  • Runs as non-root in both application containers.
  • Configured for graceful shutdowns/restarts, zero downtime deployments, auto-healing, and auto-scaling.
  • Easily extend the image with extra configuration, and scripts; such as post-build & pre-run scripts.
  • Minimal startup time, container almost start serving requests almost instantly.
  • Image tries to fail at build time as much as possible by running all sort of checks.
  • Ability to run Commands, Consumers and Crons using same image. (No supervisor or crontab)
  • Development Image supports mounting code and hot-reloading and XDebug.

How to use with my project ?

  • Copy this repository Dockerfile, docker Directory, Makefile, docker-compose.yml, docker-compose.prod.yml and .dockerignore to your application root directory and configure it to your needs.

How to configure image to run my project ?

You'll need to iterate over your application's dependency system packages, and required PHP Extensions; and add them to their respective locations in the image.

  1. Add System Dependencies and PHP Extensions your application depends on to the Image.
  2. Port in any configuration changes you made for PHP.ini to the image, otherwise use the sane defaults.
  3. make build && make up for development setup, make deploy to run the production variant.

These steps explained in details below.

How is it deployed ?

Your application will be split into two components.

  1. The Webserver -> Server Static Content and proxy dynamic requests to PHP-FPM over TCP, webserver also applies rate limiting, security headers... and whatever it is configured for.
  2. The PHP Process -> PHP FPM process that will run you PHP Code.

Other type of deployments such as a cron-job, or a supervised consumer can be achieved by overriding the default image CMD.


Requirements

Setup

1. Add Template to your repo.

  1. Download This Repository
  2. Copy Dockerfile, docker Directory, Makefile, docker-compose.yml, docker-compose.prod.yml and .dockerignore Into your Application Repository.

OR

create repository from template

2. Start

  1. Modify Dockerfile to your app needs, and add your app needed OS Packages, and PHP Extensions.
    1. Dockerfile Header has Build Time Arguments, customize it, most notably the RUNTIME_DEPS argument.
    2. Below in the base image, add the PHP Extensions your application depends on.
  2. Run make up for development or make deploy for production.
    1. For Dev: make up is just an alias for docker-compose up -d
    2. For Dev: Make sure to delete previous vendor directory if you had it before.
    3. Docker-Compose will start App container first, and only start Web server when it's ready, on initial install, it might take some time.
  3. Go to http://localhost

Makefile is just a wrapper over docker-compose commands.

Building, Configuring and Extending Image

Image Targets and Build Arguments

  • The image comes with a handy Makefile to build the image using Docker-Compose files, it's handy when manually building the image for development or in a not-orchestrated docker host. However, in an environment where CI/CD pipelines will build the image, they will need to supply some build-time arguments for the image. (tho defaults exist.)

    Build Time Arguments

    ARG Description Default
    PHP_VERSION PHP Version used in the Image 7.4
    PHP_ALPINE_VERSION Alpine Version for the PHP Image 3.15
    NGINX_VERSION Nginx Version 1.21
    COMPOSER_VERSION Composer Version used in Image 2.0
    COMPOSER_AUTH A Json Object with Bitbucket or Github token to clone private Repos with composer.
    Reference
    {}
    XDEBUG_VERSION Xdebug Version to use in Development Image 3.1.3

    Image Targets

    Target Env Desc Size Based On
    app Production The PHP Application with immutable code/dependencies. By default starts PHP-FPM process listening on 9000. Command can be extended to run any PHP Consumer/Job, entrypoint will still start the pre-run setup and then run the supplied command. ~135mb PHP Official Image (Alpine)
    web Production The webserver, an Nginx container that is configured to server static content and forward dynamic requests to the PHP-FPM container running in the app image variant ~21mb Nginx Official Image (Alpine)
    app-dev Development Development PHP Application variant with dependencies inside. Image expects the code to be mounted on /app to support hot-reloading. You need to mount dummy /app/vendor volume too to avoid code volume to overwrite dependencies already inside the image. ~150mb PHP Official Image (Alpine)
    web-dev Development Development Webserver with the exact configuration as the production configuration. Expects public directory to be mounted at /app/public ~21mb Nginx Official Image (Alpine)

Install System Dependencies and PHP Extensions

  • The image is to be used as a base for your PHP application image, you should modify its Dockerfile to your needs.

    1. Install System Packages in the following section in the Dockerfile.
      • Add OS Packages needed in RUNTIME_DEPS in Dockerfile.
    2. Install PHP Extensions In the following section in the Dockerfile.
    # ---------------------------------------- Install / Enable PHP Extensions ---------------------------------------------
    RUN docker-php-ext-install \
    opcache     \
    intl        \
    pdo_mysql   \
    # Pecl Extentions
    RUN pecl install apcu-5.1.20 && docker-php-ext-enable apcu
    #   EX: RUN pecl install memcached && docker-php-ext-enable memcached
Note

At build time, Image will run composer check-platform-reqs to check that PHP and extensions versions match the platform requirements of the installed packages.

PHP Configuration

  1. PHP base Configuration that are common in all environments in docker/php/base-php.ini๐Ÿ”—
  2. PHP prod Only Configuration docker/php/php-prod.ini๐Ÿ”—
  3. PHP dev Only Configuration docker/php/php-dev.ini๐Ÿ”—

PHP FPM Configuration

  1. PHP FPM Configuration docker/fpm/*.conf ๐Ÿ”—

Nginx Configuration

  1. Nginx Configuration docker/nginx/*.conf && docker/nginx/conf.d/* ๐Ÿ”—

Post Build and Pre Run optional scripts.

In docker/ directory there is post-build-* and pre-run-* scripts that are used to extend the image and add extra behavior.

  1. post-build command runs at the end of Image build.

    Run as the last step during the image build. Are Often framework specific commands that generate optimized builds, generate assets, etc.

  2. pre-run command runs in runtime before running the container main command

    Runs before the container's CMD, but after the composer's post-install and post-autload-dump. Used for commands that needs to run at runtime before the application is started. Often are scripts that depends on other services or runtime parameters.

  3. *-base scripts run on both production and development images.


Misc Notes

  • Your application should log app logs to stdout.. Read about 12factor/logs
  • By default, php-fpm access logs are disabled as they're mirrored on nginx, this is so that php-fpm image will contain only application logs written by PHP.
  • In production, Image contains source-code, however, you must sync both php-fpm and nginx images so that they contain the same build.

FAQ

  1. Why two containers instead of one ?

    • In containerized environment, you need to only run one process inside the container. This allows us to better instrument our application for many reasons like separation of health status, metrics, logs, etc.
  2. Image Build Fails as it try to connect to DB.

License

MIT License Copyright (c) 2022 Sherif Abdel-Naby

Contribution

PR(s) are Open and welcomed.

kubephp's People

Contributors

aszenz avatar aurimasniekis avatar harkuli avatar sherifabdlnaby avatar tigitz avatar vadymtrofymenko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kubephp's Issues

Can't copy dev scripts from docker

Describe the bug
Got the error when trying to the run make up command

To Reproduce

  1. Clone the repository
  2. Run make up

Screenshot from 2022-05-13 08-27-42

 > [app-dev 3/3] RUN chmod +x /usr/local/bin/*-dev;     mv "/usr/local/etc/php/php.ini-development" "/usr/local/etc/php/php.ini" COPY docker/php/dev-*   /usr/local/etc/php/conf.d/:                              
#23 0.381 mv: can't rename 'COPY': No such file or directory                                             
#23 0.381 mv: can't rename 'docker/php/dev-*': No such file or directory
------
executor failed running [/bin/ash -eo pipefail -c chmod +x /usr/local/bin/*-dev;     mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" COPY docker/php/dev-*   $PHP_INI_DIR/conf.d/]: exit code: 1
ERROR: Service 'app' failed to build : Build failed
make: *** [Makefile:16: up] Error 1

Ubuntu 20.04.4
Docker 20.10.15

Stuck on "โ–บ Running Composer Install..."

Hello
I'm trying this out for my application, but when i run docker-compose up -d, the app container is stuck at:
โ–บ Running Composer Install...
No more log output after that.
I tried deleting the vendor folder, but same result.

How to share and keep synced code inside /app/public between php fpm and nginx container in k8s ?

I made this deployment.
I created a k8s cluster with one node locally on my computer.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  labels:
    app: backend
spec:
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend-nginx
          image: my-backend_nginx
          imagePullPolicy: Always
          ports:
            - name: nginx
              containerPort: 8080
          env:
            - name: PHP_FPM_HOST
              value: 127.0.0.1
        - name: backend-php-fpm
          image: my-backend_php-fpm
          imagePullPolicy: Always
          ports:
            - name: php-fpm
              containerPort: 9000
          envFrom:
            - configMapRef:
                name: backend-configmap

When user upload files, they are stored into /app/public/media (not empty) under php-fpm container
My problem is that those files are not replicated inside nginx container under same path /app/public/media (empty).

Thanks in advance.

nginx: [emerg] no "events" section in configuration

Hi,

I encountered the following error when trying to start:

web_1  | 2019/10/06 08:12:13 [emerg] 1#1: no "events" section in configuration
web_1  | nginx: [emerg] no "events" section in configuration
symdocker_web_1 exited with code 1

Steps to reproduce:

  • Create composer.json with a dependency so the build script does not stop when trying to copy composer.json and composer.lock
  • make build
  • make up

php:*-fpm-alpine as base image

Thanks a lot for phpdocker! Love it!

Just curious why the alpine version of php-fpm wasn't used as a base image? It's smaller and since there's already nginx-alpine version so it's can be a reason to do the same with PHP.

Issue with installing extensions

I got the following error

 > [app 6/6] RUN post-build-base && post-build-prod:
#30 0.177 โ–บ Running Composer Install...
#30 0.284 Installing dependencies from lock file
#30 0.286 Verifying lock file contents can be installed on current platform.
#30 0.306 Your lock file does not contain a compatible set of packages. Please run composer update.
#30 0.306
#30 0.306   Problem 1
#30 0.306     - Root composer.json requires PHP extension ext-zip * but it is missing from your system. Install or enable PHP's zip extension.
#30 0.306   Problem 2
#30 0.306     - Root composer.json requires PHP extension ext-pcntl * but it is missing from your system. Install or enable PHP's pcntl extension.
#30 0.306   Problem 3
#30 0.306     - Root composer.json requires PHP extension ext-imap * but it is missing from your system. Install or enable PHP's imap extension.
#30 0.306   Problem 4
#30 0.306     - Root composer.json requires PHP extension ext-intl * but it is missing from your system. Install or enable PHP's intl extension.
#30 0.306   Problem 5
#30 0.306     - Root composer.json requires PHP extension ext-tidy * but it is missing from your system. Install or enable PHP's tidy extension.
#30 0.306   Problem 6
#30 0.306     - 2amigos/qrcode-library is locked to version 1.1.2 and an update of this package was not requested.
#30 0.306     - 2amigos/qrcode-library 1.1.2 requires ext-gd * -> it is missing from your system. Install or enable PHP's gd extension.
#30 0.306   Problem 7
#30 0.306     - php-amqplib/php-amqplib is locked to version v2.12.3 and an update of this package was not requested.
#30 0.306     - php-amqplib/php-amqplib v2.12.3 requires ext-sockets * -> it is missing from your system. Install or enable PHP's sockets extension.
#30 0.306
#30 0.306 To enable extensions, verify that they are enabled in your .ini files:
#30 0.306     - /usr/local/etc/php/php.ini
#30 0.306     - /usr/local/etc/php/conf.d/base-php.ini
#30 0.306     - /usr/local/etc/php/conf.d/docker-php-ext-sodium.ini
#30 0.306     - /usr/local/etc/php/conf.d/prod-php.ini
#30 0.306 You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.

My Dockerfile contains this section and everything else is default config

...
 # PHP Extensions --------------------------------- \
 && docker-php-ext-install -j$(nproc) \
      intl        \
      opcache     \
      pdo_mysql   \
      zip         \
      mysql       \
      bcmath      \
      bz2         \
      gd          \
      gmp         \
      imap        \
      ldap        \
      tidy        \
      xsl         \
      curl        \
      json        \
      dev         \
      mbstring    \
      xml         \
      pcntl       \
...

When I run make build it throws out that error. What could be the issue? Any help would be appreciated. It's a Yii framework PHP app.

How to use with Laravel?

When I use this along with laravel nginx shows an error:
Warning: require(/var/www/app/public/../vendor/autoload.php): Failed to open stream: No such file or directory in /var/www/app/public/index.php on line 34
As I understand it, this happens because only the public folder is copied for the nginx container. Should I add the entire laravel folder as a volume for nginx or can it be done differently?

Use simple php app

Sorry I feel like I am the only one asking silly questions here but what if you are hosting "Yii" app which doesn't serve from the public folder. Or if you have just index.php which you want to use without any composer. How would I go about then for both these scenarios? What parts would I need to modify in Dockerfile or maybe I don't need to touch that file at all?

Mounting volumes and permissions

When a volume is mounted, either pvc or empty, they are mounted as root, and they cannot be chmodded or chowned(in init script), as the user in the pods is www-data(which is good).
The current way i'm handling this, is by creating an init pod, which actually uses root as user, and then run an init script.
Is this the best way to do it? Maybe kubephp should have an init container which uses root user?

APP_BASE_DIR

Hello i want to create project and project folder structure:
project_api
project_web
Dockerfile
docker-compose.yml
...
I'm setting APP_BASE_DIR arg in Dockerfile like './project_api' or '/project_api' but i get an error Running Composer Install... Composer could not find a composer.json file in /var/www. What else should i set it.

UPDATE :
Also i need to change etrypoint scripts.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.