All Projects → usabilla → Php Docker Template

usabilla / Php Docker Template

Licence: mit
Docker images for PHP applications, CLI and FPM with shared socket

Programming Languages

shell
77523 projects

Projects that are alternatives of or similar to Php Docker Template

Sanic Nginx Docker Example
Sanic + Nginx + Docker basic example
Stars: ✭ 77 (-45.77%)
Mutual labels:  skeleton, nginx
Docker Skeleton Php
A simple Docker PHP development environment
Stars: ✭ 40 (-71.83%)
Mutual labels:  skeleton, nginx
Roothub
使用 SSM 和 MySQL 开发的论坛系统
Stars: ✭ 131 (-7.75%)
Mutual labels:  nginx
Docker Nginx Unprivileged
Unprivileged NGINX Dockerfiles
Stars: ✭ 141 (-0.7%)
Mutual labels:  nginx
Ngx http consul backend module
An nginx module for setting backends from Consul services.
Stars: ✭ 139 (-2.11%)
Mutual labels:  nginx
V2ray Agent
(VLESS+TCP+TLS/VLESS+TCP+XTLS/VLESS+gRPC+TLS/VLESS+WS+TLS/VMess+TCP+TLS/VMess+WS+TLS/Trojan+TCP+TLS/Trojan+gRPC+TLS/Trojan+TCP+XTLS)+伪装站点、八合一共存脚本,支持多内核安装
Stars: ✭ 4,133 (+2810.56%)
Mutual labels:  nginx
Lovinghome Real Estate Platform
⚡️基于springboot+MyBatis+FreeMarker+redis+nginx+Echarts+druid等技术的JavaWeb项目------恋家房产平台(采用B/S架构,项目包含前后台,分为前台展示系统及后台管理系统。前台系统包含首页门户、登录注册、房产推荐、房产详情、热门房产、房产及小区搜索、经纪人列表及经纪机构创建、创建房产、房产百科、地图找房、用户个人中心、房产评论、房产打分等模块。 后台管理系统包含房产信息管理、用户管理、管理员管理、小区信息管理、博客管理、评论管理、经纪人管理、系统统计与多种图表展示、数据报表导入导出等模块。系统介绍及详细功能点、技术点见项目内文档描述)
Stars: ✭ 140 (-1.41%)
Mutual labels:  nginx
Mern Authentication
MERN stack authentication boilerplate: password reset, email verification, server sessions, redux, hooks and docker for dev and prod.
Stars: ✭ 129 (-9.15%)
Mutual labels:  nginx
Nginx Http Flv Module
Media streaming server based on nginx-rtmp-module. In addtion to the features nginx-rtmp-module provides, HTTP-FLV, GOP cache and VHOST (one IP for multi domain names) are supported now.
Stars: ✭ 2,063 (+1352.82%)
Mutual labels:  nginx
E3 Springboot
SpringBoot+Docker重构宜立方商城
Stars: ✭ 139 (-2.11%)
Mutual labels:  nginx
Owasp Mth3l3m3nt Framework
OWASP Mth3l3m3nt Framework is a penetration testing aiding tool and exploitation framework. It fosters a principle of attack the web using the web as well as pentest on the go through its responsive interface.
Stars: ✭ 139 (-2.11%)
Mutual labels:  nginx
Nextjs Docker Pm2 Nginx
Next.js with Docker, PM2 and NGINX
Stars: ✭ 139 (-2.11%)
Mutual labels:  nginx
React Content Loader
⚪ SVG-Powered component to easily create skeleton loadings.
Stars: ✭ 11,830 (+8230.99%)
Mutual labels:  skeleton
Lotos
tiny but high-performance HTTP Server
Stars: ✭ 140 (-1.41%)
Mutual labels:  nginx
Nginx Ee
Automated Nginx compilation from sources with additional modules support. Compatible with WordOps, EasyEngine & Plesk
Stars: ✭ 132 (-7.04%)
Mutual labels:  nginx
Ssm Cluster
🍏Spring+SpringMVC+Mybatis+adminLTE3实现前后端分离(nginx负载均衡+tomcat集群)
Stars: ✭ 142 (+0%)
Mutual labels:  nginx
Api Umbrella
Open source API management platform
Stars: ✭ 1,735 (+1121.83%)
Mutual labels:  nginx
Docker Flask Gunicorn Nginx
Bootstrap example of a Flask app served via Gunicorn and Nginx using Docker conteiners
Stars: ✭ 138 (-2.82%)
Mutual labels:  nginx
Lua Resty Auto Ssl
On the fly (and free) SSL registration and renewal inside OpenResty/nginx with Let's Encrypt.
Stars: ✭ 1,786 (+1157.75%)
Mutual labels:  nginx
Docker Continuous Deployment
continuous deployment of a microservices application with Docker
Stars: ✭ 141 (-0.7%)
Mutual labels:  nginx

