Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doc/improve readability #90

Merged
merged 3 commits into from
Apr 4, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 69 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ All being based on the official images we provide:

- PHP cli - Compiled without php-fpm, a simple php binary image
- PHP fpm - Specifically designed to share the php-fpm socket towards a fastcgi compliant web sever
- Nginx - Meant for PHP projects built on the PHP FPM image in this repository, since it looks for a php-fpm socket and doesn't have access to the PHP code
- Nginx - Meant for PHP projects built on the PHP FPM image in this repository, since [it looks for a php-fpm socket
and doesn't have access to the PHP code](docs/adr/0002-nginx-configuration-is-shaped-for-php-needs.md)

The fpm/HTTP server relationship:

Expand Down Expand Up @@ -70,13 +71,15 @@ 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.7` or `3.8`.
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.8` or `3.9`.

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.
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`
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.

Expand All @@ -86,17 +89,21 @@ The tag naming strategy consists of (Read as a regex):

- PHP: `(phpMajor).(phpMinor)-(cli|fpm)-(alpine|future supported OSes)(alpineMajor).(alpineMinor)(-dev)?`
- Example: `7.2-fpm-alpine3.8`, `7.2-fpm-alpine3.8-dev`
- Note: The minor version might come followed by special versioning constraints in case of betas, etc. For instance: `7.3-rc-fpm-alpine3.8-dev`
- Note: The minor version might come followed by special versioning constraints in case of betas, etc. For instance
`7.3-rc-fpm-alpine3.8-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`
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.
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
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

Expand Down Expand Up @@ -142,16 +149,19 @@ build-http: clean-tags

### Important

Removing a version from the build won't make it be removed from Docker registry, this has to be a manual operation if desired.
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](https://github.com/renatomefi/php-fpm-healthcheck) which allows you to healthcheck FPM apart from the Nginx setup, providing more compatibility with [the single process Docker container](https://cloud.google.com/solutions/best-practices-for-building-containers#package_a_single_app_per_container).
This image ships with the [php-fpm-healthcheck](https://github.com/renatomefi/php-fpm-healthcheck) which allows you to
healthcheck FPM independently of the Nginx setup, providing more compatibility with [the single process Docker
container](https://cloud.google.com/solutions/best-practices-for-building-containers#package_a_single_app_per_container).

This healthcheck provides diverse metrics to be watch and can be configured according to your needs.
More information on how to use it can be found in the [official documentation](https://github.com/renatomefi/php-fpm-healthcheck#a-php-fpm-health-check-script).
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](https://github.com/renatomefi/php-fpm-healthcheck#a-php-fpm-health-check-script).

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

Expand All @@ -171,7 +181,8 @@ Simply use the images as base of the application's `Dockerfile` and apply the ne
FROM usabillabv/php:7.3-fpm-alpine3.9
```

In usual cases it might not be necessary to extend the nginx images, unless you desire to extend its behavior by for instance serving static files.
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](#for-nginx-customization)

Expand All @@ -181,7 +192,9 @@ In usual cases it might not be necessary to extend the nginx images, unless you

### Document root configuration

Nginx is configured with only one virtual host, which is using `/opt/project/public` as 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.
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.:

Expand All @@ -194,45 +207,50 @@ 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.:
The default server name is `localhost` and that can also be overridden using an environment variable
(`NGINX_SERVER_NAME`) in the `Dockerfile`, e.g.:

```Dockerfile
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`.
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.:
These values can be overridden using environment variables (`NGINX_WORKERS_PROCESSES` and `NGINX_WORKERS_CONNECTIONS`)
in the `Dockerfile`, e.g.:

```Dockerfile
ENV NGINX_WORKERS_PROCESSES="4"
ENV NGINX_WORKERS_CONNECTIONS="2048"
```

Documentation for [worker_processes](http://nginx.org/en/docs/ngx_core_module.html#worker_processes)
and [worker_connections](http://nginx.org/en/docs/ngx_core_module.html#worker_connections)
and [worker_connections](http://nginx.org/en/docs/ngx_core_module.html#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.:
The default `keepalive_timeout` is `75` and that can also be overridden using an environment variable
(`NGINX_KEEPALIVE_TIMEOUT`) in the `Dockerfile`, e.g.:

```Dockerfile
ENV NGINX_KEEPALIVE_TIMEOUT="30"
```

More about it in the [Official documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout)
More about it in the [Official documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout).

### 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.:
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.:

```Dockerfile
ENV NGINX_CLIENT_BODY_BUFFER_SIZE="64k"
```

More about it in the [Official documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size)
More about it in the [Official documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size).

### Client max body size

Expand All @@ -243,7 +261,7 @@ larger payloads, e.g.:
ENV NGINX_CLIENT_MAX_BODY_SIZE="8m"
```

More about it in the [Official documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size)
More about it in the [Official documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size).

### Large client header buffers

Expand All @@ -254,7 +272,7 @@ 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](http://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers)
More about it in the [Official documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers).

### Expose Nginx version

Expand All @@ -270,13 +288,15 @@ ENV NGINX_EXPOSE_VERSION="on"

### 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.
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](https://github.com/docker-library/docs/blob/master/php/README.md#how-to-install-more-php-extensions)
More about it in the [Official Documentation](https://github.com/docker-library/docs/blob/master/php/README.md#how-to-install-more-php-extensions).

#### PHP Core extensions

To install a core extension that doesn't require any change on the way PHP was compiled you only need to use `docker-php-ext-install`, which will compile the extra extension and enable it.
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`:

Expand Down Expand Up @@ -311,9 +331,11 @@ RUN set -x \

#### PECL extensions

Some extensions are not provided with the PHP source, but are instead available through [PECL](https://pecl.php.net/), see a full list of them [here](https://pecl.php.net/packages.php).
Some extensions are not provided with the PHP source, but are instead available through [PECL](https://pecl.php.net/),
see a full list of them [here](https://pecl.php.net/packages.php).

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

```Dockerfile
# Installs ast extension (temporarily adding the necessary libraries):
Expand Down Expand Up @@ -344,7 +366,9 @@ RUN set -x \

#### 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:
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
Expand All @@ -355,9 +379,10 @@ Since [Xdebug](https://xdebug.org) is a common extension to be used we offer two

##### Dev image

Use the `dev` image by appending `-dev` to the end of the tag, like: `usabillabv/php:7.3-fpm-alpine3.9-dev`
Use the `dev` image by appending `-dev` to the end of the tag, like: `usabillabv/php:7.3-fpm-alpine3.9-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.
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 Xdebug and configure it.

Expand All @@ -369,23 +394,28 @@ Installing and enabling the extensions
$ docker-php-dev-mode xdebug
```

We also provide some default configuration to make it easier to start your debugging session, you can enable it also via the helper script.
We also provide some default configuration to make it easier to start your debugging session, you can enable it also via
the helper script.

The contents of the configuration can be found [here](src/php/conf/available/xdebug.ini)
The contents of the configuration can be found [here](src/php/conf/available/xdebug.ini).

```console
$ docker-php-dev-mode config
```

## 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.
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 leans.
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](https://github.com/moby/buildkit) enabled, this is what empowers the `RUN` mounts and more, check its documentation [here](https://docs.docker.com/develop/develop-images/build_enhancements/).
To be able to build this image you need [Docker buildkit](https://github.com/moby/buildkit) enabled, this is what
empowers the `RUN` mounts and more, check its documentation
[here](https://docs.docker.com/develop/develop-images/build_enhancements/).

```Dockerfile
# syntax=docker/dockerfile:1.0.0-experimental
Expand Down Expand Up @@ -456,7 +486,8 @@ $ DOCKER_BUILDKIT=1 docker build -t "my-project-dev:latest" \

### 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.
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.

```console
$ cp ~/.config/composer/auth.json .composer-auth.json
Expand Down