feat(init): first commit
This commit is contained in:
parent
1ee84e57a5
commit
b13a5e892f
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@ -0,0 +1,4 @@
|
||||
/tmp
|
||||
/tools
|
||||
/.trivy
|
||||
/docs
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/tmp
|
||||
/tools
|
||||
/.trivy
|
41
Makefile
Normal file
41
Makefile
Normal file
@ -0,0 +1,41 @@
|
||||
IMAGE_NAME := reg.cadoles.com/cadoles/sp
|
||||
DOCKERFILE ?=
|
||||
|
||||
DAY_SUFFIX_TAG ?= $(shell date +%Y%m%d)
|
||||
|
||||
build:
|
||||
|
||||
_build:
|
||||
docker \
|
||||
build \
|
||||
-t "$(IMAGE_NAME):$(IMAGE_TAG)" \
|
||||
-f $(DOCKERFILE) \
|
||||
.
|
||||
|
||||
scan:
|
||||
|
||||
_scan: tools/trivy/bin/trivy
|
||||
mkdir -p .trivy/$(IMAGE_NAME)/$(IMAGE_TAG)
|
||||
tools/trivy/bin/trivy --cache-dir .trivy/.cache image -o ".trivy/$(IMAGE_NAME)/$(IMAGE_TAG)/report.txt" $(TRIVY_ARGS) $(IMAGE_NAME):$(IMAGE_TAG)
|
||||
cat ".trivy/$(IMAGE_NAME)/$(IMAGE_TAG)/report.txt"
|
||||
|
||||
tools/trivy/bin/trivy:
|
||||
mkdir -p tools/trivy/bin
|
||||
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b ./tools/trivy/bin v0.27.1
|
||||
|
||||
|
||||
release:
|
||||
|
||||
_release:
|
||||
docker tag $(IMAGE_NAME):$(IMAGE_TAG) $(IMAGE_NAME):$(IMAGE_TAG)-$(DAY_SUFFIX_TAG)
|
||||
docker push $(IMAGE_NAME):$(IMAGE_TAG)-$(DAY_SUFFIX_TAG)
|
||||
docker push $(IMAGE_NAME):$(IMAGE_TAG)
|
||||
|
||||
_test: tools/bin/bash_unit
|
||||
tools/bin/bash_unit ./tests/test_$(IMAGE_TAG).sh
|
||||
|
||||
tools/bin/bash_unit:
|
||||
mkdir -p tools/bin
|
||||
cd tools/bin && bash <(curl -s https://raw.githubusercontent.com/pgrange/bash_unit/master/install.sh)
|
||||
|
||||
include recipes/*.mk
|
20
README.md
20
README.md
@ -1,3 +1,19 @@
|
||||
# sp-containers
|
||||
=======
|
||||
# Shibboleth and OIDC ServiceProvider containers based on "apache".
|
||||
|
||||
Shibboleth and OIDC ServiceProvider containers based on "apache".
|
||||
Recettes de construction d'image de conteneurs Symfony prêts à l'emploi pour le développement ou la production.
|
||||
|
||||
Inspiré de [`sherifabdlnaby/kubephp`](https://github.com/sherifabdlnaby/kubephp)
|
||||
|
||||
## Liste des images
|
||||
|
||||
|Image|Description|
|
||||
|-----|-----------|
|
||||
|`reg.cadoles.com/cadoles/sp:alpine-oidc-base`|Alpine 3.18, Apache 2.4, mod-auth-oidc|
|
||||
|`reg.cadoles.com/cadoles/sp:debian-shib-base`|Debian 11.7, Aapache 2.4, shibboleth-sp 3.2.2, php 7.4, php-fpm |
|
||||
|
||||
[Accéder au dépôt](https://reg.cadoles.com/harbor/projects/5/repositories/sp/artifacts-tab)
|
||||
## Documentation
|
||||
|
||||
[Voir la documentation](./docs/README.md)
|
||||
>>>>>>> c2e23db (feat(init): first commit)
|
||||
|
13
docs/README.md
Normal file
13
docs/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Documentation
|
||||
|
||||
## Tutoriels
|
||||
|
||||
- [Créer une image pour votre projet Symfony](./docker-usage.md)
|
||||
- [Utilisation avec Kubernetes](./kubernetes-usage.md)
|
||||
- [Créer une application avec docker-compose](./starting-with-docker-compose.md)
|
||||
|
||||
## Comment faire pour ... ?
|
||||
|
||||
- [Installer des paquets supplémentaires](./additional-packages.md)
|
||||
- [Contextualiser la configuration](./configuration-contextualization.md)
|
||||
- [Utiliser une version spécifique de NodeJS](./customize_nodejs_version.md)
|
12
docs/additional-packages.md
Normal file
12
docs/additional-packages.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Installer des paquets supplémentaires
|
||||
|
||||
Vous pouvez spécifier des paquets supplémentaires (par exemple des dépendances PHP) en ajoutant l'argument de construction `ADDITIONAL_PACKAGES`.
|
||||
|
||||
**Exemple**
|
||||
|
||||
```
|
||||
docker build \
|
||||
-t my-symfony-app:latest \
|
||||
--build-arg "ADDITIONAL_PACKAGES=vim=9.0.0999-r0 curl=7.87.0-r0" \
|
||||
.
|
||||
```
|
19
docs/configuration-contextualization.md
Normal file
19
docs/configuration-contextualization.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Contextualisation la configuration
|
||||
|
||||
Les images intègrent l'utilitaire [`gomplate`](https://docs.gomplate.ca/) par défaut.
|
||||
|
||||
Ce dernier est utilisé au démarrage du conteneur afin de compléter les fichiers prévus à cet effet avec les données de contexte. Cette opération est réalisée par le script [`files/common/scripts/run.sh`](../files/common/scripts/run.sh).
|
||||
|
||||
Le principe général est le suivant:
|
||||
|
||||
1. Au démarrage du conteneur:
|
||||
1. Trouver tous les fichiers de l'arborescence correspondant dont le nom termine par `<CHEMIN>/<NOM_FICHIER>.<EXT>.gotmpl`
|
||||
2. Générer le fichier `<CHEMIN>/<NOM_FICHIER>.<EXT>` via `gomplate`
|
||||
|
||||
> Par exemple, le fichier `/etc/nginx/nginx.conf.gotmpl` sera automatiquement transformé en `/etc/nginx/nginx.conf` au démarrage du conteneur.
|
||||
|
||||
Cette opération s'appliquent également aux fichiers ajoutés par les images étendant les images de base, ainsi que dans les volumes.
|
||||
|
||||
Une grande partie des fichiers de configuration par défaut des images sont prévus pour être compatibles avec ce mécanisme. Vous pouvez donc personnaliser une partie de leurs attributs via des variables d'environnement.
|
||||
|
||||
> [Voir par exemple le fichier `files/common/nginx/nginx.conf.gotmpl`](../files/common/nginx/nginx.conf.gotmpl).
|
9
docs/customize-nodejs-version.md
Normal file
9
docs/customize-nodejs-version.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Utiliser une version spécifique de NodeJS
|
||||
|
||||
Les images intègrent l'outil [nvm](https://github.com/nvm-sh/nvm) par défaut. Cet outil permet d'installer une version spécifique de NodeJS.
|
||||
|
||||
Pour personnaliser la version de NodeJS installée dans l'image de votre conteneur, créez un fichier `.nvmrc` à la racine de votre projet Symfony contenant la version de NodeJS souhaitée (par exemple: `lts/hydrogen` ou `v18.13.0`).
|
||||
|
||||
La liste des versions disponibles est visible via la commande `nvm ls-remote`.
|
||||
|
||||
(Plus d'informations sur le site du projet NVM](https://github.com/nvm-sh/nvm#nvmrc)
|
102
docs/docker-usage.md
Normal file
102
docs/docker-usage.md
Normal file
@ -0,0 +1,102 @@
|
||||
# Créer une image Docker pour votre projet Symfony
|
||||
|
||||
> ⚠ La procédure suivante s'applique dans le cadre d'un déploiement sur Docker.
|
||||
>
|
||||
> Pour créer une image à destination d'un environnement Kubernetes, préférer
|
||||
> la procédure ["Usage dans Kubernetes"](./kubernetes-usage.md)
|
||||
|
||||
## Création d'une image
|
||||
|
||||
1. Dans le répertoire de votre projet, créer le fichier `Dockerfile` suivant:
|
||||
|
||||
```Dockerfile
|
||||
ARG ADDITIONAL_PACKAGES="<packages_list>"
|
||||
|
||||
FROM reg.cadoles.com/cadoles/symfony:alpine-php-8.1-standalone
|
||||
```
|
||||
|
||||
> La variable d'environnement `ADDITIONAL_PACKAGES` permet de définir une liste de paquets supplémentaires à installer avant d'exécuter les "triggers" de base embaqrués par l'image. Voir ["Installer des paquets supplémentaires"](./additional-packages.md) pour plus d'information.
|
||||
|
||||
2. Créer le fichier `.dockerignore` avec les données suivantes:
|
||||
|
||||
```text
|
||||
/vendor
|
||||
/var
|
||||
```
|
||||
|
||||
3. Construire l'image de votre application
|
||||
|
||||
```sh
|
||||
docker build \
|
||||
-t my-symfony-app:latest \
|
||||
.
|
||||
```
|
||||
|
||||
4. Exécuter l'image de votre application
|
||||
|
||||
```sh
|
||||
docker run \
|
||||
-it \
|
||||
--rm \
|
||||
-p 8080:8080 \
|
||||
my-symfony-app:latest
|
||||
```
|
||||
|
||||
5. Ouvrir l'URL http://localhost:8080. Votre application devrait s'afficher.
|
||||
|
||||
## Utilisation de votre image en développement
|
||||
|
||||
1. **Avec docker**:
|
||||
|
||||
```sh
|
||||
docker run \
|
||||
-it --rm \
|
||||
-p 8080:8080 \
|
||||
-v "${PWD}/src:/app/src:delegated" \
|
||||
-v "${PWD}/templates:/app/templates:delegated" \
|
||||
-v "${PWD}/translations:/app/translations:delegated" \
|
||||
-v "${PWD}/tests:/app/tests:delegated" \
|
||||
-v "${PWD}/config:/app/config:delegated" \
|
||||
-v "${PWD}/.env:/app/.env:delegated" \
|
||||
test-symfony-app
|
||||
```
|
||||
|
||||
2. **Avec docker-compose**:
|
||||
1. Créer un fichier `Dockerfile.standalone` à la racine de votre projet:
|
||||
|
||||
```dockerfile
|
||||
ARG ADDITIONAL_PACKAGES=""
|
||||
|
||||
FROM reg.cadoles.com/cadoles/symfony:alpine-php-8.1-standalone
|
||||
```
|
||||
|
||||
2. Créer un fichier `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.standalone
|
||||
ports:
|
||||
- ${APP_HTTP_PORT:-8080}:8080
|
||||
volumes:
|
||||
- ./src:/app/src:delegated
|
||||
- ./templates:/app/templates:delegated
|
||||
- ./translations:/app/translations:delegated
|
||||
- ./tests:/app/tests:delegated
|
||||
- ./config:/app/config:delegated
|
||||
- ./.env:/app/.env:delegated
|
||||
environment:
|
||||
PHP_FPM_MEMORY_LIMIT: 128m
|
||||
APP_ENV: dev
|
||||
## truncated for brevity
|
||||
```
|
||||
|
||||
3. Démarrer l'environnement
|
||||
|
||||
```sh
|
||||
docker-compose up
|
||||
```
|
3
docs/kubernetes-usage.md
Normal file
3
docs/kubernetes-usage.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Utilisation avec Kubernetes
|
||||
|
||||
> `TODO`
|
115
docs/starting-with-docker-compose.md
Normal file
115
docs/starting-with-docker-compose.md
Normal file
@ -0,0 +1,115 @@
|
||||
# Créer un projet en utilisant docker-compose
|
||||
|
||||
> ⚠ La procédure suivante s'applique dans le cadre du développement d'une application
|
||||
> en utilisant l'image ["standalone"](./docker-usage.md).
|
||||
|
||||
## Création du projet symfony
|
||||
|
||||
1. **Création du projet**
|
||||
|
||||
```shell
|
||||
symfony new app --webapp [other options...]
|
||||
# voir https://symfony.com/download pour l'installation de symfony CLI
|
||||
```
|
||||
|
||||
2. **Création du ficher Dockerfile**
|
||||
A la racine du projet, créer le fichier `Dockerfile` et placer ce contenu:
|
||||
```dockerfile
|
||||
ARG ADDITIONAL_PACKAGES="php81-pdo=8.1.14-r0 php81-pdo_pgsql=8.1.14-r0"
|
||||
|
||||
FROM reg.cadoles.com/cadoles/symfony:alpine-php-8.1-standalone
|
||||
```
|
||||
**Notes**: adapter la liste des paquets additionnels à votre besoin.
|
||||
|
||||
3. **Création du fichier docker-compose**
|
||||
A la racine du projet, créer le fichier (ou remplacer celui existant)`docker-compose.yml`, supprimer le fichier `docker-compose.override.yml` et placer ce contenu:
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- ./:/app:delegated
|
||||
environment:
|
||||
PHP_FPM_MEMORY_LIMIT: 128m
|
||||
APP_ENV: dev
|
||||
DATABASE_URL: postgresql://${POSTGRES_PASSWORD:-app}:${POSTGRES_PASSWORD:-app}@db:5432/${POSTGRES_DB:-app}?serverVersion=15&chartset=utf8
|
||||
ports:
|
||||
- ${APP_HTTP_PORT:-8080}:8080
|
||||
|
||||
db:
|
||||
image: postgres:${POSTGRES_VERSION:-15}-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-app}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-app}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-app}
|
||||
volumes:
|
||||
- app-db-data:/var/lib/postgresql/data:rw
|
||||
|
||||
volumes:
|
||||
app-db-data:
|
||||
```
|
||||
4. Création du fichier `Makefile`
|
||||
A la racine du projet, créer le fichier `Makefile` et placer ce contenu:
|
||||
```make
|
||||
dc := docker-compose
|
||||
de := $(dc) exec
|
||||
dr := $(dc) run --rm
|
||||
app := $(dr) --no-deps app
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
.PHONY: help
|
||||
help: ## Affiche cette aide
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: dev
|
||||
dev: vendor/autoload.php ## Lance le serveur de développement
|
||||
$(dc) up
|
||||
|
||||
# -----------------------------------
|
||||
# Utilitaires
|
||||
# -----------------------------------
|
||||
.PHONY: php
|
||||
app: ## Se connecte au conteneur PHP
|
||||
$(app) /bin/sh
|
||||
|
||||
# -----------------------------------
|
||||
# Builds
|
||||
# -----------------------------------
|
||||
.PHONY: build
|
||||
build: ## build application image
|
||||
docker build \
|
||||
-t app-standalone:latest \
|
||||
.
|
||||
|
||||
# -----------------------------------
|
||||
# Dependencies
|
||||
# -----------------------------------
|
||||
vendor/autoload.php: composer.lock
|
||||
$(app) composer install
|
||||
touch vendor/autoload.php
|
||||
|
||||
```
|
||||
|
||||
## Démarrer l'environnement
|
||||
|
||||
```shell
|
||||
cd app/
|
||||
make
|
||||
# doit afficher la liste des commandes disponible
|
||||
make dev
|
||||
# doit démarrer l'environnement docker défini dans votre docker-compose.yml
|
||||
# l'application doit être disponible à l'adresse http://localhost:8080
|
||||
```
|
||||
|
||||
## Installer des dépendances `composer`
|
||||
|
||||
```shell
|
||||
make app
|
||||
# dans le conteneur
|
||||
composer require ....
|
||||
```
|
14
files/alpine/sp-oidc/base/Dockerfile
Normal file
14
files/alpine/sp-oidc/base/Dockerfile
Normal file
@ -0,0 +1,14 @@
|
||||
FROM reg.cadoles.com/proxy_cache/library/alpine:edge
|
||||
#FROM reg.cadoles.com/proxy_cache/library/httpd:alpine3.18
|
||||
|
||||
# Adding testing repo
|
||||
RUN echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
|
||||
|
||||
RUN apk update && apk add apache-mod-auth-openidc
|
||||
|
||||
COPY files/alpine/sp-oidc/base/conf.d/mod-auth-openidc.conf /etc/apache2/conf.d/mod-auth-openidc.conf
|
||||
COPY files/alpine/sp-oidc/base/conf.d/default-vhost.conf /etc/apache2/conf.d/default-vhost.conf
|
||||
COPY files/alpine/sp-oidc/base/scripts/httpd-foreground /usr/local/bin/
|
||||
|
||||
|
||||
CMD ["httpd-foreground"]
|
14
files/alpine/sp-oidc/base/conf.d/Dockerfile
Normal file
14
files/alpine/sp-oidc/base/conf.d/Dockerfile
Normal file
@ -0,0 +1,14 @@
|
||||
FROM reg.cadoles.com/proxy_cache/library/alpine:edge
|
||||
#FROM reg.cadoles.com/proxy_cache/library/httpd:alpine3.18
|
||||
|
||||
# Adding testing repo
|
||||
RUN echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
|
||||
|
||||
RUN apk update && apk add apache-mod-auth-openidc
|
||||
|
||||
COPY conf.d/mod-auth-openidc.conf /etc/apache2/conf.d/mod-auth-openidc.conf
|
||||
COPY conf.d/default-vhost.conf /etc/apache2/conf.d/default-vhost.conf
|
||||
COPY scripts/httpd-foreground /usr/local/bin/
|
||||
|
||||
CMD ["httpd-foreground"]
|
||||
|
29
files/alpine/sp-oidc/base/conf.d/default-vhost.conf
Normal file
29
files/alpine/sp-oidc/base/conf.d/default-vhost.conf
Normal file
@ -0,0 +1,29 @@
|
||||
<VirtualHost _default_:80>
|
||||
ServerName ${SP_SERVER_NAME}:80
|
||||
|
||||
DocumentRoot /var/www/html
|
||||
|
||||
CustomLog /proc/self/fd/1 common
|
||||
|
||||
ErrorDocument 400 /error/
|
||||
ErrorDocument 401 /error/
|
||||
ErrorDocument 403 /error/
|
||||
ErrorDocument 404 /error/
|
||||
ErrorDocument 500 /error/
|
||||
ErrorDocument 502 /error/
|
||||
ErrorDocument 503 /error/
|
||||
ErrorDocument 504 /error/
|
||||
|
||||
<FilesMatch "\.(cgi|shtml|phtml|php)$">
|
||||
SSLOptions +StdEnvVars
|
||||
</FilesMatch>
|
||||
<Directory /usr/lib/cgi-bin>
|
||||
SSLOptions +StdEnvVars
|
||||
</Directory>
|
||||
|
||||
<Location /error>
|
||||
AllowOverride All
|
||||
Options +Indexes
|
||||
Require all granted
|
||||
</Location>
|
||||
</VirtualHost>
|
14
files/alpine/sp-oidc/base/conf.d/mod-auth-openidc.conf
Normal file
14
files/alpine/sp-oidc/base/conf.d/mod-auth-openidc.conf
Normal file
@ -0,0 +1,14 @@
|
||||
LoadModule auth_openidc_module modules/mod_auth_openidc.so
|
||||
|
||||
OIDCProviderMetadataURL ${SP_OIDC_PROVIDER_METADATA_URL} #http://portal.mse.local:8000/auth/.well-known/openid-configuration
|
||||
OIDCClientID ${SP_OIDC_CLIENT_NAME} #mse
|
||||
OIDCClientSecret ${SP_OIDC_CLIENT_SERCRET} #$mse&123456$
|
||||
OIDCProviderTokenEndpointAuth client_secret_basic
|
||||
OIDCCookieSameSite On
|
||||
OIDCSessionType client-cookie
|
||||
OIDCXForwardedHeaders X-Forwarded-Host
|
||||
# OIDCRedirectURI is a vanity URL that must point to a path protected by this module but must NOT point to any content
|
||||
OIDCRedirectURI ${SP_OIDC_REDIRECT_URI} #http://portal.mse.local:8000/protected/redirect_uri
|
||||
OIDCCryptoPassphrase ${SP_OIDC_CRYPTO_PASSPHRASE} #$mse&123456$
|
||||
OIDCOAuthAcceptTokenAs header
|
||||
OIDCUnAutzAction 302 ${SP_OIDC_ERROR_URI} #http://portal.mse.local:8000/erreur?msg=mod_auth_fail
|
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Apache gets grumpy about PID files pre-existing
|
||||
rm -f /run/apache2/httpd.pid
|
||||
|
||||
exec httpd -DFOREGROUND "$@"
|
23
files/alpine/sp-oidc/base/conf.d/test_alpine-sp-oidc.sh
Normal file
23
files/alpine/sp-oidc/base/conf.d/test_alpine-sp-oidc.sh
Normal file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )";
|
||||
|
||||
source "$SCRIPT_DIR/lib.sh"
|
||||
|
||||
# Test reg.cadoles.com/cadoles/symfony:alpine-php-7.4-standalone with Symfony 4.4
|
||||
test_alpine_sp_oidc() {
|
||||
# FIXME
|
||||
|
||||
local container_name=$(run_symfony_app_container "4.4" "7.4" "alpine-php-7.4-standalone")
|
||||
local image_name=$(docker inspect -f '{{.Config.Image}}' ${container_name})
|
||||
|
||||
trap_add "docker kill ${container_name}" EXIT
|
||||
trap_add "docker rmi -f ${image_name}" EXIT
|
||||
|
||||
local app_url="http://$(docker port ${container_name} 8080/tcp)"
|
||||
|
||||
# Check that application is responding as expected
|
||||
local page_content=$(curl -s "${app_url}" | pandoc -f html -t plain)
|
||||
|
||||
assert_matches 'Welcome to Symfony 4\.4\.*' "${page_content}" "Could not find Symfony default welcome message !"
|
||||
}
|
7
files/alpine/sp-oidc/base/scripts/httpd-foreground
Normal file
7
files/alpine/sp-oidc/base/scripts/httpd-foreground
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Apache gets grumpy about PID files pre-existing
|
||||
rm -f /run/apache2/httpd.pid
|
||||
|
||||
exec httpd -DFOREGROUND "$@"
|
7
files/common/healthcheck/check-multiple.sh
Normal file
7
files/common/healthcheck/check-multiple.sh
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
for CHECK in $@; do
|
||||
/bin/sh "/usr/local/share/cadoles-symfony/healthcheck/check-${CHECK}.sh"
|
||||
done
|
5
files/common/healthcheck/check-nginx.sh
Normal file
5
files/common/healthcheck/check-nginx.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
wget --quiet --tries=1 --spider 127.0.0.1:8090/healthcheck || exit 1;
|
5
files/common/healthcheck/check-php-fpm.sh
Normal file
5
files/common/healthcheck/check-php-fpm.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
# TODO
|
89
files/common/nginx/conf.d/app.conf.gotmpl
Normal file
89
files/common/nginx/conf.d/app.conf.gotmpl
Normal file
@ -0,0 +1,89 @@
|
||||
upstream backend {
|
||||
server {{ env.Getenv "NGINX_APP_UPSTREAM_BACKEND_SERVER" "unix:/tmp/php-fpm.sock" }};
|
||||
keepalive {{ env.Getenv "NGINX_APP_UPSTREAM_BACKEND_KEEPALIVE" "40" }};
|
||||
# Must be less than php-fpm.conf:pm.max_requests
|
||||
keepalive_requests {{ env.Getenv "NGINX_APP_UPSTREAM_BACKEND_KEEPALIVE_REQUESTS" "250" }};
|
||||
keepalive_timeout {{ env.Getenv "NGINX_APP_UPSTREAM_BACKEND_KEEPALIVE_TIMEOUT" "10" }};
|
||||
}
|
||||
|
||||
server {
|
||||
listen {{ env.Getenv "NGINX_APP_SERVER_LISTEN" "8080" }} default_server;
|
||||
|
||||
server_name {{ env.Getenv "NGINX_APP_SERVER_NAME" "_" }};
|
||||
set $base /app;
|
||||
root $base{{ env.Getenv "NGINX_APP_ROOT" "/public"}};
|
||||
|
||||
# deny all dot files except .well-known
|
||||
location ~ /\.(?!well-known) {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# index.php
|
||||
index index.php;
|
||||
|
||||
|
||||
# index.php fallback
|
||||
location / {
|
||||
# try to serve file directly, fallback to index.php
|
||||
try_files $uri {{ env.Getenv "NGINX_APP_PHP_INDEX" "/index.php"}}$is_args$args;
|
||||
}
|
||||
|
||||
# Disable falling back to PHP script for the asset directories;
|
||||
location ~ ^/({{ env.Getenv "NGINX_APP_ASSETS_DIRECTORIES" "public|bundles|web"}})/ {
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# handle non-files
|
||||
location ~ {{ env.Getenv "NGINX_APP_PHP_NON_FILE_PATTERN" "^/index\\.php(/|$)" }} {
|
||||
# default fastcgi_params
|
||||
include fastcgi_params;
|
||||
|
||||
# fastcgi settings
|
||||
fastcgi_pass backend;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_buffers 8 16k;
|
||||
fastcgi_buffer_size 32k;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
|
||||
# fastcgi params
|
||||
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||
fastcgi_param PHP_ADMIN_VALUE "open_basedir=none";
|
||||
|
||||
# Prevents URIs that include the front controller. This will 404:
|
||||
# http://domain.tld/index.php/some-path
|
||||
# Remove the internal directive to allow URIs like this
|
||||
internal;
|
||||
}
|
||||
|
||||
# return 404 for all other php files not matching the front controller
|
||||
# this prevents access to other php files you don't want to be accessible.
|
||||
location ~ \.php$ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
# favicon.ico
|
||||
location = /favicon.ico {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# robots.txt
|
||||
location = /robots.txt {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# assets, media
|
||||
location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
|
||||
expires 7d;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# svg, fonts
|
||||
location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
|
||||
add_header Access-Control-Allow-Origin "*";
|
||||
expires 7d;
|
||||
access_log off;
|
||||
}
|
||||
}
|
10
files/common/nginx/conf.d/compression.conf.gotmpl
Normal file
10
files/common/nginx/conf.d/compression.conf.gotmpl
Normal file
@ -0,0 +1,10 @@
|
||||
# Compression
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 32 16k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_min_length 250;
|
||||
gzip_types image/jpeg image/bmp image/svg+xml text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon;
|
9
files/common/nginx/conf.d/healthcheck.conf.gotmpl
Normal file
9
files/common/nginx/conf.d/healthcheck.conf.gotmpl
Normal file
@ -0,0 +1,9 @@
|
||||
server {
|
||||
listen 8090;
|
||||
location /healthcheck {
|
||||
stub_status;
|
||||
access_log off;
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
}
|
||||
}
|
3
files/common/nginx/conf.d/log.conf.gotmpl
Normal file
3
files/common/nginx/conf.d/log.conf.gotmpl
Normal file
@ -0,0 +1,3 @@
|
||||
# logging
|
||||
access_log /dev/stdout;
|
||||
error_log stderr {{ env.Getenv "NGINX_ERROR_LOG_LEVEL" "warn" }};
|
3
files/common/nginx/conf.d/mime.conf.gotmpl
Normal file
3
files/common/nginx/conf.d/mime.conf.gotmpl
Normal file
@ -0,0 +1,3 @@
|
||||
# MIME
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
6
files/common/nginx/conf.d/non-root.conf.gotmpl
Normal file
6
files/common/nginx/conf.d/non-root.conf.gotmpl
Normal file
@ -0,0 +1,6 @@
|
||||
# Non Root Temp Paths
|
||||
client_body_temp_path /tmp/client_temp;
|
||||
proxy_temp_path /tmp/proxy_temp_path;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
4
files/common/nginx/conf.d/x-forward.conf.gotmpl
Normal file
4
files/common/nginx/conf.d/x-forward.conf.gotmpl
Normal file
@ -0,0 +1,4 @@
|
||||
# Replace loadbalancer IP(real-ip) with actual client IP.
|
||||
set_real_ip_from 0.0.0.0/0;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
50
files/common/nginx/nginx.conf.gotmpl
Normal file
50
files/common/nginx/nginx.conf.gotmpl
Normal file
@ -0,0 +1,50 @@
|
||||
# user www-data;
|
||||
pid /tmp/nginx.pid;
|
||||
worker_processes auto;
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
worker_connections {{ env.Getenv "NGINX_EVENTS_WORKER_CONNECTIONS" "1024" }};
|
||||
}
|
||||
|
||||
http {
|
||||
charset {{ env.Getenv "NGINX_CHARSET" "utf-8" }};
|
||||
|
||||
# copies data between one FD and other from within the kernel
|
||||
# faster than read() + write()
|
||||
sendfile {{ env.Getenv "NGINX_SENDFILE" "on" }};
|
||||
|
||||
# send headers in one piece, it is better than sending them one by one
|
||||
tcp_nopush {{ env.Getenv "NGINX_TCP_NOPUSH" "on" }};
|
||||
|
||||
# don't buffer data sent, good for small data bursts in real time
|
||||
tcp_nodelay {{ env.Getenv "NGINX_TCP_NODELAY" "on" }};
|
||||
|
||||
# allow the server to close connection on non responding client, this will free up memory
|
||||
reset_timedout_connection {{ env.Getenv "NGINX_RESET_TIMEDOUT_CONNECTION" "on" }};
|
||||
|
||||
# hide server info for security
|
||||
server_tokens {{ env.Getenv "NGINX_SERVER_TOKENS" "off" }};
|
||||
|
||||
log_not_found {{ env.Getenv "NGINX_LOG_NOT_FOUND" "off" }};
|
||||
types_hash_max_size 2048;
|
||||
|
||||
# if the request body size is more than the buffer size, then the entire (or partial)
|
||||
# request body is written into a temporary file
|
||||
client_body_buffer_size 128k;
|
||||
|
||||
# maximum body size
|
||||
client_max_body_size {{ env.Getenv "NGINX_CLIENT_MAX_BODY_SIZE" "16M" }};
|
||||
|
||||
# maximum number and size of buffers for large headers to read from client request
|
||||
large_client_header_buffers 4 256k;
|
||||
|
||||
# cache information about FDs, frequently accessed files
|
||||
open_file_cache max=200000 inactive=20s;
|
||||
open_file_cache_valid 60s;
|
||||
open_file_cache_min_uses 5;
|
||||
open_file_cache_errors off;
|
||||
|
||||
# load configs
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
10
files/common/nvm/nvm-wrapper.sh
Normal file
10
files/common/nvm/nvm-wrapper.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
export NVM_NODEJS_ORG_MIRROR=https://unofficial-builds.nodejs.org/download/release
|
||||
|
||||
NVM_DIR="$HOME/.nvm"
|
||||
source "$NVM_DIR/nvm.sh"
|
||||
|
||||
nvm_get_arch() { nvm_echo "x64-musl"; }
|
||||
|
||||
nvm $@
|
34
files/common/scripts/install-dependencies.sh
Normal file
34
files/common/scripts/install-dependencies.sh
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
main() {
|
||||
if [ "${INSTALL_DEPENDENCIES}" == "0" ]; then
|
||||
echo "Dependencies installation disabled. Doing nothing."
|
||||
exit
|
||||
fi
|
||||
|
||||
install_additional_packages
|
||||
}
|
||||
|
||||
# Return 3 for unknown distribution
|
||||
install_additional_packages() {
|
||||
if [ -z "${ADDITIONAL_PACKAGES}" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Installing additional packages '${ADDITIONAL_PACKAGES}'..."
|
||||
|
||||
if [ -f "/etc/debian_version" ]; then
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -y
|
||||
apt-get install -y ${ADDITIONAL_PACKAGES}
|
||||
elif [ -f "/etc/alpine-release" ]; then
|
||||
apk update
|
||||
apk add --no-cache ${ADDITIONAL_PACKAGES}
|
||||
else
|
||||
return 3
|
||||
fi
|
||||
}
|
||||
|
||||
main
|
24
files/common/scripts/run.sh
Normal file
24
files/common/scripts/run.sh
Normal file
@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
main() {
|
||||
echo "Generating filesystem templates..."
|
||||
generate_templates
|
||||
exec $@
|
||||
}
|
||||
|
||||
generate_templates() {
|
||||
# Find *.gotmpl files and generate associated configuration files
|
||||
local template_files=$(find / -type f -name '*.gotmpl')
|
||||
|
||||
for tmpl in $template_files; do
|
||||
local dest_file=${tmpl%".gotmpl"}
|
||||
echo "Generating file '$dest_file'..."
|
||||
gomplate -f "$tmpl" > "$dest_file"
|
||||
chmod $(stat -c '%a' "$tmpl") "$dest_file"
|
||||
chown $(stat -c '%u:%g' "$tmpl") "$dest_file"
|
||||
done
|
||||
}
|
||||
|
||||
main $@
|
27
files/debian/sp-shib/base/Dockerfile
Normal file
27
files/debian/sp-shib/base/Dockerfile
Normal file
@ -0,0 +1,27 @@
|
||||
FROM reg.cadoles.com/proxy_cache/library/debian:stable-slim
|
||||
|
||||
|
||||
RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
apt-get update -y && \
|
||||
apt-get install -y libapache2-mod-shib php-fpm
|
||||
|
||||
RUN a2enmod rewrite expires headers remoteip ssl \
|
||||
proxy proxy_fcgi proxy_http proxy_balancer \
|
||||
lbmethod_bybusyness lbmethod_byrequests lbmethod_bytraffic lbmethod_heartbeat
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
COPY files/common/healthcheck /usr/local/share/cadoles/healthcheck
|
||||
COPY files/common/scripts /usr/local/share/cadoles/scripts
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
# ========= Child image build triggers ==========
|
||||
|
||||
ONBUILD COPY . /app
|
||||
ONBUILD ARG ADDITIONAL_PACKAGES
|
||||
ONBUILD ARG INSTALL_DEPENDENCIES
|
||||
ONBUILD ARG INSTALL_COMPOSER_DEPENDENCIES
|
||||
ONBUILD ARG INSTALL_NPM_DEPENDENCIES
|
||||
ONBUILD RUN . /usr/local/share/cadoles/scripts/install-dependencies.sh
|
28
recipes/alpine-sp-oidc.mk
Normal file
28
recipes/alpine-sp-oidc.mk
Normal file
@ -0,0 +1,28 @@
|
||||
build: build-alpine-sp-oidc-base
|
||||
|
||||
build-alpine-sp-oidc-base:
|
||||
$(MAKE) \
|
||||
IMAGE_TAG=alpine-sp-oidc-base \
|
||||
DOCKERFILE=files/alpine/sp-oidc/base/Dockerfile \
|
||||
_build
|
||||
|
||||
scan: scan-alpine-sp-oidc-base
|
||||
|
||||
scan-alpine-sp-oidc-base:
|
||||
$(MAKE) \
|
||||
IMAGE_TAG=alpine-sp-oidc-base \
|
||||
_scan
|
||||
|
||||
release: release-alpine-sp-oidc-base
|
||||
|
||||
release-alpine-sp-oidc-base:
|
||||
$(MAKE) \
|
||||
IMAGE_TAG=alpine-sp-oidc-base \
|
||||
_release
|
||||
|
||||
test: test-alpine-sp-oidc-base
|
||||
|
||||
test-alpine-sp-oidc-base:
|
||||
$(MAKE) \
|
||||
IMAGE_TAG=alpine-sp-oidc-base \
|
||||
_test
|
28
recipes/debian-sp-shib.mk
Normal file
28
recipes/debian-sp-shib.mk
Normal file
@ -0,0 +1,28 @@
|
||||
build: build-debian-sp-shib-base
|
||||
|
||||
build-debian-sp-shib-base:
|
||||
$(MAKE) \
|
||||
IMAGE_TAG=debian-sp-shib-base \
|
||||
DOCKERFILE=files/debian/sp-shib/base/Dockerfile \
|
||||
_build
|
||||
|
||||
scan: scan-debian-sp-shib-base
|
||||
|
||||
scan-debian-sp-shib-base:
|
||||
$(MAKE) \
|
||||
IMAGE_TAG=debian-sp-shib-base \
|
||||
_scan
|
||||
|
||||
release: release-debian-sp-shib-base
|
||||
|
||||
release-debian-sp-shib-base:
|
||||
$(MAKE) \
|
||||
IMAGE_TAG=debian-sp-shib-base \
|
||||
_release
|
||||
|
||||
test: test-debian-sp-shib-base
|
||||
|
||||
test-debian-sp-shib-base:
|
||||
$(MAKE) \
|
||||
IMAGE_TAG=debian-sp-shib-base \
|
||||
_test
|
114
tests/lib.sh
Normal file
114
tests/lib.sh
Normal file
@ -0,0 +1,114 @@
|
||||
#!/bin/bash
|
||||
|
||||
log() { printf '%s\n' "$*"; }
|
||||
error() { log "ERROR: $*" >&2; }
|
||||
fatal() { error "$@"; exit 1; }
|
||||
|
||||
run_symfony_app_container() {
|
||||
set -e
|
||||
trap "set +e" RETURN
|
||||
|
||||
local symfony_version=${1}
|
||||
local php_version=${2}
|
||||
local image_tag=${3}
|
||||
|
||||
cd "${SCRIPT_DIR}/.."
|
||||
|
||||
# Create temporary directory
|
||||
local project_dir=$(mktemp -d)
|
||||
local run_id=$(date +%s)
|
||||
|
||||
# Defer cleanup on exit
|
||||
trap_add "rm -rf ${project_dir}" EXIT
|
||||
|
||||
# Create dummy Symfony project
|
||||
symfony new --dir="${project_dir}" --version="${symfony_version}" --php="${php_version}" --webapp 1>&2
|
||||
|
||||
cat > "${project_dir}/Dockerfile" <<EOF
|
||||
FROM reg.cadoles.com/cadoles/symfony:${image_tag}
|
||||
EOF
|
||||
|
||||
cat > "${project_dir}/.dockerignore" <<EOF
|
||||
/var
|
||||
/vendor
|
||||
EOF
|
||||
|
||||
local image_name="symfony-test-${image_tag}:${run_id}"
|
||||
|
||||
# Build Symfony project image
|
||||
docker build \
|
||||
-t "${image_name}" \
|
||||
"${project_dir}" \
|
||||
1>&2
|
||||
|
||||
local http_port=$(get_unused_port)
|
||||
local container_name="symfony-test-${image_tag}-${run_id}"
|
||||
|
||||
# Start project image
|
||||
docker run \
|
||||
-d \
|
||||
--rm \
|
||||
-p "${http_port}:8080" \
|
||||
--name "${container_name}" \
|
||||
"${image_name}" \
|
||||
1>&2
|
||||
|
||||
# Wait container is healthy with a timeout
|
||||
local duration=0
|
||||
local last_tick=$(date +%s)
|
||||
local container_status=$(docker inspect -f '{{.State.Health.Status}}' ${container_name})
|
||||
|
||||
log "Waiting for container to become healthy..." 1>&2
|
||||
until [ "${container_status}" == "healthy" ]; do
|
||||
sleep 1
|
||||
|
||||
local now=$(date +%s)
|
||||
duration=$(( ${duration} + ( ${now} - ${last_tick} ) ))
|
||||
|
||||
|
||||
if [ ${duration} -gt 60 ]; then
|
||||
fail "Container did not become healthy before timeout !"
|
||||
fi
|
||||
|
||||
last_tick=${now}
|
||||
container_status=$(docker inspect -f '{{.State.Health.Status}}' ${container_name})
|
||||
done
|
||||
|
||||
echo "${container_name}"
|
||||
}
|
||||
|
||||
get_unused_port() {
|
||||
set -e
|
||||
trap "set +e" RETURN
|
||||
|
||||
local lport=32768;
|
||||
local uport=60999;
|
||||
while true; do
|
||||
local mport=$[${lport} + (${RANDOM} % $uport)];
|
||||
(echo "" >/dev/tcp/127.0.0.1/${mport}) >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo ${mport};
|
||||
return 0;
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# From https://stackoverflow.com/a/7287873
|
||||
trap_add() {
|
||||
local trap_add_cmd=$1;
|
||||
shift || fatal "${FUNCNAME} usage error"
|
||||
for trap_add_name in "$@"; do
|
||||
trap -- "$(
|
||||
# helper fn to get existing trap command from output
|
||||
# of trap -p
|
||||
extract_trap_cmd() { printf '%s\n' "$3"; }
|
||||
# print existing trap command with newline
|
||||
eval "extract_trap_cmd $(trap -p "${trap_add_name}")"
|
||||
# print the new trap command
|
||||
printf '%s\n' "${trap_add_cmd}"
|
||||
)" "${trap_add_name}" \
|
||||
|| fatal "unable to add to trap ${trap_add_name}"
|
||||
done
|
||||
}
|
||||
|
||||
declare -f -t trap_add
|
23
tests/test_alpine-sp-oidc.sh
Normal file
23
tests/test_alpine-sp-oidc.sh
Normal file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )";
|
||||
|
||||
source "$SCRIPT_DIR/lib.sh"
|
||||
|
||||
# Test reg.cadoles.com/cadoles/symfony:alpine-php-7.4-standalone with Symfony 4.4
|
||||
test_alpine_sp_oidc() {
|
||||
# FIXME
|
||||
|
||||
local container_name=$(run_symfony_app_container "4.4" "7.4" "alpine-php-7.4-standalone")
|
||||
local image_name=$(docker inspect -f '{{.Config.Image}}' ${container_name})
|
||||
|
||||
trap_add "docker kill ${container_name}" EXIT
|
||||
trap_add "docker rmi -f ${image_name}" EXIT
|
||||
|
||||
local app_url="http://$(docker port ${container_name} 8080/tcp)"
|
||||
|
||||
# Check that application is responding as expected
|
||||
local page_content=$(curl -s "${app_url}" | pandoc -f html -t plain)
|
||||
|
||||
assert_matches 'Welcome to Symfony 4\.4\.*' "${page_content}" "Could not find Symfony default welcome message !"
|
||||
}
|
Loading…
Reference in New Issue
Block a user