PHP Docker images template

Usabilla Logo

CircleCI Docker hub Docker hub Docker hub Usabilla Feedback Button

A series of Docker images to run PHP Applications on Usabilla Style

Architecture Decisions Records

This project adheres to ADRs, a list can be found here.

Version Support Policy

Our policy on versions we support is outlined in ADR0005.

Basic architecture

All being based on the official images we provide:

The fpm/HTTP server relationship:

+------------------------------+-----+            +--------------------+
|                              | :80 |            |                    |
|  FastCGI HTTP container      +-----+            |  PHP fpm container |
|                                    |            |                    |
|                                    |            |                    |
|       +-------------------------+  |            |  +--------------+  |
|       |  /var/run/php|fpm.sock  |<--------------+  |  Source code |  |
|       +-------------------------+  |            |  +--------------+  |
|                                    |            |                    |
+------------------------------------+            +--------------------+

Extra software

  • PHP
    • Shush - Used for decrypting our secret variables using AWS KMS
    • composer - To provide the installation of PHP projects
  • Nginx
    • A location.d helper to enable/disable custom location configuration

The base images

All images are based on their official variants, being:

Alpine Linux situation

Even though both of the images are based on the Alpine Linux, the PHP official repository gives us the option to choose between its versions, at this moment being 3.9 or 3.10.

Meanwhile on the official Nginx images we have no control over which Alpine version we use, this explains the tagging strategy coming in the next section.

The available tags

The docker registry prefix is usabillabv/php, thus usabillabv/php:OUR-TAGS.

In order to provide upgrade path we intend to keep one or more versions of PHP and Nginx.

Currently Available tags on Docker hub

The tag naming strategy consists of (Read as a regex):

  • PHP: (phpMajor).(phpMinor)-(cli|fpm)-(alpine|future supported OSes)(alpineMajor).(alpineMinor)(-dev)?
    • Example: 7.3-fpm-alpine3.11, 7.3-fpm-alpine3.11-dev
    • Note: The minor version might come followed by special versioning constraints in case of betas, etc. For instance 7.3-rc-fpm-alpine3.11-dev
  • Nginx: nginx(major).(minor)(-dev)?
    • Example: nginx1.15, nginx1.15-dev

Adding more supported versions

The whole CI/CD pipeline is centralized in Makefile targets, the build of cli, fpm and http (for now only nginx) images have their targets named as build-cli, build-fpm and build-http.

With the help of building scripts the addition of new versions is as easy as updating the Makefile with the desired new version.

All the newly built versions are going to be automatically tagged and pushed upon CI/CD success, to see the output of your new changes you can see the (BUILD).tags file in the tmp directory.

PHP

In this example adding PHP 7.4-rc for cli and fpm:

build-cli: clean-tags
	./build-php.sh cli 7.4 3.10
	./build-php.sh cli 7.4 3.11
+	./build-php.sh cli 7.4-rc 3.12

build-fpm: clean-tags
	./build-php.sh fpm 7.4 3.10
	./build-php.sh fpm 7.4 3.11
+	./build-php.sh fpm 7.4-rc 3.12

Being ./build-php.sh (cli/fpm) (PHP version) (Alpine version)

Nginx

In this example adding Nginx 1.16:

build-http: clean-tags
    ./build-nginx.sh 1.15 nginx
    ./build-nginx.sh 1.14
+   ./build-nginx.sh 1.16

