From d59db2112ea379a53c1575133fff7570d867c366 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 15:30:58 +0100 Subject: [PATCH 01/11] #190: Updates metadata org.deathe.description to include PHP redis. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6a09119..a9cf89b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -85,6 +85,6 @@ jdeathe/centos-ssh-apache-php-fcgi:${RELEASE_VERSION} \ org.deathe.license="MIT" \ org.deathe.vendor="jdeathe" \ org.deathe.url="https://github.com/jdeathe/centos-ssh-apache-php-fcgi" \ - org.deathe.description="CentOS-6 6.10 x86_64 - Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP APC 3.1." + org.deathe.description="CentOS-6 6.10 x86_64 - Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP redis 2.2, PHP APC 3.1." CMD ["/usr/bin/supervisord", "--configuration=/etc/supervisord.conf"] From cf594a51e18d2f4453cc64f9fed6e30ff96d8e5f Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 15:34:54 +0100 Subject: [PATCH 02/11] #196: Adds .env to .gitignore. --- .gitignore | 1 + CHANGELOG.md | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 1db27ab..01faf4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +.env packages dist \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index fde45b9..7aa0235 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ Summary of release changes for Version 1. CentOS-6 6.10 x86_64, Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP APC 3.1. +### 1.13.0 - Unreleased + +- Adds `.env` files to `.gitignore` for exclusion from version control. + ### 1.12.0 - 2019-04-14 - Updates image source to [1.12.0](https://github.com/jdeathe/centos-ssh-apache-php/releases/tag/1.12.0). From 93e50abf69427b8dfb9d67a10121573df9e7ad1f Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 15:46:13 +0100 Subject: [PATCH 03/11] #189: Removes unused variable. --- CHANGELOG.md | 1 + environment.mk | 1 - src/opt/scmi/environment.sh | 1 - test/shpec/operation_shpec.sh | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7aa0235..7685b3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ CentOS-6 6.10 x86_64, Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP ### 1.13.0 - Unreleased - Adds `.env` files to `.gitignore` for exclusion from version control. +- Removes unused `DOCKER_PORT_MAP_TCP_22` variable from environment includes. ### 1.12.0 - 2019-04-14 diff --git a/environment.mk b/environment.mk index 7437bf8..a4131b9 100644 --- a/environment.mk +++ b/environment.mk @@ -17,7 +17,6 @@ DOCKER_IMAGE_RELEASE_TAG_PATTERN := ^(1|centos-6-1)\.[0-9]+\.[0-9]+$ DOCKER_CONTAINER_OPTS ?= DOCKER_IMAGE_TAG ?= latest DOCKER_NAME ?= apache-php.1 -DOCKER_PORT_MAP_TCP_22 ?= NULL DOCKER_PORT_MAP_TCP_80 ?= 8080 DOCKER_PORT_MAP_TCP_443 ?= 9443 DOCKER_PORT_MAP_TCP_8443 ?= NULL diff --git a/src/opt/scmi/environment.sh b/src/opt/scmi/environment.sh index 8cfc26f..a4b4f27 100644 --- a/src/opt/scmi/environment.sh +++ b/src/opt/scmi/environment.sh @@ -16,7 +16,6 @@ readonly DOCKER_IMAGE_RELEASE_TAG_PATTERN='^(1|centos-6-1)\.[0-9]+\.[0-9]+$' DOCKER_CONTAINER_OPTS="${DOCKER_CONTAINER_OPTS:-}" DOCKER_IMAGE_TAG="${DOCKER_IMAGE_TAG:-latest}" DOCKER_NAME="${DOCKER_NAME:-apache-php.1}" -DOCKER_PORT_MAP_TCP_22="${DOCKER_PORT_MAP_TCP_22:-NULL}" DOCKER_PORT_MAP_TCP_80="${DOCKER_PORT_MAP_TCP_80:-8080}" DOCKER_PORT_MAP_TCP_443="${DOCKER_PORT_MAP_TCP_443:-9443}" DOCKER_PORT_MAP_TCP_8443="${DOCKER_PORT_MAP_TCP_8443:-NULL}" diff --git a/test/shpec/operation_shpec.sh b/test/shpec/operation_shpec.sh index 0cae6e7..498ab67 100644 --- a/test/shpec/operation_shpec.sh +++ b/test/shpec/operation_shpec.sh @@ -4,7 +4,6 @@ readonly TEST_DIRECTORY="test" # These should ideally be a static value but hosts might be using this port so # need to allow for alternatives. -DOCKER_PORT_MAP_TCP_22="${DOCKER_PORT_MAP_TCP_22:-NULL}" DOCKER_PORT_MAP_TCP_80="${DOCKER_PORT_MAP_TCP_80:-8080}" DOCKER_PORT_MAP_TCP_443="${DOCKER_PORT_MAP_TCP_443:-9443}" DOCKER_PORT_MAP_TCP_8443="${DOCKER_PORT_MAP_TCP_8443:-NULL}" From dc7405b83933505e4d94e85fa1c37a68c3b15af3 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 15:50:01 +0100 Subject: [PATCH 04/11] #199: Updates description in systemd register unit file. --- CHANGELOG.md | 1 + .../system/centos-ssh-apache-php-fcgi.register@.service | 3 ++- src/etc/systemd/system/centos-ssh-apache-php-fcgi@.service | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7685b3b..11a87b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ CentOS-6 6.10 x86_64, Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP ### 1.13.0 - Unreleased +- Updates description in `centos-ssh-apache-php-fcgi.register@.service`. - Adds `.env` files to `.gitignore` for exclusion from version control. - Removes unused `DOCKER_PORT_MAP_TCP_22` variable from environment includes. diff --git a/src/etc/systemd/system/centos-ssh-apache-php-fcgi.register@.service b/src/etc/systemd/system/centos-ssh-apache-php-fcgi.register@.service index b2efc2a..5fc25b2 100644 --- a/src/etc/systemd/system/centos-ssh-apache-php-fcgi.register@.service +++ b/src/etc/systemd/system/centos-ssh-apache-php-fcgi.register@.service @@ -35,12 +35,13 @@ # # To uninstall: # sudo systemctl disable -f {service-unit-instance-name} +# sudo systemctl daemon-reload # sudo rm /etc/systemd/system/{service-unit-template-name} # sudo systemctl daemon-reload # ------------------------------------------------------------------------------ [Unit] -Description=centos-apache-php-fcgi etcd registration // %p@%i +Description=centos-ssh-apache-php-fcgi etcd registration // %p@%i After=etcd.service After=etcd2.service After={{SERVICE_UNIT_NAME}}@%i.service diff --git a/src/etc/systemd/system/centos-ssh-apache-php-fcgi@.service b/src/etc/systemd/system/centos-ssh-apache-php-fcgi@.service index 74adfe3..7988005 100644 --- a/src/etc/systemd/system/centos-ssh-apache-php-fcgi@.service +++ b/src/etc/systemd/system/centos-ssh-apache-php-fcgi@.service @@ -50,7 +50,6 @@ After=docker.service Restart=on-failure RestartSec=30 TimeoutStartSec=1200 -Environment="DOCKER_USER=jdeathe" Environment="DOCKER_CONTAINER_OPTS=" Environment="DOCKER_IMAGE_PACKAGE_PATH=/var/opt/scmi/packages" Environment="DOCKER_IMAGE_NAME=centos-ssh-apache-php-fcgi" @@ -58,6 +57,7 @@ Environment="DOCKER_IMAGE_TAG={{RELEASE_VERSION}}" Environment="DOCKER_PORT_MAP_TCP_80=8080" Environment="DOCKER_PORT_MAP_TCP_443=9443" Environment="DOCKER_PORT_MAP_TCP_8443=NULL" +Environment="DOCKER_USER=jdeathe" Environment="APACHE_AUTOSTART_HTTPD_BOOTSTRAP=true" Environment="APACHE_AUTOSTART_HTTPD_WRAPPER=true" Environment="APACHE_CONTENT_ROOT=/var/www/app" From f4e799db733edbcd7a727512384884f7e8164b50 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 15:57:55 +0100 Subject: [PATCH 05/11] #188: Updates documentation and related info. --- CHANGELOG.md | 10 +- Dockerfile | 2 +- README-short.txt | 2 +- README.md | 290 +++++++++++++---------------------------------- command-keys.md | 67 ----------- 5 files changed, 85 insertions(+), 286 deletions(-) delete mode 100644 command-keys.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 11a87b1..c5ecbbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,16 @@ # Change Log -## centos-6 +## 1 - centos-6 -Summary of release changes for Version 1. - -CentOS-6 6.10 x86_64, Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP APC 3.1. +Summary of release changes. ### 1.13.0 - Unreleased - Updates description in `centos-ssh-apache-php-fcgi.register@.service`. +- Updates CHANGELOG.md to simplify maintenance. +- Updates README.md to simplify contents and improve readability. +- Updates README-short.txt to apply to all image variants. +- Updates Dockerfile `org.deathe.description` metadata LABEL for consistency + include PHP redis module. - Adds `.env` files to `.gitignore` for exclusion from version control. - Removes unused `DOCKER_PORT_MAP_TCP_22` variable from environment includes. diff --git a/Dockerfile b/Dockerfile index a9cf89b..2676307 100644 --- a/Dockerfile +++ b/Dockerfile @@ -85,6 +85,6 @@ jdeathe/centos-ssh-apache-php-fcgi:${RELEASE_VERSION} \ org.deathe.license="MIT" \ org.deathe.vendor="jdeathe" \ org.deathe.url="https://github.com/jdeathe/centos-ssh-apache-php-fcgi" \ - org.deathe.description="CentOS-6 6.10 x86_64 - Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP redis 2.2, PHP APC 3.1." + org.deathe.description="Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP redis 2.2, PHP APC 3.1 - CentOS-6 6.10 x86_64." CMD ["/usr/bin/supervisord", "--configuration=/etc/supervisord.conf"] diff --git a/README-short.txt b/README-short.txt index d9c70ee..036f109 100644 --- a/README-short.txt +++ b/README-short.txt @@ -1 +1 @@ -CentOS-6 6.10 x86_64 - Apache / PHP-CGI (FastCGI) / PHP memcached / PHP APC. \ No newline at end of file +Apache PHP-CGI (FastCGI) - CentOS. \ No newline at end of file diff --git a/README.md b/README.md index 2e2d2ab..df7c83d 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,22 @@ -centos-ssh-apache-php-fcgi -========================== +### Tags and respective `Dockerfile` links -Docker Image including: -- CentOS-6 6.10 x86_64, Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP APC 3.1. -- CentOS-7 7.5.1804 x86_64, Apache 2.4, PHP-CGI 5.4 (FastCGI), PHP memcached 2.2, Zend Opcache 7.0. +- `centos-7`, `2.1.0` [(centos-7/Dockerfile)](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-7/Dockerfile) +- `centos-6`, `1.12.0` [(centos-6/Dockerfile)](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-6/Dockerfile) -Apache PHP web server, loading only a minimal set of Apache modules by default. Supports custom configuration via environment variables. +## Overview -## Overview & links +Apache PHP (FastCGI) web server, loading only a minimal set of Apache modules by default. -- `centos-7`, `centos-7-2.1.0`, `2.1.0` [(centos-7/Dockerfile)](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-7/Dockerfile) -- `centos-6`, `centos-6-1.12.0`, `1.12.0` [(centos-6/Dockerfile)](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-6/Dockerfile) +This build uses the base image [jdeathe/centos-ssh](https://github.com/jdeathe/centos-ssh) so inherits it's features but with `sshd` disabled by default. [Supervisor](http://supervisord.org/) is used to start the Apache [`httpd`](https://httpd.apache.org/) daemon when a docker container based on this image is run. -#### centos-6 +### Image variants -The latest CentOS-6 based release can be pulled from the centos-6 Docker tag. It is recommended to select a specific release tag - the convention is `centos-6-1.12.0` or `1.12.0` for the [1.12.0](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/tree/1.12.0) release tag. +- [Apache 2.4, PHP-CLI 5.4 (FastCGI), PHP memcached 2.2, PHP redis 2.2, Zend Opcache 7.0 - CentOS-7](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-7) +- [Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP redis 2.2, PHP APC 3.1 - CentOS-6](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-6) -#### centos-7 +## Quick start -The latest CentOS-7 based release can be pulled from the centos-7 Docker tag. It is recommended to select a specific release tag - the convention is `centos-7-2.1.0` or `2.1.0` for the [2.1.0](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/tree/2.1.0) release tag. - -This build of [Apache](https://httpd.apache.org/), (httpd CentOS package), uses the [mod_fcgid](https://httpd.apache.org/mod_fcgid/) module to run [PHP](http://php.net/) as a [FastCGI](http://www.fastcgi.com/) process. - -Included in the build are the [SCL](https://www.softwarecollections.org/), [EPEL](http://fedoraproject.org/wiki/EPEL) and [IUS](https://ius.io) repositories. Installed packages include [OpenSSH](http://www.openssh.com/portable.html) secure shell, [vim-minimal](http://www.vim.org/), [elinks](http://elinks.or.cz) (for fullstatus support), PHP [APC](http://pecl.php.net/package/APC), PHP [Memcached](http://pecl.php.net/package/memcached) are installed along with python-setuptools, [supervisor](http://supervisord.org/) and [supervisor-stdout](https://github.com/coderanger/supervisor-stdout). - -Supervisor is used to start httpd.worker daemon when a docker container based on this image is run. To enable simple viewing of stdout for the service's subprocess, supervisor-stdout is included. This allows you to see output from the supervisord controlled subprocesses with `docker logs {docker-container-name}`. - -If enabling and configuring SSH access, it is by public key authentication and, by default, the [Vagrant](http://www.vagrantup.com/) [insecure private key](https://github.com/mitchellh/vagrant/blob/master/keys/vagrant) is required. - -### SSH Alternatives - -SSH is not required in order to access a terminal for the running container. The simplest method is to use the docker exec command to run bash (or sh) as follows: - -``` -$ docker exec -it {docker-name-or-id} bash -``` - -For cases where access to docker exec is not possible the preferred method is to use Command Keys and the nsenter command. See [command-keys.md](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-6/command-keys.md) for details on how to set this up. - -## Quick Example +> For production use, it is recommended to select a specific release tag as shown in the examples. Run up a container named `apache-php.1` from the docker image `jdeathe/centos-ssh-apache-php-fcgi` on port 8080 of your docker host. @@ -47,210 +25,85 @@ $ docker run -d \ --name apache-php.1 \ -p 8080:80 \ -e "APACHE_SERVER_NAME=app-1.local" \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 + jdeathe/centos-ssh-apache-php-fcgi:2.1.0 ``` -Now point your browser to `http://{docker-host}:8080` where `{docker-host}` is the host name of your docker server and, if all went well, you should see the "Hello, world!" page. +Go to `http://{{docker-host}}:8080` using a browser where `{{docker-host}}` is the host name of your docker server and, if all went well, you should see the "Hello, world!" page. + +![PHP "Hello, world!" - Chrome screenshot](https://raw.github.com/jdeathe/centos-ssh-apache-php-fcgi/centos-7/images/php-hello-world-chrome-fcgi.png) -![PHP "Hello, world!" - Chrome screenshot](https://raw.github.com/jdeathe/centos-ssh-apache-php-fcgi/centos-6/images/php-hello-world-chrome-fcgi.png) +To be able to access the server using the "app-1.local" domain name you need to add a hosts file entry locally; such that the IP address of the Docker host resolves to the name "app-1.local". Alternatively, you can use the `elinks` browser installed in the container. -To be able to access the server using the "app-1.local" domain name you need to add a hosts file entry locally; such that the IP address of the Docker host resolves to the name "app-1.local". Alternatively, you can use the elinks browser installed in the container. Note that because you are using the browser from the container you access the site over port 80. +> Note that because you are using the browser from the container you access the site over the standard port 80. ``` $ docker exec -it apache-php.1 \ elinks http://app-1.local ``` -![PHP "Hello, world!" - eLinks screenshot](https://raw.github.com/jdeathe/centos-ssh-apache-php-fcgi/centos-6/images/php-hello-world-elinks-fcgi.png) +![PHP "Hello, world!" - eLinks screenshot](https://raw.github.com/jdeathe/centos-ssh-apache-php-fcgi/centos-7/images/php-hello-world-elinks-fcgi.png) -To verify the container is initialised and running successfully by inspecting the container's logs. +Verify the named container's process status and health. + +``` +$ docker ps -a \ + -f "name=apache-php.1" +``` + +Verify successful initialisation of the named container. ``` $ docker logs apache-php.1 ``` -On first run, the bootstrap script, ([/usr/sbin/httpd-bootstrap](https://github.com/jdeathe/centos-ssh-apache-php/blob/centos-6/src/usr/sbin/httpd-bootstrap)), will check if the DocumentRoot directory is empty and, if so, will populate it with the example app scripts and VirtualHost configuration files. +On first run, if the DocumentRoot directory is empty, it will be populated with the example app scripts and app specific configuration files. The `apachectl` command can be accessed as follows. ``` $ docker exec -it apache-php.1 \ - bash -c "apachectl -h" + apachectl -h ``` ## Instructions ### Running -To run the a docker container from this image you can use the standard docker commands. Alternatively, you can use the embedded (Service Container Manager Interface) [scmi](https://github.com/jdeathe/centos-ssh/blob/centos-6/src/usr/sbin/scmi) that is included in the image since `centos-6-1.7.1` or, if you have a checkout of the [source repository](https://github.com/jdeathe/centos-ssh-apache-php-fcgi), and have make installed the Makefile provides targets to build, install, start, stop etc. where environment variables can be used to configure the container options and set custom docker run parameters. - -#### SCMI Installation Examples - -The following example uses docker to run the SCMI install command to create and start a container named `apache-php.1`. To use SCMI it requires the use of the `--privileged` docker run parameter and the docker host's root directory mounted as a volume with the container's mount directory also being set in the `scmi` `--chroot` option. The `--setopt` option is used to add extra parameters to the default docker run command template; in the following example a named configuration volume is added which allows the SSH host keys to persist after the first container initialisation. Not that the placeholder `{{NAME}}` can be used in this option and is replaced with the container's name. - -##### SCMI Install - -``` -$ docker run \ - --rm \ - --privileged \ - --volume /:/media/root \ - --env BASH_ENV="" \ - --env ENV="" \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 \ - /usr/sbin/scmi install \ - --chroot=/media/root \ - --tag=1.12.0 \ - --name=apache-php.1 -``` - -##### SCMI Uninstall - -To uninstall the previous example simply run the same docker run command with the scmi `uninstall` command. - -``` -$ docker run \ - --rm \ - --privileged \ - --volume /:/media/root \ - --env BASH_ENV="" \ - --env ENV="" \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 \ - /usr/sbin/scmi uninstall \ - --chroot=/media/root \ - --tag=1.12.0 \ - --name=apache-php.1 -``` - -##### SCMI Systemd Support - -If your docker host has systemd (and optionally etcd) installed then `scmi` provides a method to install the container as a systemd service unit. This provides some additional features for managing a group of instances on a single docker host and has the option to use an etcd backed service registry. Using a systemd unit file allows the System Administrator to use a Drop-In to override the settings of a unit-file template used to create service instances. To use the systemd method of installation use the `-m` or `--manager` option of `scmi` and to include the optional etcd register companion unit use the `--register` option. - -``` -$ docker run \ - --rm \ - --privileged \ - --volume /:/media/root \ - --env BASH_ENV="" \ - --env ENV="" \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 \ - /usr/sbin/scmi install \ - --chroot=/media/root \ - --tag=1.12.0 \ - --name=apache-php.1 \ - --manager=systemd \ - --register \ - --env='APACHE_MOD_SSL_ENABLED=true' \ - --setopt='--volume {{NAME}}.data-tls:/etc/pki/tls' -``` - -##### SCMI Fleet Support - -**_Deprecation Notice:_** The fleet project is no longer maintained. The fleet `--manager` option has been deprecated in `scmi`. - -If your docker host has systemd, fleetd (and optionally etcd) installed then `scmi` provides a method to schedule the container to run on the cluster. This provides some additional features for managing a group of instances on a [fleet](https://github.com/coreos/fleet) cluster and has the option to use an etcd backed service registry. To use the fleet method of installation use the `-m` or `--manager` option of `scmi` and to include the optional etcd register companion unit use the `--register` option. - -##### SCMI Image Information - -Since release `centos-6-1.7.1` the install template has been added to the image metadata. Using docker inspect you can access `scmi` to simplify install/uninstall tasks. - -To see detailed information about the image run `scmi` with the `--info` option. To see all available `scmi` options run with the `--help` option. - -``` -$ eval "sudo -E $( - docker inspect \ - -f "{{.ContainerConfig.Labels.install}}" \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 - ) --info" -``` - -To perform an installation using the docker name `apache-php.2` simply use the `--name` or `-n` option. - -``` -$ eval "sudo -E $( - docker inspect \ - -f "{{.ContainerConfig.Labels.install}}" \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 - ) --name=apache-php.2" -``` - -To uninstall use the *same command* that was used to install but with the `uninstall` Label. - -``` -$ eval "sudo -E $( - docker inspect \ - -f "{{.ContainerConfig.Labels.uninstall}}" \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 - ) --name=apache-php.2" -``` - -##### SCMI on Atomic Host +To run the a docker container from this image you can use the standard docker commands as shown in the example below. Alternatively, there's a [docker-compose](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-7/docker-compose.yml) example. -With the addition of install/uninstall image labels it is possible to use [Project Atomic's](http://www.projectatomic.io/) `atomic install` command to simplify install/uninstall tasks on [CentOS Atomic](https://wiki.centos.org/SpecialInterestGroup/Atomic) Hosts. +For production use, it is recommended to select a specific release tag as shown in the examples. -_NOTE:_ A prerequisite of the following examples is that the image has been pulled (or loaded from the release package). +#### Using environment variables ``` -$ docker pull jdeathe/centos-ssh-apache-php-fcgi:1.12.0 -``` - -To see detailed information about the image run `scmi` with the `--info` option. To see all available `scmi` options run with the `--help` option. - -``` -$ sudo -E atomic install \ - -n apache-php.3 \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 \ - --info -``` - -To perform an installation using the docker name `apache-php.3` simply use the `-n` option of the `atomic install` command. - -``` -$ sudo -E atomic install \ - -n apache-php.3 \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 -``` - -Alternatively, you could use the `scmi` options `--name` or `-n` for naming the container. - -``` -$ sudo -E atomic install \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 \ - --name apache-php.3 -``` - -To uninstall use the *same command* that was used to install but with the `uninstall` Label. - -``` -$ sudo -E atomic uninstall \ - -n apache-php.3 \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 +$ docker stop apache-php.1 && \ + docker rm apache-php.1; \ + docker run -d \ + --name apache-php.1 \ + --publish 8080:80 \ + --publish 9443:443 \ + --env "APACHE_CUSTOM_LOG_LOCATION=/dev/stdout" \ + --env "APACHE_ERROR_LOG_LOCATION=/dev/stderr" \ + --env "APACHE_EXTENDED_STATUS_ENABLED=true" \ + --env "APACHE_LOAD_MODULES=env_module rewrite_module" \ + --env "APACHE_MOD_SSL_ENABLED=true" \ + --env "APACHE_SERVER_NAME=app-1.local" \ + --env "APACHE_SSL_PROTOCOL=All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1" \ + --env "PHP_OPTIONS_DATE_TIMEZONE=Europe/London" \ + jdeathe/centos-ssh-apache-php-fcgi:2.1.0 ``` #### Environment Variables There are environmental variables available which allows the operator to customise the running container. -##### APACHE_AUTOSTART_HTTPD_BOOTSTRAP & APACHE_AUTOSTART_HTTPD_WRAPPER - -It may be desirable to prevent the startup of the httpd-bootstrap and/or httpd-wrapper scripts. For example, when using an image built from this Dockerfile as the source for another Dockerfile you could disable services from startup by setting `APACHE_AUTOSTART_HTTPD_WRAPPER` to `false`. The benefit of this is to reduce the number of running processes in the final container. Another use for this would be to make use of the packages installed in the image such as `ab`, `curl`, `elinks`, `php-cli` etc. +##### ENABLE_HTTPD_BOOTSTRAP, ENABLE_HTTPD_WRAPPER & ENABLE_PHP_FPM_WRAPPER -##### APACHE_SERVER_NAME & APACHE_SERVER_ALIAS - -The `APACHE_SERVER_NAME` and `APACHE_SERVER_ALIAS` environmental variables are used to set the VirtualHost `ServerName` and `ServerAlias` values respectively. If the value contains the placeholder `{{HOSTNAME}}` it will be replaced with the system `hostname` value; by default this is the container id but the hostname can be modified using the `--hostname` docker create|run parameter. - -In the following example the running container would respond to the host names `app-1.local` or `app-1`. - -``` -... - --env "APACHE_SERVER_ALIAS=app-1" \ - --env "APACHE_SERVER_NAME=app-1.local" \ -... -``` +It may be desirable to prevent the startup of the `httpd-bootstrap` and/or `httpd-wrapper` scripts. For example, when using an image built from this Dockerfile as the source for another Dockerfile you could disable services from startup by setting `ENABLE_HTTPD_WRAPPER` to `false`. The benefit of this is to reduce the number of running processes in the final container. Another use for this would be to make use of the packages installed in the image such as `ab`, `curl`, `elinks`, `php-cli` etc. ##### APACHE_CONTENT_ROOT -The home directory of the service user and parent directory of the Apache DocumentRoot is /var/www/app by default but can be changed if necessary using the `APACHE_CONTENT_ROOT` environment variable. +The home directory of the service user and parent directory of the Apache DocumentRoot is `/var/www/app` by default but can be changed if necessary using the `APACHE_CONTENT_ROOT` environment variable. ``` ... @@ -258,8 +111,6 @@ The home directory of the service user and parent directory of the Apache Docume ... ``` -from your browser you can then access it with `http://app-1.local:8080` assuming you have the IP address of your docker mapped to the hostname using your DNS server or a local hosts entry. - ##### APACHE_CUSTOM_LOG_LOCATION & APACHE_CUSTOM_LOG_FORMAT The Apache CustomLog can be defined using `APACHE_CUSTOM_LOG_LOCATION` to set a file, (or pipe), location and `APACHE_CUSTOM_LOG_FORMAT` to specify the required LogFormat nickname. @@ -304,17 +155,19 @@ The variable `APACHE_EXTENDED_STATUS_ENABLED` allows you to turn ExtendedStatus ``` ... - --env "APACHE_EXTENDED_STATUS_ENABLED=true" + --env "APACHE_EXTENDED_STATUS_ENABLED=true" \ ... ``` -You can view the output from Apache server-status either using the elinks browser from onboard the container or by using `watch` and `curl` to monitor status over time. The following command shows the server-status updated at a 1 second interval given an `APACHE_SERVER_NAME` or `APACHE_SERVER_ALIAS` of "app-1.local". +You can view the output from Apache server-status either using the `elinks` browser from onboard the container or by using `watch` and `curl` to monitor status over time. The following command shows the server-status updated at a 1 second interval given an `APACHE_SERVER_NAME` or `APACHE_SERVER_ALIAS` of "app-1.local". ``` $ docker exec -it apache-php.1 \ env TERM=xterm \ watch -n 1 \ - -d "curl -sH 'Host: app-1.local' http://127.0.0.1/server-status?auto" + -d "curl -s \ + -H 'Host: app-1.local' \ + http://127.0.0.1/server-status?auto" ``` ##### APACHE_HEADER_X_SERVICE_UID @@ -329,8 +182,7 @@ The `APACHE_HEADER_X_SERVICE_UID` environmental variable is used to set a respon ##### APACHE_LOAD_MODULES -By default, the image loads a minimal set of required Apache modules. To load additional modules the -`APACHE_LOAD_MODULES` can be used. To load both the `mod_env` and `mod_rewrite` Apache Modules use the respective module identifiers. i.e. `env_module` and `rewrite_module`. +By default, the image loads a minimal set of required Apache modules. To load additional modules the `APACHE_LOAD_MODULES` can be used. To load both the `mod_env` and `mod_rewrite` Apache Modules use the respective module identifiers. i.e. `env_module` and `rewrite_module`. ``` ... @@ -344,16 +196,15 @@ By default SSL support is disabled but a second port, (mapped to 8443), is avail ``` $ docker stop apache-php.1 && \ - docker rm apache-php.1 -$ docker run -d \ + docker rm apache-php.1; \ + docker run -d \ --name apache-php.1 \ --publish 8080:80 \ --publish 9443:443 \ --env "APACHE_SERVER_ALIAS=app-1" \ --env "APACHE_SERVER_NAME=app-1.local" \ --env "APACHE_MOD_SSL_ENABLED=true" \ - --volume apache-php.1.data-tls:/etc/pki/tls \ - jdeathe/centos-ssh-apache-php-fcgi:1.12.0 + jdeathe/centos-ssh-apache-php-fcgi:2.1.0 ``` ##### APACHE_MPM @@ -387,6 +238,19 @@ The public directory is relative to the `APACHE_CONTENT_ROOT` and together they ... ``` +##### APACHE_SERVER_ALIAS & APACHE_SERVER_NAME + +The `APACHE_SERVER_NAME` and `APACHE_SERVER_ALIAS` environmental variables are used to set the VirtualHost `ServerName` and `ServerAlias` values respectively. If the value contains the placeholder `{{HOSTNAME}}` it will be replaced with the system `hostname` value; by default this is the container id but the hostname can be modified using the `--hostname` docker create|run parameter. + +In the following example the running container would respond to the host names `app-1.local` or `app-1`. + +``` +... + --env "APACHE_SERVER_ALIAS=app-1" \ + --env "APACHE_SERVER_NAME=app-1.local" \ +... +``` + ##### APACHE_SSL_CERTIFICATE The `APACHE_SSL_CERTIFICATE` environment variable is used to define a PEM encoded certificate bundle. To make a compatible certificate bundle use the `cat` command to combine the certificate files together. @@ -400,7 +264,7 @@ $ cat /usr/share/private/server-key.pem \ Base64 encoding of the PEM file contents is recommended if not using the file path method. -*Note:* The `base64` command on Mac OSX will encode a file without line breaks by default but if using the command on Linux you need to include use the `-w` option to prevent wrapping lines at 80 characters. i.e. `base64 -w 0 -i {certificate-path}`. +> *Note:* The `base64` command on Mac OSX will encode a file without line breaks by default but if using the command on Linux you need to include use the `-w` option to prevent wrapping lines at 80 characters. i.e. `base64 -w 0 -i {{certificate-path}}`. ``` ... @@ -426,7 +290,7 @@ References: - [OpenSSL ciphers documentation](https://www.openssl.org/docs/manmaster/man1/ciphers.html). - [Mozilla Security/Server Side TLS guidance](https://wiki.mozilla.org/Security/Server_Side_TLS). -*Note:* The value show is using space separated values to allow for readablity in the documentation; this is valid syntax however using the colon separator is the recommended form. +> *Note:* The value show is using space separated values to allow for readablity in the documentation; this is valid syntax however using the colon separator is the recommended form. ``` ... @@ -473,15 +337,15 @@ To set the timezone for the UK and account for British Summer Time you would use ##### PHP_OPTIONS_SESSION_NAME, PHP_OPTIONS_SESSION_SAVE_HANDLER & PHP_OPTIONS_SESSION_SAVE_PATH -Using `PHP_OPTIONS_SESSION_SAVE_HANDLER` and `PHP_OPTIONS_SESSION_SAVE_PATH` together it's possible to configure PHP to use an alternative `session.save_handler` and `session.save_path`. For example if you have a Memcached server running on the host `memcached-server` on the default port `11211` the following configuration will allow session data to be stored in Memcached, allowing session data to be shared between multiple PHP containers. +Using `PHP_OPTIONS_SESSION_SAVE_HANDLER` and `PHP_OPTIONS_SESSION_SAVE_PATH` together it's possible to configure PHP to use an alternative `session.save_handler` and `session.save_path`. For example if you have a Redis server running on the host `redis-server` on the default port `6379` the following configuration will allow session data to be stored in Redis, allowing session data to be shared between multiple PHP containers. Using `PHP_OPTIONS_SESSION_NAME` a session name can be defined - otherwise the default name "PHPSESSID" is used. ``` ... - --env "PHP_OPTIONS_SESSION_NAME=app-session" \ - --env "PHP_OPTIONS_SESSION_SAVE_HANDLER=memcached" \ - --env "PHP_OPTIONS_SESSION_SAVE_PATH=memcached-server:11211" \ + --env "PHP_OPTIONS_SESSION_NAME=APPSESSID" \ + --env "PHP_OPTIONS_SESSION_SAVE_HANDLER=redis" \ + --env "PHP_OPTIONS_SESSION_SAVE_PATH=redis-server:6379" \ ... ``` diff --git a/command-keys.md b/command-keys.md deleted file mode 100644 index 098f7fa..0000000 --- a/command-keys.md +++ /dev/null @@ -1,67 +0,0 @@ -# Command Keys - -Using command keys to access containers (without sshd). - -Access docker containers using docker host SSH public key authentication and nsenter command to start up a bash terminal inside a container. In the following example the container name is "apache-php.app-1.1.1" - -## Create a unique public/private key pair for each container - -``` -$ cd ~/.ssh/ && ssh-keygen -q -t rsa -f id-rsa.apache-php.app-1.1.1 -``` - -## Prefix the public key with the nsenter command - -``` -$ sed -i '' \ - '1s#^#command="sudo nsenter -m -u -i -n -p -t $(docker inspect --format \\\"{{ .State.Pid }}\\\" apache-php.app-1.1.1) /bin/bash" #' \ - ~/.ssh/id-rsa.apache-php.app-1.1.1.pub -``` - -## Upload the public key to the docker host VM - -The host in this example is core-01.local that has SSH public key authentication enabled using the Vagrant insecure private key. - -### Generic Linux Host Example - -``` -$ cat ~/.ssh/id-rsa.apache-php.app-1.1.1.pub | ssh -i ~/.vagrant.d/insecure_private_key \ - core@core-01.local \ - "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" -``` - -### CoreOS Host Example - -``` -$ cat ~/.ssh/id-rsa.apache-php.app-1.1.1.pub | ssh -i ~/.vagrant.d/insecure_private_key \ - core@core-01.local \ - update-ssh-keys -a core@apache-php.app-1.1.1 -``` - -### Usage - -``` -$ ssh -i ~/.ssh/id-rsa.apache-php.app-1.1.1 \ - core@core-01.local \ - -o StrictHostKeyChecking=no -``` - -#### SSH Config - -To simplify the command required to access the running container we can add an entry to the SSH configuration file ```~/.ssh/config``` as follows: - -``` -Host core-01.apache-php.app-1.1.1 - HostName core-01.local - Port 22 - User core - StrictHostKeyChecking no - IdentitiesOnly yes - IdentityFile ~/.ssh/id-rsa.apache-php.app-1.1.1 -``` - -With the above entry in place we can now run the following to access the running container: - -``` -$ ssh core-01.apache-php.app-1.1.1 -``` From f559aeb1d7986ec190164cb5e46b5d694f5a1da1 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 16:04:35 +0100 Subject: [PATCH 06/11] #188: Fixes typo in README; PHP-CLI -> PHP-CGI. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index df7c83d..9c31ffc 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This build uses the base image [jdeathe/centos-ssh](https://github.com/jdeathe/c ### Image variants -- [Apache 2.4, PHP-CLI 5.4 (FastCGI), PHP memcached 2.2, PHP redis 2.2, Zend Opcache 7.0 - CentOS-7](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-7) +- [Apache 2.4, PHP-CGI 5.4 (FastCGI), PHP memcached 2.2, PHP redis 2.2, Zend Opcache 7.0 - CentOS-7](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-7) - [Apache 2.2, PHP-CGI 5.3 (FastCGI), PHP memcached 1.0, PHP redis 2.2, PHP APC 3.1 - CentOS-6](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-6) ## Quick start From 2ac473e55750c75f41b99d9fc35245b76c2368e7 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 16:48:56 +0100 Subject: [PATCH 07/11] #187: Updates image source to 1.13.0. --- CHANGELOG.md | 1 + Dockerfile | 14 +- Makefile | 287 ++- default.mk | 7 +- docker-compose.yml | 6 +- environment.mk | 24 +- .../centos-ssh-apache-php-fcgi@.service | 9 +- src/opt/scmi/environment.sh | 27 +- src/usr/sbin/httpd-bootstrap | 2006 ----------------- test/shpec/operation_shpec.sh | 59 +- 10 files changed, 237 insertions(+), 2203 deletions(-) delete mode 100755 src/usr/sbin/httpd-bootstrap diff --git a/CHANGELOG.md b/CHANGELOG.md index c5ecbbf..9bf3b52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Summary of release changes. ### 1.13.0 - Unreleased +- Updates image source to [1.13.0](https://github.com/jdeathe/centos-ssh-apache-php/releases/tag/1.13.0). - Updates description in `centos-ssh-apache-php-fcgi.register@.service`. - Updates CHANGELOG.md to simplify maintenance. - Updates README.md to simplify contents and improve readability. diff --git a/Dockerfile b/Dockerfile index 2676307..1f30ada 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,11 @@ -FROM jdeathe/centos-ssh-apache-php:1.12.0 +FROM jdeathe/centos-ssh-apache-php:1.13.0 ARG RELEASE_VERSION="1.12.0" # ------------------------------------------------------------------------------ -# - Base install of required packages +# Base install of required packages # ------------------------------------------------------------------------------ -RUN rpm --rebuilddb \ - && yum -y erase \ +RUN yum -y erase \ php-5.3.3-49.el6 \ && yum -y install \ --setopt=tsflags=nodocs \ @@ -37,9 +36,7 @@ RUN cat \ /etc/httpd/conf.d/fcgid.conf \ && sed -i \ -e "s~{{RELEASE_VERSION}}~${RELEASE_VERSION}~g" \ - /etc/systemd/system/centos-ssh-apache-php-fcgi@.service \ - && chmod 700 \ - /usr/{bin/healthcheck,sbin/httpd-{bootstrap,wrapper}} + /etc/systemd/system/centos-ssh-apache-php-fcgi@.service # ------------------------------------------------------------------------------ # Package installation @@ -54,7 +51,8 @@ RUN sed -i \ # ------------------------------------------------------------------------------ # Set default environment variables used to configure the service container # ------------------------------------------------------------------------------ -ENV APACHE_MPM="worker" +ENV \ + APACHE_MPM="worker" # ------------------------------------------------------------------------------ # Set image metadata diff --git a/Makefile b/Makefile index 5ebb343..6416f1b 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ Targets: distclean Clean up distribution artifacts. exec COMMAND [ARG...] Run command in a the running container. help Show this help. + inspect [-f \"FORMAT\"] Return low-level information on the container. install Terminate running container and run the docker create template. images Show container's image details. @@ -32,14 +33,19 @@ Targets: pull Pull the release image from the registry. Requires the DOCKER_IMAGE_TAG variable. ps Display the details of the container process. + reload Send SIGHUP to the PID 1 container process. restart Restarts the container. rm Force remove the container. + rm-exited Force remove all containers in the exited state. rmi Untag (remove) the image. + rmi-dangling Untag (remove) images not referenced by any + container. run Execute the run container template. start Start the container in the created state. stop Stop the container when in a running state. terminate Unpause, stop and remove the container. test Run all test cases. + top [ps OPTIONS] Display the running processes of the container. unpause Unpause the container when in a paused state. Variables: @@ -60,6 +66,8 @@ Variables: artifacts are placed. - NO_CACHE When true, no cache will be used while running the build target. + - RELOAD_SIGNAL Default signal is SIGHUP. Use to set an alternative + signal value. - STARTUP_TIME Defines the number of seconds expected to complete the startup process, including the bootstrap where applicable. @@ -69,7 +77,7 @@ endef include environment.mk include default.mk -# UI constants +.DEFAULT_GOAL := build COLOUR_NEGATIVE := \033[1;31m COLOUR_POSITIVE := \033[1;32m COLOUR_RESET := \033[0m @@ -106,25 +114,22 @@ PREFIX_SUB_STEP_POSITIVE := $(shell \ "$(PREFIX_SUB_STEP)" \ "$(COLOUR_RESET)"; \ ) - -.DEFAULT_GOAL := build - -# Package prerequisites docker := $(shell \ command -v docker \ ) -xz := $(shell \ - command -v xz \ +docker-status := $(shell \ + if ! docker version > /dev/null; \ + then \ + printf -- 'ERROR'; \ + else \ + printf -- 'OK'; \ + fi \ ) - -# Testing prerequisites shpec := $(shell \ command -v shpec \ ) - -# Used to test docker host is accessible -get-docker-info := $(shell \ - $(docker) info \ +xz := $(shell \ + command -v xz \ ) define get-docker-image-id @@ -166,6 +171,7 @@ endef distclean \ exec \ help \ + inspect \ install \ images \ load \ @@ -174,14 +180,18 @@ endef pause \ pull \ ps \ + reload \ restart \ rm \ + rm-exited \ rmi \ + rmi-dangling \ run \ start \ stop \ terminate \ test \ + top \ unpause _prerequisites: @@ -193,38 +203,34 @@ ifeq ($(xz),) $(error "Please install the xz package.") endif -ifeq ($(get-docker-info),) - $(error "Unable to connect to docker host.") +ifneq ($(docker-status),OK) + $(error "Docker server host error.") endif _require-docker-container: @ if [[ -z $$($(docker) ps -aq --filter "name=$(DOCKER_NAME)") ]]; \ then \ - printf -- '%sThis operation requires the %s container.\n' \ + >&2 printf -- '%sThis operation requires the %s container.\n' \ "$(PREFIX_STEP_NEGATIVE)" \ - "$(DOCKER_NAME)" \ - >&2; \ - printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ + "$(DOCKER_NAME)"; \ + >&2 printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ "$(PREFIX_SUB_STEP)" \ "$(DOCKER_NAME)" \ - "install" \ - >&2; \ + "install"; \ exit 1; \ fi _require-docker-container-not: @ if [[ -n $$($(docker) ps -aq --filter "name=$(DOCKER_NAME)") ]]; \ then \ - printf -- '%sThis operation requires the %s container %s.\n' \ + >&2 printf -- '%sThis operation requires the %s container %s.\n' \ "$(PREFIX_STEP_NEGATIVE)" \ "$(DOCKER_NAME)" \ - "be removed or renamed" \ - >&2; \ - printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ + "be removed or renamed"; \ + >&2 printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ "$(PREFIX_SUB_STEP)" \ "$(DOCKER_NAME)" \ - "rm" \ - >&2; \ + "rm"; \ exit 1; \ fi @@ -234,16 +240,14 @@ _require-docker-container-not-status-paused: --filter "status=paused" \ ) ]]; \ then \ - printf -- '%sThis operation requires the %s container %s.\n' \ + >&2 printf -- '%sThis operation requires the %s container %s.\n' \ "$(PREFIX_STEP_NEGATIVE)" \ "$(DOCKER_NAME)" \ - "to be unpaused" \ - >&2; \ - printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ + "to be unpaused"; \ + >&2 printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ "$(PREFIX_SUB_STEP)" \ "$(DOCKER_NAME)" \ - "unpause" \ - >&2; \ + "unpause"; \ exit 1; \ fi @@ -253,16 +257,14 @@ _require-docker-container-status-created: --filter "status=created" \ ) ]]; \ then \ - printf -- '%sThis operation requires the %s container %s.\n' \ + >&2 printf -- '%sThis operation requires the %s container %s.\n' \ "$(PREFIX_STEP_NEGATIVE)" \ "$(DOCKER_NAME)" \ - "to be created" \ - >&2; \ - printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ + "to be created"; \ + >&2 printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ "$(PREFIX_SUB_STEP)" \ "$(DOCKER_NAME)" \ - "install" \ - >&2; \ + "install"; \ exit 1; \ fi @@ -272,16 +274,14 @@ _require-docker-container-status-exited: --filter "status=exited" \ ) ]]; \ then \ - printf -- '%sThis operation requires the %s container %s.\n' \ + >&2 printf -- '%sThis operation requires the %s container %s.\n' \ "$(PREFIX_STEP_NEGATIVE)" \ "$(DOCKER_NAME)" \ - "to be exited" \ - >&2; \ - printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ + "to be exited"; \ + >&2 printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ "$(PREFIX_SUB_STEP)" \ "$(DOCKER_NAME)" \ - "stop" \ - >&2; \ + "stop"; \ exit 1; \ fi @@ -291,16 +291,14 @@ _require-docker-container-status-paused: --filter "status=paused" \ ) ]]; \ then \ - printf -- '%sThis operation requires the %s container %s.\n' \ + >&2 printf -- '%sThis operation requires the %s container %s.\n' \ "$(PREFIX_STEP_NEGATIVE)" \ "$(DOCKER_NAME)" \ - "to be paused" \ - >&2; \ - printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ + "to be paused"; \ + >&2 printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ "$(PREFIX_SUB_STEP)" \ "$(DOCKER_NAME)" \ - "pause" \ - >&2; \ + "pause"; \ exit 1; \ fi @@ -310,42 +308,37 @@ _require-docker-container-status-running: --filter "status=running" \ ) ]]; \ then \ - printf -- '%sThis operation requires the %s container %s.\n' \ + >&2 printf -- '%sThis operation requires the %s container %s.\n' \ "$(PREFIX_STEP_NEGATIVE)" \ "$(DOCKER_NAME)" \ - "to be running" \ - >&2; \ - printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ + "to be running"; \ + >&2 printf -- '%sTry: DOCKER_NAME=%s make %s\n' \ "$(PREFIX_SUB_STEP)" \ "$(DOCKER_NAME)" \ - "start" \ - >&2; \ + "start"; \ exit 1; \ fi _require-docker-image-tag: @ if ! [[ "$(DOCKER_IMAGE_TAG)" =~ $(DOCKER_IMAGE_TAG_PATTERN) ]]; \ then \ - printf -- '%sInvalid %s value: %s\n' \ + >&2 printf -- '%sInvalid %s value: %s\n' \ "$(PREFIX_STEP_NEGATIVE)" \ "DOCKER_IMAGE_TAG" \ - "$(DOCKER_IMAGE_TAG)" \ - >&2; \ + "$(DOCKER_IMAGE_TAG)"; \ exit 1; \ fi _require-docker-release-tag: @ if ! [[ "$(DOCKER_IMAGE_TAG)" =~ $(DOCKER_IMAGE_RELEASE_TAG_PATTERN) ]]; \ then \ - printf -- '%sInvalid %s value: %s\n' \ + >&2 printf -- '%sInvalid %s value: %s\n' \ "$(PREFIX_STEP_NEGATIVE)" \ "DOCKER_IMAGE_TAG" \ - "$(DOCKER_IMAGE_TAG)" \ - >&2; \ - printf -- '%s%s\n' \ + "$(DOCKER_IMAGE_TAG)"; \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP)" \ - "A release tag is required for this operation." \ - >&2; \ + "A release tag is required for this operation."; \ exit 1; \ fi @@ -359,18 +352,16 @@ _require-package-path: fi; \ if [[ ! $${?} -eq 0 ]]; \ then \ - printf -- '%s%s: %s\n' \ + >&2 printf -- '%s%s: %s\n' \ "$(PREFIX_STEP_NEGATIVE)" \ "Failed to make package path" \ - "$(DIST_PATH)" \ - >&2; \ + "$(DIST_PATH)"; \ exit 1; \ elif [[ -z $(DIST_PATH) ]]; \ then \ - printf -- '%sUndefined %s\n' \ + >&2 printf -- '%sUndefined %s\n' \ "$(PREFIX_STEP_NEGATIVE)" \ - "DIST_PATH" \ - >&2; \ + "DIST_PATH"; \ exit 1; \ fi @@ -415,10 +406,9 @@ build: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Build complete"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Build error" \ - >&2; \ + "Build error"; \ exit 1; \ fi @@ -426,7 +416,9 @@ clean: \ _prerequisites \ | \ terminate \ - rmi + rm-exited \ + rmi \ + rmi-dangling create: \ _prerequisites \ @@ -456,10 +448,9 @@ create: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Container created"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Container creation failed" \ - >&2; \ + "Container creation failed"; \ exit 1; \ fi @@ -506,10 +497,9 @@ dist: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Package saved"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Package save error" \ - >&2; \ + "Package save error"; \ exit 1; \ fi; \ fi @@ -547,10 +537,9 @@ distclean: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Package cleanup complete"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Package cleanup failed" \ - >&2; \ + "Package cleanup failed"; \ exit 1; \ fi; \ else \ @@ -560,7 +549,9 @@ distclean: \ fi exec: \ - _prerequisites + _prerequisites \ + _require-docker-container \ + _require-docker-container-status-running @ $(docker) exec -it $(DOCKER_NAME) $(filter-out $@, $(MAKECMDGOALS)) %:; @: @@ -572,17 +563,29 @@ images: \ help: \ _usage +inspect: \ + _prerequisites \ + _require-docker-container \ + _require-docker-container-status-running + @ $(docker) inspect \ + --type=container \ + $(filter-out $@, $(MAKECMDGOALS)) \ + $(DOCKER_NAME) +%:; @: + install: | \ _prerequisites \ terminate \ create logs: \ - _prerequisites + _prerequisites \ + _require-docker-container @ $(docker) logs $(DOCKER_NAME) logs-delayed: \ - _prerequisites + _prerequisites \ + _require-docker-container @ sleep $(STARTUP_TIME) @ $(MAKE) logs @@ -608,15 +611,13 @@ load: \ "$(DOCKER_IMAGE_TAG)"; \ if [[ ! -s $($@_dist_path)/$($@_dist_file) ]]; \ then \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Package not found" \ - >&2; \ - printf -- '%sTry: DOCKER_IMAGE_TAG=%s make %s\n' \ + "Package not found"; \ + >&2 printf -- '%sTry: DOCKER_IMAGE_TAG=%s make %s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ "$(DOCKER_IMAGE_TAG)" \ - "dist" \ - >&2; \ + "dist"; \ exit 1; \ else \ $(xz) -dc \ @@ -632,6 +633,7 @@ load: \ pause: \ _prerequisites \ + _require-docker-container \ _require-docker-container-status-running @ printf -- '%s%s\n' \ "$(PREFIX_STEP)" \ @@ -660,10 +662,9 @@ pull: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Image pulled"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Error pulling image" \ - >&2; \ + "Error pulling image"; \ exit 1; \ fi @@ -673,6 +674,19 @@ ps: \ @ $(docker) ps -as \ --filter "name=$(DOCKER_NAME)" +reload: \ + _prerequisites \ + _require-docker-container \ + _require-docker-container-status-running + @ printf -- '%s%s\n' \ + "$(PREFIX_STEP)" \ + "Reloading container" + @ $(docker) exec $(DOCKER_NAME) \ + kill -$(RELOAD_SIGNAL) 1 + @ printf -- '%s%s\n' \ + "$(PREFIX_SUB_STEP_POSITIVE)" \ + "Container reloaded" + restart: \ _prerequisites \ _require-docker-container \ @@ -710,14 +724,33 @@ rm: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Container removed"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Container removal failed" \ - >&2; \ + "Container removal failed"; \ exit 1; \ fi; \ fi +rm-exited: \ + _prerequisites + @ if [[ -z $$($(docker) ps -aq \ + --filter "status=exited" \ + ) ]]; \ + then \ + printf -- '%s%s\n' \ + "$(PREFIX_STEP)" \ + "Exited containers removal skipped"; \ + else \ + printf -- '%s%s\n' \ + "$(PREFIX_STEP)" \ + "Removing exited containers"; \ + $(docker) rm -f \ + $$($(docker) ps -aq \ + --filter "status=exited" \ + ) \ + 1> /dev/null; \ + fi + rmi: \ _prerequisites \ _require-docker-image-tag \ @@ -742,10 +775,9 @@ rmi: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Image untagged"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Error untagging image" \ - >&2; \ + "Error untagging image"; \ exit 1; \ fi; \ else \ @@ -754,6 +786,26 @@ rmi: \ "Untagging image skipped"; \ fi +rmi-dangling: \ + _prerequisites + @ if [[ -z $$($(docker) images -q \ + --filter "dangling=true" \ + ) ]]; \ + then \ + printf -- '%s%s\n' \ + "$(PREFIX_STEP)" \ + "Untagging dangling images skipped"; \ + else \ + printf -- '%s%s\n' \ + "$(PREFIX_STEP)" \ + "Untagging dangling images"; \ + $(docker) rmi \ + $$($(docker) images -q \ + --filter "dangling=true" \ + ) \ + 1> /dev/null; \ + fi + run: \ _prerequisites \ _require-docker-image-tag @@ -783,10 +835,9 @@ run: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Container running"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Container run failed" \ - >&2; \ + "Container run failed"; \ exit 1; \ fi @@ -816,15 +867,15 @@ start: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Container started"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Container start failed" \ - >&2; \ + "Container start failed"; \ exit 1; \ fi stop: \ _prerequisites \ + _require-docker-container \ _require-docker-container-not-status-paused \ _require-docker-container-status-running @ printf -- '%s%s\n' \ @@ -847,14 +898,20 @@ stop: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Container stopped"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Error stopping container" \ - >&2; \ + "Error stopping container"; \ exit 1; \ fi; \ fi +top: \ + _prerequisites \ + _require-docker-container \ + _require-docker-container-status-running + @ $(docker) top $(DOCKER_NAME) $(filter-out $@, $(MAKECMDGOALS)) +%:; @: + terminate: \ _prerequisites @ if [[ -z $$($(docker) ps -aq --filter "name=$(DOCKER_NAME)") ]]; \ @@ -905,10 +962,9 @@ terminate: \ "$(PREFIX_SUB_STEP_POSITIVE)" \ "Container terminated"; \ else \ - printf -- '%s%s\n' \ + >&2 printf -- '%s%s\n' \ "$(PREFIX_SUB_STEP_NEGATIVE)" \ - "Container termination failed" \ - >&2; \ + "Container termination failed"; \ exit 1; \ fi; \ fi @@ -926,6 +982,7 @@ test: \ unpause: \ _prerequisites \ + _require-docker-container \ _require-docker-container-status-paused @ printf -- '%s%s\n' \ "$(PREFIX_STEP)" \ diff --git a/default.mk b/default.mk index 7677721..5dca73a 100644 --- a/default.mk +++ b/default.mk @@ -110,8 +110,6 @@ DOCKER_PUBLISH := $(shell \ define DOCKER_CONTAINER_PARAMETERS --name $(DOCKER_NAME) \ --restart $(DOCKER_RESTART_POLICY) \ ---env "APACHE_AUTOSTART_HTTPD_BOOTSTRAP=$(APACHE_AUTOSTART_HTTPD_BOOTSTRAP)" \ ---env "APACHE_AUTOSTART_HTTPD_WRAPPER=$(APACHE_AUTOSTART_HTTPD_WRAPPER)" \ --env "APACHE_CONTENT_ROOT=$(APACHE_CONTENT_ROOT)" \ --env "APACHE_CUSTOM_LOG_FORMAT=$(APACHE_CUSTOM_LOG_FORMAT)" \ --env "APACHE_CUSTOM_LOG_LOCATION=$(APACHE_CUSTOM_LOG_LOCATION)" \ @@ -132,8 +130,11 @@ define DOCKER_CONTAINER_PARAMETERS --env "APACHE_SSL_CIPHER_SUITE=$(APACHE_SSL_CIPHER_SUITE)" \ --env "APACHE_SSL_PROTOCOL=$(APACHE_SSL_PROTOCOL)" \ --env "APACHE_SYSTEM_USER=$(APACHE_SYSTEM_USER)" \ +--env "ENABLE_HTTPD_BOOTSTRAP=$(ENABLE_HTTPD_BOOTSTRAP)" \ +--env "ENABLE_HTTPD_WRAPPER=$(ENABLE_HTTPD_WRAPPER)" \ --env "PHP_OPTIONS_DATE_TIMEZONE=$(PHP_OPTIONS_DATE_TIMEZONE)" \ --env "PHP_OPTIONS_SESSION_NAME=$(PHP_OPTIONS_SESSION_NAME)" \ --env "PHP_OPTIONS_SESSION_SAVE_HANDLER=$(PHP_OPTIONS_SESSION_SAVE_HANDLER)" \ ---env "PHP_OPTIONS_SESSION_SAVE_PATH=$(PHP_OPTIONS_SESSION_SAVE_PATH)" +--env "PHP_OPTIONS_SESSION_SAVE_PATH=$(PHP_OPTIONS_SESSION_SAVE_PATH)" \ +--env "SYSTEM_TIMEZONE=$(SYSTEM_TIMEZONE)" endef diff --git a/docker-compose.yml b/docker-compose.yml index f3e3d01..72a07ad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,9 +13,9 @@ # docker-compose logs apache-php # # Usage: -# docker-compose exec apache-php bash -c "apachectl -V" -# docker-compose exec apache-php bash -c "apachectl -M" -# docker-compose exec apache-php bash -c "apachectl -S" +# docker-compose exec apache-php apachectl -V +# docker-compose exec apache-php apachectl -M +# docker-compose exec apache-php apachectl -S # docker-compose exec apache-php elinks http://localhost # ------------------------------------------------------------------------------ version: "3.0" diff --git a/environment.mk b/environment.mk index a4131b9..a759a40 100644 --- a/environment.mk +++ b/environment.mk @@ -1,19 +1,16 @@ # ------------------------------------------------------------------------------ # Constants # ------------------------------------------------------------------------------ -DOCKER_USER := jdeathe DOCKER_IMAGE_NAME := centos-ssh-apache-php-fcgi +DOCKER_IMAGE_RELEASE_TAG_PATTERN := ^[1-2]\.[0-9]+\.[0-9]+$ +DOCKER_IMAGE_TAG_PATTERN := ^(latest|[1-2]\.[0-9]+\.[0-9]+)$ +DOCKER_USER := jdeathe SHPEC_ROOT := test/shpec -# Tag validation patterns -DOCKER_IMAGE_TAG_PATTERN := ^(latest|centos-6|((1|centos-6-1)\.[0-9]+\.[0-9]+))$ -DOCKER_IMAGE_RELEASE_TAG_PATTERN := ^(1|centos-6-1)\.[0-9]+\.[0-9]+$ - # ------------------------------------------------------------------------------ # Variables # ------------------------------------------------------------------------------ - -# Docker image/container settings +DIST_PATH ?= ./dist DOCKER_CONTAINER_OPTS ?= DOCKER_IMAGE_TAG ?= latest DOCKER_NAME ?= apache-php.1 @@ -21,21 +18,15 @@ DOCKER_PORT_MAP_TCP_80 ?= 8080 DOCKER_PORT_MAP_TCP_443 ?= 9443 DOCKER_PORT_MAP_TCP_8443 ?= NULL DOCKER_RESTART_POLICY ?= always - -# Docker build --no-cache parameter NO_CACHE ?= false - -# Directory path for release packages -DIST_PATH ?= ./dist - -# Number of seconds expected to complete container startup including bootstrap. +RELOAD_SIGNAL ?= HUP STARTUP_TIME ?= 2 # ------------------------------------------------------------------------------ # Application container configuration # ------------------------------------------------------------------------------ -APACHE_AUTOSTART_HTTPD_BOOTSTRAP ?= true -APACHE_AUTOSTART_HTTPD_WRAPPER ?= true +ENABLE_HTTPD_BOOTSTRAP ?= true +ENABLE_HTTPD_WRAPPER ?= true APACHE_CONTENT_ROOT ?= /var/www/app APACHE_CUSTOM_LOG_FORMAT ?= combined APACHE_CUSTOM_LOG_LOCATION ?= var/log/apache_access_log @@ -60,3 +51,4 @@ PHP_OPTIONS_DATE_TIMEZONE ?= UTC PHP_OPTIONS_SESSION_NAME ?= PHPSESSID PHP_OPTIONS_SESSION_SAVE_HANDLER ?= files PHP_OPTIONS_SESSION_SAVE_PATH ?= var/session +SYSTEM_TIMEZONE ?= UTC diff --git a/src/etc/systemd/system/centos-ssh-apache-php-fcgi@.service b/src/etc/systemd/system/centos-ssh-apache-php-fcgi@.service index 7988005..093911c 100644 --- a/src/etc/systemd/system/centos-ssh-apache-php-fcgi@.service +++ b/src/etc/systemd/system/centos-ssh-apache-php-fcgi@.service @@ -58,8 +58,6 @@ Environment="DOCKER_PORT_MAP_TCP_80=8080" Environment="DOCKER_PORT_MAP_TCP_443=9443" Environment="DOCKER_PORT_MAP_TCP_8443=NULL" Environment="DOCKER_USER=jdeathe" -Environment="APACHE_AUTOSTART_HTTPD_BOOTSTRAP=true" -Environment="APACHE_AUTOSTART_HTTPD_WRAPPER=true" Environment="APACHE_CONTENT_ROOT=/var/www/app" Environment="APACHE_CUSTOM_LOG_FORMAT=combined" Environment="APACHE_CUSTOM_LOG_LOCATION=var/log/apache_access_log" @@ -80,6 +78,8 @@ Environment="APACHE_SSL_CERTIFICATE=" Environment="APACHE_SSL_CIPHER_SUITE=ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS" Environment="APACHE_SSL_PROTOCOL=All -SSLv2 -SSLv3" Environment="APACHE_SYSTEM_USER=app" +Environment="ENABLE_HTTPD_BOOTSTRAP=true" +Environment="ENABLE_HTTPD_WRAPPER=true" Environment="PHP_OPTIONS_DATE_TIMEZONE=UTC" Environment="PHP_OPTIONS_SESSION_NAME=PHPSESSID" Environment="PHP_OPTIONS_SESSION_SAVE_HANDLER=files" @@ -140,8 +140,6 @@ ExecStartPre=-/bin/bash -c \ ExecStart=/bin/bash -c \ "exec /usr/bin/docker run \ --name %p.%i \ - --env \"APACHE_AUTOSTART_HTTPD_BOOTSTRAP=${APACHE_AUTOSTART_HTTPD_BOOTSTRAP}\" \ - --env \"APACHE_AUTOSTART_HTTPD_WRAPPER=${APACHE_AUTOSTART_HTTPD_WRAPPER}\" \ --env \"APACHE_CONTENT_ROOT=${APACHE_CONTENT_ROOT}\" \ --env \"APACHE_CUSTOM_LOG_FORMAT=${APACHE_CUSTOM_LOG_FORMAT}\" \ --env \"APACHE_CUSTOM_LOG_LOCATION=${APACHE_CUSTOM_LOG_LOCATION}\" \ @@ -162,10 +160,13 @@ ExecStart=/bin/bash -c \ --env \"APACHE_SSL_CIPHER_SUITE=${APACHE_SSL_CIPHER_SUITE}\" \ --env \"APACHE_SSL_PROTOCOL=${APACHE_SSL_PROTOCOL}\" \ --env \"APACHE_SYSTEM_USER=${APACHE_SYSTEM_USER}\" \ + --env \"ENABLE_HTTPD_BOOTSTRAP=${ENABLE_HTTPD_BOOTSTRAP}\" \ + --env \"ENABLE_HTTPD_WRAPPER=${ENABLE_HTTPD_WRAPPER}\" \ --env \"PHP_OPTIONS_DATE_TIMEZONE=${PHP_OPTIONS_DATE_TIMEZONE}\" \ --env \"PHP_OPTIONS_SESSION_NAME=${PHP_OPTIONS_SESSION_NAME}\" \ --env \"PHP_OPTIONS_SESSION_SAVE_HANDLER=${PHP_OPTIONS_SESSION_SAVE_HANDLER}\" \ --env \"PHP_OPTIONS_SESSION_SAVE_PATH=${PHP_OPTIONS_SESSION_SAVE_PATH}\" \ + --env \"SYSTEM_TIMEZONE=${SYSTEM_TIMEZONE}\" \ $(if [[ ${DOCKER_PORT_MAP_TCP_80} != NULL ]]; \ then \ if /bin/grep -qE \ diff --git a/src/opt/scmi/environment.sh b/src/opt/scmi/environment.sh index a4b4f27..44fbcb2 100644 --- a/src/opt/scmi/environment.sh +++ b/src/opt/scmi/environment.sh @@ -1,18 +1,15 @@ # ------------------------------------------------------------------------------ # Constants # ------------------------------------------------------------------------------ -readonly DOCKER_USER=jdeathe readonly DOCKER_IMAGE_NAME=centos-ssh-apache-php-fcgi - -# Tag validation patterns -readonly DOCKER_IMAGE_TAG_PATTERN='^(latest|centos-6|((1|centos-6-1)\.[0-9]+\.[0-9]+))$' readonly DOCKER_IMAGE_RELEASE_TAG_PATTERN='^(1|centos-6-1)\.[0-9]+\.[0-9]+$' +readonly DOCKER_IMAGE_TAG_PATTERN='^(latest|centos-6|((1|centos-6-1)\.[0-9]+\.[0-9]+))$' +readonly DOCKER_USER=jdeathe # ------------------------------------------------------------------------------ # Variables # ------------------------------------------------------------------------------ - -# Docker image/container settings +DIST_PATH="${DIST_PATH:-./dist}" DOCKER_CONTAINER_OPTS="${DOCKER_CONTAINER_OPTS:-}" DOCKER_IMAGE_TAG="${DOCKER_IMAGE_TAG:-latest}" DOCKER_NAME="${DOCKER_NAME:-apache-php.1}" @@ -20,26 +17,15 @@ DOCKER_PORT_MAP_TCP_80="${DOCKER_PORT_MAP_TCP_80:-8080}" DOCKER_PORT_MAP_TCP_443="${DOCKER_PORT_MAP_TCP_443:-9443}" DOCKER_PORT_MAP_TCP_8443="${DOCKER_PORT_MAP_TCP_8443:-NULL}" DOCKER_RESTART_POLICY="${DOCKER_RESTART_POLICY:-always}" - -# Docker build --no-cache parameter NO_CACHE="${NO_CACHE:-false}" - -# Directory path for release packages -DIST_PATH="${DIST_PATH:-./dist}" - -# Number of seconds expected to complete container startup including bootstrap. -STARTUP_TIME="${STARTUP_TIME:-2}" - -# ETCD register service settings REGISTER_ETCD_PARAMETERS="${REGISTER_ETCD_PARAMETERS:-}" REGISTER_TTL="${REGISTER_TTL:-60}" REGISTER_UPDATE_INTERVAL="${REGISTER_UPDATE_INTERVAL:-55}" +STARTUP_TIME="${STARTUP_TIME:-2}" # ------------------------------------------------------------------------------ # Application container configuration # ------------------------------------------------------------------------------ -APACHE_AUTOSTART_HTTPD_BOOTSTRAP="${APACHE_AUTOSTART_HTTPD_BOOTSTRAP:-true}" -APACHE_AUTOSTART_HTTPD_WRAPPER="${APACHE_AUTOSTART_HTTPD_WRAPPER:-true}" APACHE_CONTENT_ROOT="${APACHE_CONTENT_ROOT:-/var/www/app}" APACHE_CUSTOM_LOG_FORMAT="${APACHE_CUSTOM_LOG_FORMAT:-combined}" APACHE_CUSTOM_LOG_LOCATION="${APACHE_CUSTOM_LOG_LOCATION:-var/log/apache_access_log}" @@ -58,9 +44,12 @@ APACHE_SERVER_ALIAS="${APACHE_SERVER_ALIAS:-}" APACHE_SERVER_NAME="${APACHE_SERVER_NAME:-}" APACHE_SSL_CERTIFICATE="${APACHE_SSL_CERTIFICATE:-}" APACHE_SSL_CIPHER_SUITE="${APACHE_SSL_CIPHER_SUITE:-"ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS"}" -APACHE_SSL_PROTOCOL="${APACHE_SSL_PROTOCOL:-All -SSLv2 -SSLv3}" +APACHE_SSL_PROTOCOL="${APACHE_SSL_PROTOCOL:-"All -SSLv2 -SSLv3"}" APACHE_SYSTEM_USER="${APACHE_SYSTEM_USER:-app}" +ENABLE_HTTPD_BOOTSTRAP="${ENABLE_HTTPD_BOOTSTRAP:-true}" +ENABLE_HTTPD_WRAPPER="${ENABLE_HTTPD_WRAPPER:-true}" PHP_OPTIONS_DATE_TIMEZONE="${PHP_OPTIONS_DATE_TIMEZONE:-UTC}" PHP_OPTIONS_SESSION_NAME="${PHP_OPTIONS_SESSION_NAME:-PHPSESSID}" PHP_OPTIONS_SESSION_SAVE_HANDLER="${PHP_OPTIONS_SESSION_SAVE_HANDLER:-files}" PHP_OPTIONS_SESSION_SAVE_PATH="${PHP_OPTIONS_SESSION_SAVE_PATH:-var/session}" +SYSTEM_TIMEZONE="${SYSTEM_TIMEZONE:-UTC}" diff --git a/src/usr/sbin/httpd-bootstrap b/src/usr/sbin/httpd-bootstrap deleted file mode 100755 index fb4c267..0000000 --- a/src/usr/sbin/httpd-bootstrap +++ /dev/null @@ -1,2006 +0,0 @@ -#!/usr/bin/env bash - -set -e - -function __absolute_path () -{ - local -r directory_path="${1}" - - local value - - if [[ -n ${directory_path} ]] - then - value="$( - python -c "import os,sys; print os.path.abspath(sys.argv[1])" \ - "${directory_path}" - )" - fi - - printf -- '%s' "${value}" -} - -function __add_hosts_entry () -{ - local address="${1:-127.0.0.1}" - local hosts - local usage="Usage: ${0} ip_address hostname [hostname ...]" - - shift - if [[ "${#}" -eq 0 ]] - then - >&2 printf -- \ - '%s\n' \ - "${usage}" - exit 1 - fi - - while (( "${#}" )) - do - if [[ ${1} != localhost ]] \ - && [[ ${1} != 127.0.0.1 ]] \ - && [[ ${1} != "${address}" ]] - then - hosts+=" ${1}" - fi - shift - done - - printf -- \ - '%s\t%s\n' \ - "${address}" \ - "${hosts}" \ - >> /etc/hosts -} - -function __cleanup () -{ - local -r exit_code="${?}" - local -r lock_file="${1}" - local -r state_file="${2}" - - if [[ -e ${lock_file} ]] - then - rm -f "${lock_file}" - fi - - if [[ ${exit_code} -eq 0 ]] - then - touch "${state_file}" - fi - -} - -function __enable_apache_modules () -{ - local -r apache_version="$( - __get_apache_server_version - )" - - local config_file - local -a config_files=( - '00-base.conf' - '00-dav.conf' - '00-lua.conf' - '00-optional.conf' - '00-proxy.conf' - ) - local config_paths="/etc/httpd/conf/httpd.conf" - local identifier - local -a identifiers - local -a identifiers_default - local modules="${1:-"$( - __get_apache_load_modules - )"}" - local enabled - local sed_command - - if [[ ${apache_version} =~ ^2\.4\. ]] - then - # Default DSO Modules - identifiers_default=( - 'authz_core_module' - 'authz_user_module' - 'log_config_module' - 'expires_module' - 'deflate_module' - 'filter_module' - 'headers_module' - 'setenvif_module' - 'socache_shmcb_module' - 'mime_module' - 'status_module' - 'dir_module' - 'alias_module' - 'unixd_module' - 'version_module' - 'proxy_module' - 'proxy_fcgi_module' - ) - - # Available DSO Modules - identifiers=( - 'access_compat_module' - 'actions_module' - 'alias_module' - 'allowmethods_module' - 'auth_basic_module' - 'auth_digest_module' - 'authn_anon_module' - 'authn_core_module' - 'authn_dbd_module' - 'authn_dbm_module' - 'authn_file_module' - 'authn_socache_module' - 'authz_core_module' - 'authz_dbd_module' - 'authz_dbm_module' - 'authz_groupfile_module' - 'authz_host_module' - 'authz_owner_module' - 'authz_user_module' - 'autoindex_module' - 'cache_module' - 'cache_disk_module' - 'cache_socache_module' - 'data_module' - 'dbd_module' - 'deflate_module' - 'dir_module' - 'dumpio_module' - 'echo_module' - 'env_module' - 'expires_module' - 'ext_filter_module' - 'filter_module' - 'headers_module' - 'http2_module' - 'include_module' - 'info_module' - 'log_config_module' - 'logio_module' - 'macro_module' - 'mime_magic_module' - 'mime_module' - 'negotiation_module' - 'remoteip_module' - 'reqtimeout_module' - 'request_module' - 'rewrite_module' - 'setenvif_module' - 'slotmem_plain_module' - 'slotmem_shm_module' - 'socache_dbm_module' - 'socache_memcache_module' - 'socache_shmcb_module' - 'status_module' - 'substitute_module' - 'suexec_module' - 'unique_id_module' - 'unixd_module' - 'userdir_module' - 'version_module' - 'vhost_alias_module' - 'watchdog_module' - 'dav_module' - 'dav_fs_module' - 'dav_lock_module' - 'lua_module' - 'proxy_module' - 'lbmethod_bybusyness_module' - 'lbmethod_byrequests_module' - 'lbmethod_bytraffic_module' - 'lbmethod_heartbeat_module' - 'proxy_ajp_module' - 'proxy_balancer_module' - 'proxy_connect_module' - 'proxy_express_module' - 'proxy_fcgi_module' - 'proxy_fdpass_module' - 'proxy_ftp_module' - 'proxy_http_module' - 'proxy_hcheck_module' - 'proxy_scgi_module' - 'proxy_wstunnel_module' - ) - else - # Default DSO Modules - identifiers_default=( - 'authz_user_module' - 'log_config_module' - 'expires_module' - 'deflate_module' - 'headers_module' - 'setenvif_module' - 'mime_module' - 'status_module' - 'dir_module' - 'alias_module' - 'version_module' - ) - - # Available DSO Modules - identifiers=( - 'auth_basic_module' - 'auth_digest_module' - 'authn_file_module' - 'authn_alias_module' - 'authn_anon_module' - 'authn_dbm_module' - 'authn_default_module' - 'authz_host_module' - 'authz_user_module' - 'authz_owner_module' - 'authz_groupfile_module' - 'authz_dbm_module' - 'authz_default_module' - 'ldap_module' - 'authnz_ldap_module' - 'include_module' - 'log_config_module' - 'logio_module' - 'env_module' - 'ext_filter_module' - 'mime_magic_module' - 'expires_module' - 'deflate_module' - 'headers_module' - 'usertrack_module' - 'setenvif_module' - 'mime_module' - 'dav_module' - 'status_module' - 'autoindex_module' - 'info_module' - 'dav_fs_module' - 'vhost_alias_module' - 'negotiation_module' - 'dir_module' - 'actions_module' - 'speling_module' - 'userdir_module' - 'alias_module' - 'substitute_module' - 'rewrite_module' - 'proxy_module' - 'proxy_balancer_module' - 'proxy_ftp_module' - 'proxy_http_module' - 'proxy_ajp_module' - 'proxy_connect_module' - 'cache_module' - 'suexec_module' - 'disk_cache_module' - 'cgi_module' - 'version_module' - 'reqtimeout_module' - 'asis_module' - 'authn_dbd_module' - 'cern_meta_module' - 'cgid_module' - 'dbd_module' - 'dumpio_module' - 'filter_module' - 'ident_module' - 'log_forensic_module' - 'unique_id_module' - ) - fi - - for identifier in "${identifiers_default[@]}" - do - # Prevent invalid or unavailable module identifiers - if [[ " ${identifiers[@]} " =~ " ${identifier} " ]] - then - enabled+=" - ${identifier}\n" - sed_command+="$( - printf -- \ - " -e 's~^#LoadModule %s ~LoadModule %s ~g'" \ - "${identifier}" \ - "${identifier}" - )" - fi - done - - if [[ -n ${modules} ]] - then - for identifier in ${modules} - do - # Prevent invalid, unavailable or duplicate module identifiers - if [[ " ${identifiers[@]} " =~ " ${identifier} " ]] \ - && ! [[ " ${identifiers_default[@]} " =~ " ${identifier} " ]] - then - enabled+=" - ${identifier}\n" - sed_command+="$( - printf -- \ - " -e 's~^#LoadModule %s ~LoadModule %s ~g'" \ - "${identifier}" \ - "${identifier}" - )" - fi - done - fi - - if [[ -n ${sed_command} ]] - then - for config_file in "${config_files[@]}" - do - if [[ -f /etc/httpd/conf.modules.d/${config_file} ]] - then - config_paths+=" /etc/httpd/conf.modules.d/${config_file}" - fi - done - - eval "$( - printf -- \ - 'sed -i %s %s' \ - "${sed_command}" \ - "${config_paths}" - )" - fi - - printf -- \ - '%b' \ - "${enabled}" \ - | sort -} - -function __get_apache_content_root () -{ - local -r default_value="${1:-/var/www/app}" - - local value="${APACHE_CONTENT_ROOT}" - - if ! __is_valid_apache_content_root "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_custom_log_format () -{ - local -r default_value="${1:-combined}" - - local value="${APACHE_CUSTOM_LOG_FORMAT}" - - if ! __is_valid_apache_custom_log_format "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_custom_log_location () -{ - local -r content_root="${2:-"$( - __get_apache_content_root - )"}" - local -r default_value="${1:-var/log/apache_access_log}" - - local value="${APACHE_CUSTOM_LOG_LOCATION:-${default_value}}" - - if [[ ! ${value} =~ ^[\.]{,2}/ ]] - then - printf -v \ - value \ - -- '%s/%s' \ - "${content_root}" \ - "${value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_document_root () -{ - local -r content_root="${1:-"$( - __get_apache_content_root - )"}" - local -r public_directory="${2:-"$( - __get_apache_public_directory - )"}" - - printf -- \ - '%s/%s' \ - "${content_root}" \ - "${public_directory}" -} - -function __get_apache_error_log_level () -{ - local -r default_value="${1:-warn}" - - local value="${APACHE_ERROR_LOG_LEVEL}" - - if ! __is_valid_apache_error_log_level "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_error_log_location () -{ - local -r content_root="${2:-"$( - __get_apache_content_root - )"}" - local -r default_value="${1:-var/log/apache_error_log}" - - local value="${APACHE_ERROR_LOG_LOCATION:-${default_value}}" - - if [[ ! ${value} =~ ^[\.]{,2}/ ]] - then - printf -v \ - value \ - -- '%s/%s' \ - "${content_root}" \ - "${value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_extended_status_enabled () -{ - local -r default_value="${1:-false}" - - local value="${APACHE_EXTENDED_STATUS_ENABLED}" - - if ! __is_valid_apache_extended_status_enabled "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_header_x_service_uid () -{ - local value="${APACHE_HEADER_X_SERVICE_UID}" - - value="${value//'{{HOSTNAME}}'/${HOSTNAME:-localhost.localdomain}}" - - printf -- '%s' "${value}" -} - -function __get_apache_load_modules () -{ - local value="${APACHE_LOAD_MODULES}" - - printf -- '%s' "${value}" -} - -function __get_apache_mod_ssl_enabled () -{ - local -r default_value="${1:-false}" - - local value="${APACHE_MOD_SSL_ENABLED}" - - if ! __is_valid_apache_mod_ssl_enabled "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_mpm () -{ - local -r default_value="${1:-prefork}" - - local value="${APACHE_MPM}" - - if ! __is_valid_apache_mpm "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_operating_mode () -{ - local -r default_value="${1:-production}" - - local value="${APACHE_OPERATING_MODE}" - - if ! __is_valid_apache_operating_mode "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_public_directory () -{ - local -r default_value="${1:-public_html}" - - local value="${APACHE_PUBLIC_DIRECTORY}" - - if ! __is_valid_apache_public_directory "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_run_group () -{ - local -r default_value="${1:-app-www}" - - local value="${APACHE_RUN_GROUP}" - - if ! __is_valid_apache_run_group "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_run_user () -{ - local -r default_value="${1:-app-www}" - - local value="${APACHE_RUN_USER}" - - if ! __is_valid_apache_run_user "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_server_alias () -{ - local value="${APACHE_SERVER_ALIAS}" - - value="${value//'{{HOSTNAME}}'/${HOSTNAME:-localhost.localdomain}}" - - printf -- '%s' "${value}" -} - -function __get_apache_server_name () -{ - local value="${APACHE_SERVER_NAME:-"{{HOSTNAME}}"}" - - value="${value//'{{HOSTNAME}}'/${HOSTNAME:-localhost.localdomain}}" - - printf -- '%s' "${value}" -} - -function __get_apache_ssl_certificate () -{ - local -r default_value="" - local -r base64_pattern='^[A-Za-z0-9/+=]*$' - - local value="${APACHE_SSL_CERTIFICATE}" - - if [[ -n ${value} ]] - then - if [[ -f ${value} ]] - then - value="$(< "${value}")" - fi - - if [[ ${value} =~ ${base64_pattern} ]] - then - value="$( - base64 -d -i <<< "${value}" - )" - fi - - if ! __is_valid_apache_ssl_certificate "${value}" - then - value="${default_value}" - fi - fi - - printf -- '%s' "${value}" -} - -function __get_apache_ssl_cipher_suite () -{ - local -r default_value="${1:-ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS}" - - local value="${APACHE_SSL_CIPHER_SUITE}" - - if ! __is_valid_apache_ssl_cipher_suite "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_ssl_protocol () -{ - local -r default_value="${1:-"All -SSLv2 -SSLv3"}" - - local value="${APACHE_SSL_PROTOCOL}" - - if ! __is_valid_apache_ssl_protocol "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_system_user () -{ - local -r default_value="${1:-app}" - - local value="${APACHE_SYSTEM_USER}" - - if ! __is_valid_apache_system_user "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_apache_server_version () -{ - local semantic_version - - if ! command -v httpd &> /dev/null - then - >&2 printf -- \ - 'ERROR: Apache Server binary not installed.\n' - return 1 - fi - - semantic_version="$( - httpd -v \ - | grep -E -o 'Server version: Apache\/[0-9]+\.[0-9]+\.[0-9]+' \ - | awk -F/ '{ print $NF; }' - )" - - printf -- '%s' "${semantic_version}" -} - -function __get_details_ssl_certificate_fingerprint () -{ - local -r digest="${1:-sha1}" - local -r fingerprint="$( - __get_ssl_certificate_fingerprint \ - "${digest}" - )" - - printf -- \ - '\ntls/ssl certificate %s fingerprint : \n%s' \ - "${digest}" \ - "${fingerprint}" -} - -function __get_package_path () -{ - local -r default_value="${1:-/opt/app}" - - local value="${PACKAGE_PATH}" - - if ! __is_valid_package_path "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_password () -{ - local -r length="${1:-16}" - local -r password="$( - head -n 4096 /dev/urandom \ - | tr -cd '[:alnum:]' \ - | cut -c1-"${length}" - )" - - printf -- '%s' "${password}" -} - -function __get_php_options_date_timezone () -{ - local -r default_value="${1:-UTC}" - - local value="${PHP_OPTIONS_DATE_TIMEZONE}" - - if ! __is_valid_php_options_date_timezone "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_php_options_session_name () -{ - local -r default_value="${1:-PHPSESSID}" - - local value="${PHP_OPTIONS_SESSION_NAME}" - - if ! __is_valid_php_options_session_name "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_php_options_session_save_handler () -{ - local -r default_value="${1:-files}" - - local value="${PHP_OPTIONS_SESSION_SAVE_HANDLER}" - - if ! __is_valid_php_options_session_save_handler "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __get_php_options_session_save_path () -{ - local -r content_root="${3:-"$( - __get_apache_content_root - )"}" - local -r default_value="${1:-var/session}" - local -r default_value_memcached="memcached:11211" - local -r default_value_redis="redis:6379" - local -r save_handler="${2:-"$( - __get_php_options_session_save_handler - )"}" - - local value="${PHP_OPTIONS_SESSION_SAVE_PATH}" - - if [[ -z "${value}" ]] - then - case "${save_handler}" in - # memcached) - # value="${default_value_memcached}" - # ;; - # redis) - # value="${default_value_redis}" - # ;; - files|*) - value="${default_value}" - ;; - esac - fi - - if [[ ${save_handler} == files ]] \ - && [[ ! ${value} =~ ^[\.]{,2}/ ]] - then - printf -v \ - value \ - -- '%s/%s' \ - "${content_root}" \ - "${value}" - fi - - printf -- '%s' "${value}" -} - -function __get_ssl_certificate_fingerprint () -{ - local -r digest="${1:-sha1}" - local -r certificate_path="${2:-/etc/pki/tls/certs/localhost.crt}" - - local value - - value="$( - openssl x509 \ - -"${digest,,}" \ - -in "${certificate_path}" \ - -noout \ - -fingerprint - )" - - value="${value//${digest^^}' Fingerprint='/}" - - printf -- '%s' "${value}" -} - -function __get_timer_total () -{ - local -r timer_end="$( - date +%s.%N - )" - local -r timer_start="${1}" - - if [[ -z ${timer_start} ]] \ - || [[ ${timer_start//.} -gt ${timer_end//.} ]] - then - >&2 printf -- \ - 'ERROR: invalid timer start: %s\n' \ - "${timer_start}" - printf -- \ - '0.000000' - else - awk \ - -v timer_end="${timer_end}" \ - -v timer_start="${timer_start}" \ - 'BEGIN { print \ - timer_end - timer_start; - }' - fi -} - -function __init_datadir () -{ - local -r content_root="${2:-"$( - __get_apache_content_root - )"}" - local -r content_root_prefix="$( - dirname \ - "${content_root}" - )" - local -r package_path="${1:-"$( - __get_package_path - )"}" - - verbose="${verbose:-false}" - - if [[ ! -d ${content_root_prefix} ]] - then - mkdir \ - -p \ - -m 755 \ - "${content_root_prefix}" - fi - - if [[ ! -d ${content_root} ]] - then - if [[ ${verbose} == true ]] - then - printf -- \ - 'Linking install directory %s > %s.\n' \ - "${package_path}" \ - "${content_root}" - fi - - ln -s \ - "${package_path}" \ - "${content_root}" - elif [[ -d ${content_root} ]] \ - && [[ ! -h ${content_root} ]] \ - && [[ -z "$(find "${content_root}" -maxdepth 1 -type f)" ]] - then - if [[ ${verbose} == true ]] - then - printf -- \ - 'Populating install directory %s > %s.\n' \ - "${package_path}" \ - "${content_root}" - fi - - cp -rpf \ - "${package_path}"/. \ - "${content_root}" - fi -} - -function __is_valid_apache_content_root () -{ - local -r directory_path="${1}" - local -r valid_directory='^\/(?!\/|bin|dev|etc|lib|lib64|lost+found|media|proc|root|sbin|sys|tmp|usr).+$' - - local absolute_path="$( - __absolute_path \ - "${directory_path}" - )" - - if grep -qoP "${valid_directory}" <<< "${absolute_path}" - then - return 0 - fi - - return 1 -} - -function __is_valid_apache_custom_log_format () -{ - local -r format="${1}" - local -r package_path="${2:-"$( - __get_package_path - )"}" - - local defined_format - local defined_formats - - if [[ -z ${format} ]] - then - return 1 - fi - - defined_formats="$( - find \ - /etc/httpd \ - "${package_path}"/etc/httpd \ - -type f \ - -name *.conf \ - | xargs \ - sed \ - -e ':a;N;$!ba;s/\\\n//g' \ - | grep 'LogFormat' \ - | awk '{ print $NF; }' \ - | sort \ - | uniq - )" - - for defined_format in ${defined_formats} - do - if [[ ${defined_format} == "${format}" ]] - then - return 0 - fi - done - - return 1 -} - -function __is_valid_apache_error_log_level () -{ - local -r apache_version="$( - __get_apache_server_version - )" - local -r valid_loglevel='^(emerg|alert|crit|error|warn|notice|info|debug)$' - local -r valid_loglevel_24='^trace[1-8]$' - local -r value="${1}" - - if [[ ${value} =~ ${valid_loglevel} ]] - then - return 0 - elif [[ ${apache_version} =~ ^2\.4\. ]] \ - && [[ ${value} =~ ${valid_loglevel_24} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_apache_extended_status_enabled () -{ - __is_valid_boolean "${@}" -} - -function __is_valid_apache_mod_ssl_enabled () -{ - __is_valid_boolean "${@}" -} - -function __is_valid_apache_mpm () -{ - local -r valid_value='^(prefork|worker|event)$' - local -r value="${1}" - - if [[ ${value} =~ ${valid_value} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_apache_operating_mode () -{ - local -r valid_value='^(production|development|debug)$' - local -r value="${1}" - - if [[ ${value} =~ ${valid_value} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_apache_run_group () -{ - __is_valid_user_login "${@}" -} - -function __is_valid_apache_run_user () -{ - __is_valid_user_login "${@}" -} - -function __is_valid_apache_public_directory () -{ - local -r directory="${1}" - local -r directory_absolute="$( - __absolute_path "$( - __get_apache_content_root - )/${directory}" - )" - local -r valid_directory='^\/(?!\/|bin|dev|etc|lib|lib64|lost+found|media|proc|root|sbin|sys|tmp|usr).+$' - local -r valid_subdirectory='^[^\/\\].+$' - - if grep -qoP "${valid_directory}" <<< "${directory_absolute}" \ - && grep -qoP "${valid_subdirectory}" <<< "${directory}" - then - return 0 - fi - - return 1 -} - -function __is_valid_apache_ssl_certificate () -{ - local -r certificate="${1}" - local -r certificate_pattern='^-----BEGIN ' - - if [[ ${certificate} =~ ${certificate_pattern} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_apache_ssl_certificate_file () -{ - local -r certificate_path="${1:-/etc/pki/tls/certs/localhost.crt}" - local -r fingerprint_pattern='^SHA1 Fingerprint=' - - local fingerprint - - fingerprint="$( - openssl \ - x509 \ - -sha1 \ - -in "${certificate_path}" \ - -noout \ - -fingerprint - )" - - if [[ ${fingerprint} =~ ${fingerprint_pattern} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_apache_ssl_cipher_suite () -{ - local cipher_list="${1}" - - if [[ -n ${cipher_list} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_apache_ssl_protocol () -{ - local protocol_list="${1}" - - if [[ -n ${protocol_list} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_apache_system_user () -{ - __is_valid_user_login "${@}" -} - -function __is_valid_boolean () -{ - local -r boolean_value='^(true|false)$' - local -r value="${1}" - - if [[ ${value} =~ ${boolean_value} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_package_path () -{ - __is_valid_apache_content_root "${@}" -} - -function __is_valid_php_options_date_timezone () -{ - __is_valid_timezone "${@}" -} - -# PHP Manual advises short alphanumeric values only however session names with -# _ and - are in common use. -function __is_valid_php_options_session_name () -{ - local -r alphanumeric_value='^[A-Za-z0-9_-]{1,16}$' - local -r numeric_value='^[0-9]+$' - local -r value="${1}" - - if [[ ${value} =~ ${alphanumeric_value} ]] \ - && [[ ! ${value} =~ ${numeric_value} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_php_options_session_save_handler () -{ - local -r registered_save_handlers="$( - php \ - -d error_reporting=0 \ - -i \ - | grep 'Registered save handlers' \ - | sed -r \ - -e 's~^.* => ~~' \ - -e 's~ ~|~g' \ - -e 's~^(.*)$~^(\1~' \ - -e 's~^(.*)\|$~\1)$~' - )" - local -r value="${1}" - - if [[ ${value} =~ ${registered_save_handlers} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_user_login () -{ - local -r login="${1}" - local -r valid_login='^[a-z_][a-z0-9_-]{0,29}[$a-z0-9_]?$' - - if [[ ${login} != root ]] \ - && [[ ${login} =~ ${valid_login} ]] - then - return 0 - fi - - return 1 -} - -function __is_valid_timezone () -{ - local -r zone="${1}" - - if [[ -z ${zone} ]] - then - return 1 - fi - - if [[ -f /usr/share/zoneinfo/${zone} ]] - then - return 0 - fi - - return 1 -} - -function __load_httpd_conf_scan_files () -{ - local -r package_path="${1:-"$( - __get_package_path - )"}" - - local file_path - - if [[ -n ${package_path} ]] \ - && [[ -d ${package_path}/etc/httpd/conf.d ]] - then - for file_path in "${package_path}"/etc/httpd/conf.d/*.conf - do - cat \ - "${file_path}" \ - > "/etc/httpd/conf.d/${file_path##*/}" - done - fi - - if [[ -n ${package_path} ]] \ - && [[ -d ${package_path}/etc/httpd/conf.virtualhost.d ]] - then - for file_path in "${package_path}"/etc/httpd/conf.virtualhost.d/*.conf - do - cat \ - "${file_path}" \ - > "/etc/httpd/conf.virtualhost.d/${file_path##*/}" - done - fi -} - -function __load_php_ini_scan_file () -{ - local -r file_path="${1}" - local -r scan_directory="${2}" - - if [[ -n ${scan_directory} ]] \ - && [[ -n ${file_path} ]] \ - && [[ -s ${file_path} ]] - then - cat \ - "${file_path}" \ - > "${scan_directory}/${file_path##*/}" - fi -} - -function __load_php_ini_scan_files () -{ - local -r package_path="${1:-"$( - __get_package_path - )"}" - local -r scan_directory="/etc/php.d" - - local file_path - - if [[ -n ${package_path} ]] \ - && [[ -d ${package_path}/etc/php.d ]] - then - for file_path in "${package_path}/${scan_directory}"/*.ini - do - __load_php_ini_scan_file \ - "${file_path}" \ - "${scan_directory}" - done - fi -} - -function __make_self_signed_san_certificate () -{ - local -r certificate_path="/etc/pki/tls/certs/localhost.crt" - local -r config_path="/etc/pki/tls/certs/localhost.cnf" - local -r default_config_path="/etc/pki/tls/openssl.cnf" - local -r hosts="${@}" - - local common_name - local host - local subject_alt_name - - # Use default host if none specified. - if [[ ${#hosts[@]} -eq 0 ]] - then - hosts="localhost.localdomain" - fi - - if [[ ${#hosts[@]} -gt 0 ]] - then - for host in ${hosts[@]} - do - if [[ -z ${subject_alt_name} ]] - then - # Common Name is required - use the first host. - common_name="${host}" - else - # Additional hosts should be comma separated. - subject_alt_name+="," - fi - - # Build up the subjectAltName value. - subject_alt_name+="DNS:${host}" - done - fi - - # Generate a custom openssl configuration - appending a san section. - cat \ - "${default_config_path}" \ - - \ - <<-CONFIG > "${config_path}" - - [ san ] - subjectAltName="${subject_alt_name:-root@localhost.localdomain}" - CONFIG - - # Generate the certificate. - openssl req \ - -x509 \ - -sha256 \ - -nodes \ - -newkey rsa:2048 \ - -days 365 \ - -reqexts san \ - -extensions san \ - -subj "/CN=${common_name}" \ - -config "${config_path}" \ - -keyout "${certificate_path}" \ - -out "${certificate_path}" -} - -function __set_apache_enable_sendfile () -{ - local enable="${1:-true}" - local match - local replace - - if [[ ${enable} == true ]] - then - match="^[#]?EnableSendfile (Off|off)$" - replace="#EnableSendfile on" - else - match="^[#]?EnableSendfile (On|on|Off|off)$" - replace="EnableSendfile off" - fi - - sed -r -i \ - -e "s~${match}~${replace}~g" \ - /etc/httpd/conf/httpd.conf -} - -function __set_apache_extended_status () -{ - local enable="${1:-"$( - __get_apache_extended_status_enabled - )"}" - local match - local replace - - if [[ ${enable} == true ]] - then - match="^[#]?ExtendedStatus (On|on|Off|off)$" - replace="ExtendedStatus On" - else - match="^ExtendedStatus (On|on)$" - replace="#ExtendedStatus On" - fi - - sed -r -i \ - -e "s~${match}~${replace}~g" \ - /etc/httpd/conf/httpd.conf -} - -function __set_apache_header_x_service_uid () -{ - local header="${1}" - - if [[ -n ${header} ]] - then - sed -r -i \ - -e "s~(\\$\{|\{\{)APACHE_HEADER_X_SERVICE_UID(\}\}|(:-.+)?\})~${header}~g" \ - /etc/httpd/conf.d/00-headers.conf - else - # Remove X-Service-UID header if an empty value. - sed -r -i \ - -e 's~^([ \t]*)(Header set X-Service-UID .*)$~\1#\2~g' \ - /etc/httpd/conf.d/00-headers.conf - fi -} - -function __set_apache_mod_ssl_enabled () -{ - local enable="${1:-"$( - __get_apache_mod_ssl_enabled - )"}" - - if [[ ${enable} == true ]] - then - cat \ - /etc/httpd/conf.d/ssl.conf.off \ - > /etc/httpd/conf.d/00-ssl.conf - - if [[ -f /etc/httpd/conf.d/10-ssl-vhost.conf.off ]] - then - cat \ - /etc/httpd/conf.d/10-ssl-vhost.conf.off \ - > /etc/httpd/conf.d/10-ssl-vhost.conf - fi - - if [[ -f /etc/httpd/conf.modules.d/00-ssl.conf ]] - then - sed -i \ - -e 's~^#\(LoadModule ssl_module .*\)$~\1~' \ - /etc/httpd/conf.modules.d/00-ssl.conf - fi - else - truncate -s 0 \ - /etc/httpd/conf.d/00-ssl.conf - - if [[ -f /etc/httpd/conf.d/10-ssl-vhost.conf ]] - then - truncate -s 0 \ - /etc/httpd/conf.d/10-ssl-vhost.conf - fi - - if [[ -f /etc/httpd/conf.modules.d/00-ssl.conf ]] - then - sed -i \ - -e 's~^\(LoadModule ssl_module .*\)$~#\1~' \ - /etc/httpd/conf.modules.d/00-ssl.conf - fi - fi -} - -function __set_apache_mpm () -{ - local apache_mpm="${1:-"$( - __get_apache_mpm - )"}" - - case "${apache_mpm,,}" in - event) - if [[ -f /etc/httpd/conf.modules.d/00-mpm.conf ]] - then - sed -r -i \ - -e 's~^(LoadModule.*)$~#\1~g' \ - -e 's~^#(LoadModule mpm_event_module.*)$~\1~' \ - /etc/httpd/conf.modules.d/00-mpm.conf - elif [[ -f /usr/sbin/httpd.event ]] - then - sed -r -i \ - -e 's~^#?(HTTPD=/usr/sbin/httpd).*$~\1.event~' \ - /etc/sysconfig/httpd - else - >&2 printf -- \ - 'ERROR: Invalid Apache Server MPM: %s\n' \ - "${apache_mpm}" - exit 1 - fi - ;; - worker) - if [[ -f /etc/httpd/conf.modules.d/00-mpm.conf ]] - then - sed -r -i \ - -e 's~^(LoadModule.*)$~#\1~g' \ - -e 's~^#(LoadModule mpm_worker_module.*)$~\1~' \ - /etc/httpd/conf.modules.d/00-mpm.conf - elif [[ -f /usr/sbin/httpd.worker ]] - then - sed -r -i \ - -e 's~^#?(HTTPD=/usr/sbin/httpd).*$~\1.worker~' \ - /etc/sysconfig/httpd - else - >&2 printf -- \ - 'ERROR: Invalid Apache Server MPM: %s\n' \ - "${apache_mpm}" - exit 1 - fi - ;; - prefork) - if [[ -f /etc/httpd/conf.modules.d/00-mpm.conf ]] - then - sed -r -i \ - -e 's~^(LoadModule.*)$~#\1~g' \ - -e 's~^#(LoadModule mpm_prefork_module.*)$~\1~' \ - /etc/httpd/conf.modules.d/00-mpm.conf - elif [[ -f /usr/sbin/httpd ]] - then - sed -r -i \ - -e 's~^(HTTPD=/usr/sbin/httpd.*)$~#\1~g' \ - /etc/sysconfig/httpd - else - >&2 printf -- \ - 'ERROR: Invalid Apache Server MPM: %s\n' \ - "${apache_mpm}" - exit 1 - fi - ;; - *) - >&2 printf -- \ - 'ERROR: Invalid Apache Server MPM: %s\n' \ - "${apache_mpm}" - exit 1 - ;; - esac -} - -function __set_apache_server_name () -{ - local -r host="${1:-"$( - __get_apache_server_name - )"}" - local -r port="${2:-80}" - - sed -i \ - -e "s~^#ServerName \(.*\):80$~ServerName ${host}:${port}~g" \ - /etc/httpd/conf/httpd.conf -} - -function __set_apache_ssl_certificate () -{ - local -r certificate="${1:-"$( - __get_apache_ssl_certificate - )"}" - local -r certificate_path="/etc/pki/tls/certs/localhost.crt" - - local server_name - local server_alias - - if [[ -z ${certificate} ]] - then - server_name="${2:-"$( - __get_apache_server_name - )"}" - server_alias="${3:-"$( - __get_apache_server_alias - )"}" - - __make_self_signed_san_certificate \ - "${server_name}" \ - "${server_alias}" \ - &> /dev/null - else - printf -- \ - '%s' \ - "${certificate}" \ - > "${certificate_path}" - fi - - if ! __is_valid_apache_ssl_certificate_file "${certificate_path}" - then - >&2 printf -- \ - 'ERROR: Invalid APACHE_SSL_CERTIFICATE\n' - exit 1 - fi -} - -function __set_apache_run_user () -{ - local -r user="${1:-"$( - __get_apache_run_user - )"}" - local -r user_default="${2:-app-www}" - - __update_user_login \ - "${user_default}" \ - "${user}" -} - -function __set_apache_run_group () -{ - local -r group="${1:-"$( - __get_apache_run_group - )"}" - local -r group_default="${2:-app-www}" - - __update_group_name \ - "${group_default}" \ - "${group}" -} - -function __set_apache_system_user () -{ - local -r user="${1:-"$( - __get_apache_system_user - )"}" - local -r user_default="${2:-app}" - - __update_user_login \ - "${user_default}" \ - "${user}" - __update_group_name \ - "${user_default}" \ - "${user}" -} - -function __set_loopback_hosts_entry () -{ - local server_name="${1:-"$( - __get_apache_server_name - )"}" - local server_alias="${2:-"$( - __get_apache_server_alias - )"}" - - __add_hosts_entry \ - "127.0.0.1" \ - "$( - printf -- \ - '%s%s%s' \ - "${apache_server_name}" \ - "${apache_server_alias:+ }" \ - "${apache_server_alias}" - )" -} - -function __set_php_fpm_pool () -{ - local -r user="${1:-"$( - __get_apache_run_user - )"}" - local -r group="${2:-"$( - __get_apache_run_group - )"}" - - if [[ -f /etc/php-fpm.d/www.conf.template ]] - then - rm -f /etc/php-fpm.d/*.conf - - sed \ - -e "s~{{APACHE_RUN_GROUP}}~${group}~g" \ - -e "s~{{APACHE_RUN_USER}}~${user}~g" \ - /etc/php-fpm.d/www.conf.template \ - > "/etc/php-fpm.d/${user}.conf" - - sed -i \ - -e "s~php-fpm/\(.*\)\.sock~php-fpm/${user}\.sock~" \ - /etc/httpd/conf.d/php-fpm.conf - fi -} - -function __update_group_name () -{ - local -r group="${1}" - local -r group_new="${2}" - - if [[ ${group_new} != "${group}" ]] \ - && [[ ${group_new} != root ]] \ - && [[ ${group} != root ]] \ - && [[ -n $(getent group "${group}") ]] - then - groupmod -n "${group_new}" "${group}" - fi -} - -function __update_user_login () -{ - local -r user="${1}" - local -r user_new="${2}" - - if [[ ${user_new} != "${user}" ]] \ - && __is_valid_user_login "${user_new}" \ - && __is_valid_user_login "${user}" \ - && [[ -z $(getent passwd "${user_new}") ]] \ - && [[ -n $(getent passwd "${user}") ]] - then - usermod -l "${user_new}" "${user}" - fi -} - -function main () -{ - local -r lock_file="/var/lock/subsys/httpd-bootstrap" - local -r ssl_certificate_fingerprint_digest="sha1" - local -r state_file="/var/lib/misc/httpd-bootstrap" - local -r timer_start="$( - date +%s.%N - )" - - local HOSTNAME - local apache_content_root - local apache_custom_log_format - local apache_custom_log_location - local apache_error_log_level - local apache_error_log_location - local apache_extended_status_enabled - local apache_header_x_service_uid - local apache_mod_ssl_enabled - local apache_mpm - local apache_operating_mode - local apache_public_directory - local apache_run_group - local apache_run_user - local apache_server_alias - local apache_server_name - local apache_ssl_certificate - local apache_ssl_cipher_suite - local apache_ssl_protocol - local apache_system_user - local config_files - local details_modules_enabled_list - local details_ssl_certificate_fingerprint - local document_root - local document_root_file_system - local package_path - local php_options_date_timezone - local php_options_session_name - local php_options_session_save_handler - local php_options_session_save_path - local -a pids - local verbose="false" - - # Parse options - while [[ "${#}" -gt 0 ]] - do - case "${1}" in - -v|--verbose) - verbose="true" - shift 1 - ;; - esac - done - - if [[ -e ${state_file} ]] - then - if [[ ${verbose} == true ]] - then - printf -- \ - 'INFO: %s finished - skipping.\n' \ - "${0##*/}" - fi - exit 0 - fi - - if [[ -e ${lock_file} ]] - then - >&2 printf -- \ - 'ERROR: %s lock detected - aborting.\n' \ - "${0##*/}" - exit 1 - fi - - trap \ - "__cleanup \"${lock_file}\" \"${state_file}\"" \ - INT TERM EXIT - - # Create lock - touch \ - "${lock_file}" - - HOSTNAME="$( - hostname - )" - - apache_content_root="$( - __get_apache_content_root - )" - apache_custom_log_format="$( - __get_apache_custom_log_format - )" - apache_custom_log_location="$( - __get_apache_custom_log_location - )" - apache_error_log_level="$( - __get_apache_error_log_level - )" - apache_error_log_location="$( - __get_apache_error_log_location - )" - apache_extended_status_enabled="$( - __get_apache_extended_status_enabled - )" - apache_header_x_service_uid="$( - __get_apache_header_x_service_uid - )" - apache_mod_ssl_enabled="$( - __get_apache_mod_ssl_enabled - )" - apache_mpm="$( - __get_apache_mpm - )" - apache_operating_mode="$( - __get_apache_operating_mode - )" - apache_public_directory="$( - __get_apache_public_directory - )" - apache_run_group="$( - __get_apache_run_group - )" - apache_run_user="$( - __get_apache_run_user - )" - apache_server_alias="$( - __get_apache_server_alias - )" - apache_server_name="$( - __get_apache_server_name - )" - apache_system_user="$( - __get_apache_system_user - )" - php_options_date_timezone="$( - __get_php_options_date_timezone - )" - php_options_session_name="$( - __get_php_options_session_name - )" - php_options_session_save_handler="$( - __get_php_options_session_save_handler - )" - php_options_session_save_path="$( - __get_php_options_session_save_path - )" - - document_root="$( - __get_apache_document_root - )" - package_path="$( - __get_package_path - )" - - # Verify package installation directory exists - if [[ ! -d ${package_path} ]] - then - >&2 printf -- \ - 'ERROR: %s not found.\n' \ - "${package_path}" - exit 1 - fi - - if [[ ${apache_mod_ssl_enabled} == true ]] - then - apache_ssl_certificate="$( - __get_apache_ssl_certificate - )" - apache_ssl_cipher_suite="$( - __get_apache_ssl_cipher_suite - )" - apache_ssl_protocol="$( - __get_apache_ssl_protocol - )" - - __set_apache_ssl_certificate \ - "${apache_ssl_certificate}" \ - "${apache_server_name}" \ - "${apache_server_alias}" \ - & - pids[1]="${!}" - fi - - __load_php_ini_scan_files \ - "${package_path}" - __set_php_fpm_pool \ - "${apache_run_user}" \ - "${apache_run_group}" - __set_apache_mpm \ - "${apache_mpm}" - __load_httpd_conf_scan_files \ - "${package_path}" - __set_apache_header_x_service_uid \ - "${apache_header_x_service_uid}" - __set_apache_server_name \ - "${apache_server_name}" - __set_apache_mod_ssl_enabled \ - "${apache_mod_ssl_enabled}" - __set_apache_extended_status \ - "${apache_extended_status_enabled}" - - details_modules_enabled_list="$( - __enable_apache_modules - )" - - __set_apache_system_user \ - "${apache_system_user}" - __set_apache_run_user \ - "${apache_run_user}" - __set_apache_run_group \ - "${apache_run_group}" - __set_loopback_hosts_entry \ - "${apache_server_name}" \ - "${apache_server_alias}" - - # Set ownership for fcgid php-wrapper and socket if necessary - if [[ -d /var/run/mod_fcgid ]] \ - && [[ -d ${package_path}/bin ]] - then - chown -R \ - "${apache_run_user}":"${apache_run_group}" \ - {"${package_path}"/bin,/var/run/mod_fcgid} - fi - - __init_datadir \ - "${package_path}" \ - "${apache_content_root}" - - # Verify Apache DocumentRoot directory exists - if [[ ! -d ${document_root} ]] - then - >&2 printf -- \ - 'ERROR: %s not found.\n' \ - "${document_root}" - exit 1 - fi - - document_root_file_system="$( - df -PT "${document_root}" \ - | awk 'NR>1 { print $2 }' - )" - if [[ ${document_root_file_system} == nfs ]] - then - if [[ ${verbose} == true ]] - then - printf -- \ - 'Disabling EnableSendfile.' - fi - __set_apache_enable_sendfile \ - "false" - fi - - config_files="$( - find \ - /etc/httpd \ - /etc/php.d \ - -type f \ - -name *.conf \ - -o \ - -name *.ini \ - | tr '\n' ' ' - )" - - # Replace both environment variables with optional default values or - # mustache style placeholders - sed -r -i \ - -e "s~(\\$\{|\{\{)APACHE_CONTENT_ROOT(\}\}|(:-.+)?\})~${apache_content_root}~g" \ - -e "s~(\\$\{|\{\{)APACHE_CUSTOM_LOG_FORMAT(\}\}|(:-.+)?\})~${apache_custom_log_format}~g" \ - -e "s~(\\$\{|\{\{)APACHE_CUSTOM_LOG_LOCATION(\}\}|(:-.+)?\})~${apache_custom_log_location}~g" \ - -e "s~(\\$\{|\{\{)APACHE_ERROR_LOG_LOCATION(\}\}|(:-.+)?\})~${apache_error_log_location}~g" \ - -e "s~(\\$\{|\{\{)APACHE_ERROR_LOG_LEVEL(\}\}|(:-.+)?\})~${apache_error_log_level}~g" \ - -e "s~(\\$\{|\{\{)APACHE_PUBLIC_DIRECTORY(\}\}|(:-.+)?\})~${apache_public_directory}~g" \ - -e "s~(\\$\{|\{\{)APACHE_RUN_GROUP(\}\}|(:-.+)?\})~${apache_run_group}~g" \ - -e "s~(\\$\{|\{\{)APACHE_RUN_USER(\}\}|(:-.+)?\})~${apache_run_user}~g" \ - -e "s~(\\$\{|\{\{)APACHE_SERVER_ALIAS(\}\}|(:-.+)?\})~${apache_server_alias}~g" \ - -e "s~(\\$\{|\{\{)APACHE_SERVER_NAME(\}\}|(:-.+)?\})~${apache_server_name}~g" \ - -e "s~(\\$\{|\{\{)APACHE_SSL_CIPHER_SUITE(\}\}|(:-.+)?\})~${apache_ssl_cipher_suite}~g" \ - -e "s~(\\$\{|\{\{)APACHE_SSL_PROTOCOL(\}\}|(:-.+)?\})~${apache_ssl_protocol}~g" \ - -e "s~(\\$\{|\{\{)APACHE_SYSTEM_USER(\}\}|(:-.+)?\})~${apache_system_user}~g" \ - -e "s~(\\$\{|\{\{)PHP_OPTIONS_DATE_TIMEZONE(\}\}|(:-.+)?\})~${php_options_date_timezone}~g" \ - -e "s~(\\$\{|\{\{)PHP_OPTIONS_SESSION_NAME(\}\}|(:-.+)?\})~${php_options_session_name}~g" \ - -e "s~(\\$\{|\{\{)PHP_OPTIONS_SESSION_SAVE_HANDLER(\}\}|(:-.+)?\})~${php_options_session_save_handler}~g" \ - -e "s~(\\$\{|\{\{)PHP_OPTIONS_SESSION_SAVE_PATH(\}\}|(:-.+)?\})~${php_options_session_save_path}~g" \ - ${config_files} - - if [[ ${apache_mod_ssl_enabled} == true ]] - then - # Wait for certificate generation if necessary - if [[ -n ${pids[1]} ]] - then - wait ${pids[1]} - fi - - if [[ ${verbose} == true ]] - then - details_ssl_certificate_fingerprint="$( - __get_details_ssl_certificate_fingerprint - )" - fi - fi - - if [[ ${verbose} == true ]] - then - timer_total="$( - __get_timer_total \ - "${timer_start}" - )" - - cat <<-EOT - - ================================================================================ - Apache Details - -------------------------------------------------------------------------------- - custom log location : ${apache_custom_log_location} - custom log format : ${apache_custom_log_format} - document root : ${document_root} (${document_root_file_system}) - error log location : ${apache_error_log_location} - error log level : ${apache_error_log_level} - header x-service-uid : ${apache_header_x_service_uid} - modules enabled : - ${details_modules_enabled_list} - operating mode : ${apache_operating_mode} - run group : ${apache_run_group} - run user : ${apache_run_user} - server alias : ${apache_server_alias} - server mpm : ${apache_mpm,,} - server name : ${apache_server_name} - system user : ${apache_system_user}${details_ssl_certificate_fingerprint} - - ================================================================================ - PHP Details - -------------------------------------------------------------------------------- - date.timezone : ${php_options_date_timezone} - session.name : ${php_options_session_name} - session.save_handler : ${php_options_session_save_handler} - session.save_path : ${php_options_session_save_path} - -------------------------------------------------------------------------------- - ${timer_total} - - EOT - fi -} - -main "${@}" \ No newline at end of file diff --git a/test/shpec/operation_shpec.sh b/test/shpec/operation_shpec.sh index 498ab67..c3ebd5c 100644 --- a/test/shpec/operation_shpec.sh +++ b/test/shpec/operation_shpec.sh @@ -88,7 +88,7 @@ function __setup () local -r session_store_alias="memcached_1" local -r session_store_name="memcached.pool-1.1.1" local -r session_store_network="bridge_internal_1" - local -r session_store_release="1.1.3" + local -r session_store_release="1.3.1" if [[ -z $(docker network ls -q -f name="${session_store_network}") ]]; then docker network create \ @@ -221,9 +221,9 @@ ${other_required_apache_modules} local container_hostname="" local container_port_80="" local curl_get_request="" - local curl_session_name="" local header_server="" local header_x_service_uid="" + local php_session_name="" local status=0 describe "Basic Apache PHP operations" @@ -317,6 +317,7 @@ ${other_required_apache_modules} apache_details_title="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | grep '^Apache Details' \ | tr -d '\r' )" @@ -331,6 +332,7 @@ ${other_required_apache_modules} apache_system_user="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | grep '^system user : ' \ | cut -c 15- \ | tr -d '\r' @@ -345,6 +347,7 @@ ${other_required_apache_modules} apache_run_user="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | grep '^run user : ' \ | cut -c 12- \ | tr -d '\r' @@ -359,6 +362,7 @@ ${other_required_apache_modules} apache_run_group="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | grep '^run group : ' \ | cut -c 13- \ | tr -d '\r' @@ -373,6 +377,7 @@ ${other_required_apache_modules} apache_server_name="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | grep '^server name : ' \ | cut -c 15- \ | tr -d '\r' @@ -387,6 +392,7 @@ ${other_required_apache_modules} apache_server_alias="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | grep '^server alias : ' \ | cut -c 16- \ | tr -d '\r' @@ -401,6 +407,7 @@ ${other_required_apache_modules} header_x_service_uid="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | grep '^header x-service-uid : ' \ | cut -c 24- \ | tr -d '\r' @@ -416,6 +423,7 @@ ${other_required_apache_modules} apache_document_root="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | grep '^document root : ' \ | cut -c 17- \ | tr -d '\r' \ @@ -432,6 +440,7 @@ ${other_required_apache_modules} apache_server_mpm="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | grep '^server mpm : ' \ | cut -c 13- \ | tr -d '\r' \ @@ -447,6 +456,7 @@ ${other_required_apache_modules} apache_load_modules="$( docker logs \ apache-php.1 \ + 2> /dev/null \ | sed -ne \ '/^modules enabled :/,/^--+$/ p' \ | awk '/^ - /' @@ -633,20 +643,16 @@ ${other_required_apache_modules} describe "PHP options" it "Has default session.name." - curl_session_name="$( - curl -s \ - --header 'Host: localhost.localdomain' \ - http://127.0.0.1:${container_port_80}/_phpinfo.php \ - | grep 'session.name' \ - | sed -E \ - -e 's~^.*(session.name)~\1~' \ - -e 's~~~g' \ - -e 's~]*>~ ~g' + php_session_name="$( + docker exec \ + apache-php.1 \ + php -r \ + "printf('%s', ini_get('session.name'));" )" assert equal \ - "${curl_session_name}" \ - "session.name PHPSESSID PHPSESSID" + "${php_session_name}" \ + "PHPSESSID" end end @@ -682,11 +688,11 @@ function test_custom_configuration () local curl_response_code_server_alias="" local curl_session_data_write="" local curl_session_data_read="" - local curl_session_name="" local header_x_service_operating_mode="" local header_x_service_uid="" local is_up="" local php_date_timezone="" + local php_session_name="" local protocol="" describe "Customised Apache PHP configuration" @@ -2095,7 +2101,7 @@ function test_custom_configuration () docker run \ --detach \ --name apache-php.1 \ - --env APACHE_AUTOSTART_HTTPD_BOOTSTRAP=false \ + --env ENABLE_HTTPD_BOOTSTRAP=false \ jdeathe/centos-ssh-apache-php:latest \ &> /dev/null @@ -2129,7 +2135,7 @@ function test_custom_configuration () docker run \ --detach \ --name apache-php.1 \ - --env APACHE_AUTOSTART_HTTPD_WRAPPER=false \ + --env ENABLE_HTTPD_WRAPPER=false \ jdeathe/centos-ssh-apache-php:latest \ &> /dev/null @@ -2185,8 +2191,7 @@ function test_custom_configuration () php_date_timezone="$( docker exec \ apache-php.1 \ - php \ - -r \ + php -r \ "printf('%s', ini_get('date.timezone'));" )" @@ -2225,20 +2230,16 @@ function test_custom_configuration () )" it "Sets to app-session." - curl_session_name="$( - curl -s \ - --header 'Host: localhost.localdomain' \ - http://127.0.0.1:${container_port_80}/_phpinfo.php \ - | grep 'session.name' \ - | sed -E \ - -e 's~^.*(session.name)~\1~' \ - -e 's~~~g' \ - -e 's~]*>~ ~g' + php_session_name="$( + docker exec \ + apache-php.1 \ + php -r \ + "printf('%s', ini_get('session.name'));" )" assert equal \ - "${curl_session_name}" \ - "session.name app-session app-session" + "${php_session_name}" \ + "app-session" end __terminate_container \ From 5bd1fe113382be2c9176522b5a167ccd6733791a Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 18:09:53 +0100 Subject: [PATCH 08/11] #193: Adds php-wrapper and the httpd configuration to implement it. --- CHANGELOG.md | 1 + Dockerfile | 10 +++--- src/etc/httpd/conf.d/00-fcgid.conf | 25 +++++++++++++++ src/var/www/cgi-bin/php-wrapper | 50 ++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 src/etc/httpd/conf.d/00-fcgid.conf create mode 100755 src/var/www/cgi-bin/php-wrapper diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bf3b52..c02aae6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Summary of release changes. - Updates README-short.txt to apply to all image variants. - Updates Dockerfile `org.deathe.description` metadata LABEL for consistency + include PHP redis module. - Adds `.env` files to `.gitignore` for exclusion from version control. +- Adds `php-wrapper` and `fcgid.conf` as part of the service; removing dependency on the php-hello-world app. - Removes unused `DOCKER_PORT_MAP_TCP_22` variable from environment includes. ### 1.12.0 - 2019-04-14 diff --git a/Dockerfile b/Dockerfile index 1f30ada..af92ae3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,13 +25,13 @@ ADD src / # ------------------------------------------------------------------------------ # Provisioning -# - Relocate default fcgid configuration to ensure correct loading order +# - Disable default fcgid configuration; replaced with 00-fcgid.conf # - Replace placeholders with values in systemd service unit template # - Set permissions # ------------------------------------------------------------------------------ RUN cat \ /etc/httpd/conf.d/fcgid.conf \ - > /etc/httpd/conf.d/00-fcgid.conf \ + > /etc/httpd/conf.d/fcgid.conf.off \ && truncate -s 0 \ /etc/httpd/conf.d/fcgid.conf \ && sed -i \ @@ -44,9 +44,9 @@ RUN cat \ RUN sed -i \ -e 's~^description =.*$~description = "This CentOS / Apache / PHP-CGI (FastCGI) service is running in a container."~' \ ${PACKAGE_PATH}/etc/views/index.ini \ - && sed -r -i \ - -e 's~^(source /etc/httpd-bootstrap\.conf)~#\1~' \ - ${PACKAGE_PATH}/bin/php-wrapper + && rm -f \ + ${PACKAGE_PATH}/bin/php-wrapper \ + ${PACKAGE_PATH}/etc/httpd/conf.d/50-fcgid.conf # ------------------------------------------------------------------------------ # Set default environment variables used to configure the service container diff --git a/src/etc/httpd/conf.d/00-fcgid.conf b/src/etc/httpd/conf.d/00-fcgid.conf new file mode 100644 index 0000000..7a79801 --- /dev/null +++ b/src/etc/httpd/conf.d/00-fcgid.conf @@ -0,0 +1,25 @@ + + LoadModule fcgid_module modules/mod_fcgid.so + + + + AddHandler fcgid-script php + AddType text/html php + DirectoryIndex index.php + FcgidFixPathinfo 1 + FcgidIOTimeout 360 + FcgidIPCDir /var/run/mod_fcgid + FcgidIdleTimeout 1800 + FcgidMaxProcesses 10 + FcgidMaxRequestLen 157286400 + FcgidMaxRequestsPerProcess 10000 + FcgidPassHeader Authorization + FcgidProcessTableFile /var/run/mod_fcgid/fcgid_shm + + + FcgidWrapper "/var/www/cgi-bin/php-wrapper --tmp=${APACHE_CONTENT_ROOT}/var/tmp" .php + + Options +ExecCGI + + + diff --git a/src/var/www/cgi-bin/php-wrapper b/src/var/www/cgi-bin/php-wrapper new file mode 100755 index 0000000..7c78ed7 --- /dev/null +++ b/src/var/www/cgi-bin/php-wrapper @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +function main () +{ + local -r bin="/usr/bin/php-cgi" + local -r nice="/bin/nice" + local -r niceness="15" + + local bin_options + local option + local -a options + local tmp="/var/tmp" + + while [[ "${#}" -gt 0 ]] + do + case "${1}" in + -d) + options+=("${2}") + shift 2 + ;; + --tmp=*) + tmp="${1#*=}" + shift 1 + ;; + esac + done + + if [[ ${#options[@]} -gt 0 ]] + then + for option in "${options[@]}" + do + bin_options+=" -d ${option}" + done + fi + + export PHP_FCGI_CHILDREN="0" + export PHP_FCGI_MAX_REQUESTS="15000" + export PHPRC="/etc" + export REDIRECT_STATUS="200" + export TMP="${tmp}" + export TEMP="${tmp}" + export TMPDIR="${tmp}" + + exec ${nice} \ + -n ${niceness} \ + ${bin} \ + ${bin_options} +} + +main "${@}" From c1e95ef17714bc5535a06069958c182a501981bc Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 18:28:45 +0100 Subject: [PATCH 09/11] #193: Updates configuration for consistency between image variants. --- Dockerfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index af92ae3..3f18956 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,14 +25,13 @@ ADD src / # ------------------------------------------------------------------------------ # Provisioning -# - Disable default fcgid configuration; replaced with 00-fcgid.conf +# - Disable Apache default fcgid configuration; replaced with 00-fcgid.conf # - Replace placeholders with values in systemd service unit template # - Set permissions # ------------------------------------------------------------------------------ -RUN cat \ +RUN truncate -s 0 \ /etc/httpd/conf.d/fcgid.conf \ - > /etc/httpd/conf.d/fcgid.conf.off \ - && truncate -s 0 \ + && chmod 444 \ /etc/httpd/conf.d/fcgid.conf \ && sed -i \ -e "s~{{RELEASE_VERSION}}~${RELEASE_VERSION}~g" \ From 12e3c47e552ffa5450c4a51cb82bd8681ce46da2 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 18:33:23 +0100 Subject: [PATCH 10/11] #207: Removes unused environment variable from README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c31ffc..b7de107 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ $ docker stop apache-php.1 && \ There are environmental variables available which allows the operator to customise the running container. -##### ENABLE_HTTPD_BOOTSTRAP, ENABLE_HTTPD_WRAPPER & ENABLE_PHP_FPM_WRAPPER +##### ENABLE_HTTPD_BOOTSTRAP & ENABLE_HTTPD_WRAPPER It may be desirable to prevent the startup of the `httpd-bootstrap` and/or `httpd-wrapper` scripts. For example, when using an image built from this Dockerfile as the source for another Dockerfile you could disable services from startup by setting `ENABLE_HTTPD_WRAPPER` to `false`. The benefit of this is to reduce the number of running processes in the final container. Another use for this would be to make use of the packages installed in the image such as `ab`, `curl`, `elinks`, `php-cli` etc. From a0a2f045d506d1bcc5f5d45728a40f19665f979f Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 20 Jul 2019 18:43:29 +0100 Subject: [PATCH 11/11] Release changes for 1.13.0 and 2.2.0. --- CHANGELOG.md | 2 +- Dockerfile | 2 +- README.md | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c02aae6..aad3a9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Summary of release changes. -### 1.13.0 - Unreleased +### 1.13.0 - 2019-07-20 - Updates image source to [1.13.0](https://github.com/jdeathe/centos-ssh-apache-php/releases/tag/1.13.0). - Updates description in `centos-ssh-apache-php-fcgi.register@.service`. diff --git a/Dockerfile b/Dockerfile index 3f18956..184cad6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM jdeathe/centos-ssh-apache-php:1.13.0 -ARG RELEASE_VERSION="1.12.0" +ARG RELEASE_VERSION="1.13.0" # ------------------------------------------------------------------------------ # Base install of required packages diff --git a/README.md b/README.md index b7de107..ad03640 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ### Tags and respective `Dockerfile` links -- `centos-7`, `2.1.0` [(centos-7/Dockerfile)](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-7/Dockerfile) -- `centos-6`, `1.12.0` [(centos-6/Dockerfile)](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-6/Dockerfile) +- `centos-7`, `2.2.0` [(centos-7/Dockerfile)](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-7/Dockerfile) +- `centos-6`, `1.13.0` [(centos-6/Dockerfile)](https://github.com/jdeathe/centos-ssh-apache-php-fcgi/blob/centos-6/Dockerfile) ## Overview @@ -25,7 +25,7 @@ $ docker run -d \ --name apache-php.1 \ -p 8080:80 \ -e "APACHE_SERVER_NAME=app-1.local" \ - jdeathe/centos-ssh-apache-php-fcgi:2.1.0 + jdeathe/centos-ssh-apache-php-fcgi:2.2.0 ``` Go to `http://{{docker-host}}:8080` using a browser where `{{docker-host}}` is the host name of your docker server and, if all went well, you should see the "Hello, world!" page. @@ -90,7 +90,7 @@ $ docker stop apache-php.1 && \ --env "APACHE_SERVER_NAME=app-1.local" \ --env "APACHE_SSL_PROTOCOL=All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1" \ --env "PHP_OPTIONS_DATE_TIMEZONE=Europe/London" \ - jdeathe/centos-ssh-apache-php-fcgi:2.1.0 + jdeathe/centos-ssh-apache-php-fcgi:2.2.0 ``` #### Environment Variables @@ -204,7 +204,7 @@ $ docker stop apache-php.1 && \ --env "APACHE_SERVER_ALIAS=app-1" \ --env "APACHE_SERVER_NAME=app-1.local" \ --env "APACHE_MOD_SSL_ENABLED=true" \ - jdeathe/centos-ssh-apache-php-fcgi:2.1.0 + jdeathe/centos-ssh-apache-php-fcgi:2.2.0 ``` ##### APACHE_MPM