Being ./build-nginx.sh (nginx version) (extra tag)

Note you can add extra tags, this means if you want to make Nginx 1.16 our new default version you have to:

build-http: clean-tags
-   ./build-nginx.sh 1.15 nginx
+   ./build-nginx.sh 1.15
    ./build-nginx.sh 1.14
-   ./build-nginx.sh 1.16
+   ./build-nginx.sh 1.16 nginx

Important

Removing a version from the build will not remove it from the Docker registry, this has to be done manually when desired.

Using and extending

PHP FPM healthcheck

This image ships with the php-fpm-healthcheck which allows you to healthcheck FPM independently of the Nginx setup, providing more compatibility with the single process Docker container.

This healthcheck provides diverse metrics to watch and can be configured according to your needs. More information on how to use it can be found in the official documentation.

The healthcheck can be found in the container $PATH as an executable:

$ php-fpm-healthcheck
$ echo $?
0

Basic usage

Simply use the images as base of the application's Dockerfile and apply the necessary changes.

# syntax=docker/dockerfile:1.0.0-experimental

FROM usabillabv/php:7.4-fpm-alpine3.12

In usual cases it might not be necessary to extend the nginx images, unless you desire to extend its behavior, for instance to serve static files.

Nginx customization

PHP customization

For Nginx customization

Document root configuration

Nginx is configured with only one virtual host, which is using /opt/project/public as the document root. Ideally we should change this configuration to point to the public directory of our project, so that we expose only what's necessary.

In order to do this you should override NGINX_DOCUMENT_ROOT environment variable in the Dockerfile, e.g.:

# assuming that your project is mounted/copied to `/project` and it has a public
# directory...

ENV NGINX_DOCUMENT_ROOT="/project/public"

Server name configuration

The default server name is localhost and that can also be overridden using an environment variable (NGINX_SERVER_NAME) in the Dockerfile, e.g.:

ENV NGINX_SERVER_NAME="myawesomeservice myawesomeservice.usabilla.com"

Workers

To use the most of your server you can tweak the number of nginx workers and connections accepted by them, the default values are (respectively): 1 and 1024.

These values can be overridden using environment variables (NGINX_WORKERS_PROCESSES and NGINX_WORKERS_CONNECTIONS) in the Dockerfile, e.g.:

ENV NGINX_WORKERS_PROCESSES="4"
ENV NGINX_WORKERS_CONNECTIONS="2048"

Documentation for worker_processes and worker_connections.

Connection keep alive timeout

The default keepalive_timeout is 75 and that can also be overridden using an environment variable (NGINX_KEEPALIVE_TIMEOUT) in the Dockerfile, e.g.:

ENV NGINX_KEEPALIVE_TIMEOUT="30"

More about it in the Official documentation.

Client body buffer size

The default client_body_buffer_size is 8k|16k (depending on architecture), having it configurable helps to not create disk body buffers in apps that don't splitting it, e.g.:

ENV NGINX_CLIENT_BODY_BUFFER_SIZE="64k"

More about it in the Official documentation.

Client max body size

The default client_max_body_size is 1m, you can increase it in case of larger payloads, e.g.:

ENV NGINX_CLIENT_MAX_BODY_SIZE="8m"

More about it in the Official documentation.

Large client header buffers

The default large_client_header_buffers is 4 8k, being number size you can increase it in case of larger header payloads, e.g.:

ENV NGINX_LARGE_CLIENT_HEADER_BUFFERS="8 128k"

More about it in the Official documentation.

Expose Nginx version

By default we are not exposing the nginx version in the Server header, that can also be overridden using an environment variable (NGINX_EXPOSE_VERSION) in the Dockerfile, e.g.:

ENV NGINX_EXPOSE_VERSION="on"

Cors configuration

There's a CORS helper available, it can be activated by running:

$ docker-nginx-location.d-enable cors

Or by setting an environment variable:

ENV NGINX_CORS_ENABLE=true

It's also possible to customize the Allow-Origin but setting an environment variable in the Dockerfile, e.g.:

ENV NGINX_CORS_ALLOW_ORIGIN="https://my-domain.cool"

For PHP customization

PHP-FPM Configuration

To allow tuning the FPM pool, some pool directives are configurable via the following environment variables. For more information on these directives, see the documentation.

Directive Environment Variable Default
pm PHP_FPM_PM dynamic
pm.max_children PHP_FPM_PM_MAX_CHILDREN 5
pm.start_servers PHP_FPM_PM_START_SERVERS 2
pm.min_spare_servers PHP_FPM_PM_MIN_SPARE_SERVERS 1
pm.max_spare_servers PHP_FPM_PM_MAX_SPARE_SERVERS 3
pm.process_idle_timeout PHP_FPM_PM_PROCESS_IDLE_TIMEOUT 10
pm.max_requests PHP_FPM_PM_MAX_REQUESTS 0
access.format PHP_FPM_ACCESS_FORMAT %R - %u %t "%m %r" %s

An example Dockerfile with customized configuration might look like:

# syntax=docker/dockerfile:1.0.0-experimental

FROM usabillabv/php:7.3-fpm-alpine3.11

ENV PHP_FPM_PM="static"
ENV PHP_FPM_PM_MAX_CHILDREN="70"
ENV PHP_FPM_PM_START_SERVERS="10"
ENV PHP_FPM_PM_MIN_SPARE_SERVERS="20"
ENV PHP_FPM_PM_MAX_SPARE_SERVERS="40" 
ENV PHP_FPM_PM_PROCESS_IDLE_TIMEOUT="35"
ENV PHP_FPM_PM_MAX_REQUESTS="500"
ENV PHP_FPM_ACCESS_FORMAT {\\\"cpu_usage\\\":%C,\\\"memory_usage\\\":%M,\\\"duration_microsecond\\\":%d,\\\"script\\\":\\\"%f\\\",\\\"content_length\\\":%l,\\\"request_method\\\":\\\"%m\\\",\\\"pool_name\\\":\\\"%n\\\",\\\"process_id\\\":\\\"%p\\\",\\\"request_query_string\\\":\\\"%q\\\",\\\"request_uri_query_string_glue\\\":\\\"%Q\\\",\\\"request_uri\\\":\\\"%r\\\",\\\"request_url\\\":\\\"%r%Q%q\\\",\\\"remote_ip_address\\\":\\\"%R\\\",\\\"response_status_code\\\":%s,\\\"time\\\":\\\"%t\\\",\\\"remote_user\\\":\\\"%u\\\"}

PHP configuration

The official PHP images ship with recommended ini configuration files for both development and production. In order to guarantee a reasonable configuration, our images load these files by default in each image respectively at this path: $PHP_INI_DIR/php.ini.

Images that wish to extend the ones provided in this repository can override these configurations easily by including customized configuration files in the $PHP_INI_DIR/conf.d/ directory.

Installing & enabling PHP extensions

This image bundles helper scripts to manage PHP extensions (docker-php-ext-configure, docker-php-ext-install, and docker-php-ext-enable), so it's quite simple to install core and PECL extensions.

More about it in the Official Documentation.

PHP Core extensions

To install a core extension that doesn't require any change in the way PHP is compiled you only need to use docker-php-ext-install, which will compile the extra extension and enable it.

To do it should include something like this to your Dockerfile:

# Enables opcache:
RUN set -x \
    && apk add --no-cache gnupg \
    && docker-php-source-tarball download \
    && docker-php-ext-install opcache \
    && docker-php-source-tarball delete

# Installs PDO driver for PostgreSQL (temporarily adding postgresql-dev to have
# the necessary C libraries):
RUN set -x \
    && apk add --no-cache gnupg postgresql-client postgresql-dev \
    && docker-php-source-tarball download \
    && docker-php-ext-install pdo_pgsql \
    && docker-php-source-tarball delete \
    && apk del gnupg postgresql-dev

Some core extensions, like GD, requires changes to PHP compilation. For that you should also use docker-php-ext-configure, e.g.:

# Installs GD extension and the required libraries: 
RUN set -x \
    apk add --no-cache freetype-dev libjpeg-turbo-dev libpng-dev \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install gd

PECL extensions

Some extensions are not provided with the PHP source, but are instead available through PECL, see a full list of them here.

To install a PECL extension, use pecl install to download and compile it, then use docker-php-ext-enable to enable it:

# Installs ast extension (temporarily adding the necessary libraries):
RUN set -x \
    && apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS \
    && pecl install ast \
    && docker-php-ext-enable ast \
    && apk del .phpize-deps

Check if the extension is loaded after building it:

$ docker build .
Successfully built 5bcf0f7d49b0
$ docker run --rm 5bcf0f7d49b0 php -m | grep ast
ast
# Installs MongoDB Driver (temporarily adding the necessary libraries):
RUN set -x \
    && apk add --no-cache --virtual .build-deps $PHPIZE_DEPS openssl-dev  \
    && pecl install mongodb-1.5.3 \
    && docker-php-ext-enable mongodb \
    && apk del .build-deps

Common extension helper scripts

Some extensions are used across multiple projects but can have some complexities while installing so we ship helper scripts with the PHP images to install dependencies and enable the extension. The following helper scripts can be run inside projects' Dockerfile:

  • docker-php-ext-rdkafka for RD Kafka
  • docker-php-ext-pdo-pgsql for PDO Postgres

Xdebug

Since Xdebug is a common extension to be used we offer two options:

Dev image

Use the dev image by appending -dev to the end of the tag, like: usabillabv/php:7.3-fpm-alpine3.11-dev.

Not recommended if you're layering with your production images, using a different base image doesn't allow to you share cache among your Dockerfile targets.

We ship the image with a dev mode helper, which can install and configure Xdebug, as well as override the production php.ini with the recommended development version.

Helper script

Installing and enabling the extensions

$ docker-php-dev-mode xdebug

As mentioned, we override the production php.ini with the recommended development version, which can be found here.

Next to that we provide some additional configuration to make it easier to start your debugging session. The contents of that configuration can be found here.

Both are enabled via the helper script, by running

$ docker-php-dev-mode config
Setting up Xdebug

Xdebug 3 comes with new mechanism to enable it's functionalities. The most notable, is the introduction of the xdebug.mode setting, which controls which features are enabled. It can be specified via .ini files or by using the environment variable XDEBUG_MODE. To learn more about the different modes in which Xdebug can be configured, please refer to the Xdebug settings guide.

Notable changes from Xdebug 2

With the introduction of the Xdebug mode in the v3 release, it is now mandatory to specify either xdebug.mode=coverage setting in .ini file, or XDEBUG_MODE=coverage as environment variable, to use the code coverage analysis features. This impacts tools like mutation tests.

We recommend setting the XDEBUG_MODE when booting up a new container. Here's an example on how it could look like:

docker run -it \
  -e XDEBUG_MODE=coverage \
  -v "<HOST_PATH>:<CONTAINER_PATH>" \
  usabillabv/php:7.4-cli-alpine3.12-dev \
  vendor/bin/infection --test-framework-options='--testsuite=unit' -s --threads=12 --min-msi=100 --min-covered-msi=100

Another notable change, is the Xdebug port change. The default port is now 9003 instead of 9000. Check your IDE settings to confirm the correct port is specified.

For the full upgrade guide, please refer to the official upgrade guide.

Prometheus Exporter

In order to monitor applications many systems implement Prometheus to expose metrics, one challenge specially in PHP is how to expose those to Prometheus without having to, either implement an endpoint in our application, or add HTTP and an endpoint for non-interactive containers.

This prove has the aim to provide support for the sidecar pattern for monitoring.

More about "Make your application easy to monitor" by Google

Static File

The easiest way to solve this problem in the PHP ecosystem is to make your application write down the metrics to a text file, which then is shared via a volume to a sidecar container which can expose it to Prometheus.

The container we offer is a simple Nginx based on the same configuration as the one for PHP-FPM, with the difference it only serves static content.

Docker image

The image named prometheus-exporter-file is available via our docker registry under with the tags (from less to more specific versions):

  • usabillabv/php:prometheus-exporter-file - This has the behavior of latest
  • usabillabv/php:prometheus-exporter-file1
  • usabillabv/php:prometheus-exporter-file1.0

Kubernetes Deployment Example

# Pod v1 core Spec - https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#pod-v1-core

spec:
  template:
    metadata:
      annotations:
        prometheus.io/path: /metrics
        prometheus.io/port: "5556"
        prometheus.io/scrape: "true"
    spec:
      containers:
      - image: usabillabv/php:7.3-cli-alpine3.11
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /prometheus
          name: prometheus-metrics
      - image: usabillabv/php:prometheus-exporter-file1
        imagePullPolicy: IfNotPresent
        name: prometheus-exporter
        env:
        - name: NGINX_PORT
          value: "5556"
        ports:
        - containerPort: 5556
          name: http
          protocol: TCP
        volumeMounts:
        - mountPath: /opt/project/public
          name: prometheus-metrics
      volumes:
      - emptyDir: {}
        name: prometheus-metrics

In this example the PHP container must write down the metrics in the file /prometheus/metrics, the exporter container will have the same file mount at /opt/project/public/metrics. Which will then be available via http as http://pod:5556/metrics, observe that the filename becomes the url which we configured the prometheus scrape to look for.

Open Census

To be created and/or documented

For now please refer to: https://github.com/basvanbeek/opencensus-php-docker and https://github.com/census-instrumentation/opencensus-php

Dockerfile example

The Dockerfile in the example below is meant to centralize the production and development images in a single Dockerfile, sharing cached layers among the build steps, cleaning unnecessary files like tests, docs and readme files from the final result via git archive.

Composer auth is done via a secret mount to avoid layering credentials and keeping the layers lean.

We also run the image with the app user since doing it as root is considered a bad practice.

To be able to build this image you need Docker buildkit enabled, this is what empowers the RUN mounts and more, check its documentation here.

# syntax=docker/dockerfile:1.0.0-experimental

# The base target will serve as initial layer for dev and prod images,
# thus all necessary global configurations, extensions and modules
# should be put here
FROM usabillabv/php:7.3-fpm-alpine3.11 AS base

# When composer gets copied we want to make sure it's from the major version 1
FROM composer:1 as composer

# The source target is responsible to prepare the source code by cleaning it and
# installing the necessary dependencies, it's later copied into the production
# target, which then leaves no traces of the build process behind whilst making
# the image lean
FROM base as source

ENV COMPOSER_HOME=/opt/.composer

RUN apk add --no-cache git

COPY --from=composer /usr/bin/composer /usr/bin/composer

WORKDIR /opt/archived

# Mount the current directory at `/opt/project` and run git archive
# hadolint ignore=SC2215
RUN --mount=type=bind,source=./,rw \
    mkdir -p /opt/project \
    && git archive --verbose --format tar HEAD | tar -x -C /opt/project

WORKDIR /opt/project

# Mount composer.auth to the project root and composer cache if available
# then install the dependencies
# hadolint ignore=SC2215
RUN --mount=type=secret,id=composer.auth,target=/opt/project/auth.json \
    --mount=type=bind,source=.composer/cache,target=/opt/.composer/cache \
    composer install --no-interaction --no-progress --no-dev --prefer-dist --classmap-authoritative

# Copy the source from its target and prepare permissions
FROM base as prod

WORKDIR /opt/project

COPY --chown=app:app --from=source /opt/project /opt/project

# Install Xdebug and enable development specific configuration
# also create a volume for the project which will later be mount via run
FROM base AS dev

COPY --chown=app:app --from=composer /usr/bin/composer /usr/bin/composer

RUN docker-php-dev-mode xdebug \
    && docker-php-dev-mode config

VOLUME [ "/opt/project" ]

Building this image as dev

$ DOCKER_BUILDKIT=1 docker build -t "my-project-dev:latest" \
  --target=dev .

Building this image as prod

You want to run this in your CI/CD environment, you can create the composer.auth file there, for this example let's get your computer's file and mount the secret.

$ cp ~/.config/composer/auth.json .composer-auth.json
$ DOCKER_BUILDKIT=1 docker build -t "my-project-prod:latest" \
  --target=prod \
  --secret id=composer.auth,src=.composer-auth.json

Working example

We also have a simple, but fully functional PHP FPM example, check it here.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].