PHP 8
37
.docker/.env.example
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# docker-compose env vars
|
||||||
|
# @see https://docs.docker.com/compose/reference/envvars/
|
||||||
|
COMPOSE_CONVERT_WINDOWS_PATHS=1
|
||||||
|
|
||||||
|
# application
|
||||||
|
APP_GROUP_NAME=application
|
||||||
|
|
||||||
|
# application
|
||||||
|
APP_SSH_PASSWORD=123456
|
||||||
|
|
||||||
|
# mysql
|
||||||
|
MYSQL_DATABASE=psc
|
||||||
|
MYSQL_PASSWORD=Wichtig1
|
||||||
|
MYSQL_ROOT_PASSWORD=Wichtig1
|
||||||
|
|
||||||
|
#APP_USER_NAME=application
|
||||||
|
#APP_USER_ID=10000
|
||||||
|
#APP_GROUP_ID=10001
|
||||||
|
|
||||||
|
APP_CODE_PATH_CONTAINER=/data/www
|
||||||
|
|
||||||
|
APP_CODE_PATH_HOST=../../src
|
||||||
|
APP_HOST=app.local
|
||||||
|
NETWORKS_DRIVER=bridge
|
||||||
|
|
||||||
|
NGINX_HOST_HTTP_PORT=80
|
||||||
|
NGINX_HOST_HTTPS_PORT=443
|
||||||
|
|
||||||
|
PHP_IDE_CONFIG=serverName=psc
|
||||||
|
VOLUMES_DRIVER=local
|
||||||
|
|
||||||
|
ALPINE_VERSION=3.12
|
||||||
|
COMPOSER_VERSION=2.2.5
|
||||||
|
MYSQL_VERSION=10.4.8
|
||||||
|
MONGODB_VERSION=5
|
||||||
|
NGINX_VERSION=1.21.5-alpine
|
||||||
|
PHP_VERSION=7.4
|
||||||
47
.docker/docker-compose/docker-compose-old.yml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
version: "2"
|
||||||
|
services:
|
||||||
|
mongodb:
|
||||||
|
image: mongo
|
||||||
|
ports:
|
||||||
|
- "11000:27017"
|
||||||
|
mysql:
|
||||||
|
image: registry.gitlab.com/printshopcreator/docker/docker_mysql:latest
|
||||||
|
ports:
|
||||||
|
- "11001:3306"
|
||||||
|
environment:
|
||||||
|
- MYSQL_ROOT_PASSWORD=Wichtig1
|
||||||
|
- MYSQL_DATABASE=psc
|
||||||
|
cron:
|
||||||
|
image: registry.gitlab.com/printshopcreator/docker/docker_cron:php7
|
||||||
|
environment:
|
||||||
|
- SYMFONY_DECRYPTION_SECRET=ZfzbggHk012ImxwsovgF0iLkJf7pUJlMJ+uBLNTHFxbwz0iwe7STUJhAyULlDSv9unBVXfPW3DFf/VuVw6vPCQ==%
|
||||||
|
volumes:
|
||||||
|
- .:/data/www/old
|
||||||
|
- .:/data/www/new
|
||||||
|
links:
|
||||||
|
- mysql:mysql
|
||||||
|
- mongodb:mongodb
|
||||||
|
php:
|
||||||
|
image: registry.gitlab.com/printshopcreator/docker/docker_php:php7
|
||||||
|
environment:
|
||||||
|
- ftpUsername=papedruck
|
||||||
|
- ftpPassword=27JSdjs62Jhs
|
||||||
|
- ftpHost=157.90.18.62
|
||||||
|
- ftpPort=20000
|
||||||
|
- ftpIp=157.90.18.62
|
||||||
|
- SYMFONY_DECRYPTION_SECRET=ZfzbggHk012ImxwsovgF0iLkJf7pUJlMJ+uBLNTHFxbwz0iwe7STUJhAyULlDSv9unBVXfPW3DFf/VuVw6vPCQ==%
|
||||||
|
links:
|
||||||
|
- mysql:mysql
|
||||||
|
- mongodb:mongodb
|
||||||
|
volumes:
|
||||||
|
- ./psc-source-v1:/data/www/old
|
||||||
|
- ./psc-source-v2:/data/www/new
|
||||||
|
tp:
|
||||||
|
image: registry.gitlab.com/printshopcreator/docker/docker_tp:v21x1x1
|
||||||
|
web:
|
||||||
|
image: registry.gitlab.com/printshopcreator/docker/docker_web:php7_tp
|
||||||
|
ports:
|
||||||
|
- "8001:80"
|
||||||
|
volumes:
|
||||||
|
- ./psc-source-v1:/data/www/old
|
||||||
|
- ./psc-source-v2:/data/www/new
|
||||||
19
.docker/docker-compose/docker-compose-php-base.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
version: '3.7'
|
||||||
|
|
||||||
|
services:
|
||||||
|
php-base:
|
||||||
|
image: ${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/php-base-${ENV?}:${TAG?}
|
||||||
|
build:
|
||||||
|
context: ../../
|
||||||
|
dockerfile: ./.docker/images/php/base/Dockerfile
|
||||||
|
args:
|
||||||
|
- ALPINE_VERSION=${ALPINE_VERSION?}
|
||||||
|
- APP_CODE_PATH=${APP_CODE_PATH_CONTAINER?}
|
||||||
|
- APP_GROUP_ID=${APP_GROUP_ID?}
|
||||||
|
- APP_GROUP_NAME=${APP_GROUP_NAME?}
|
||||||
|
- APP_USER_ID=${APP_USER_ID?}
|
||||||
|
- APP_USER_NAME=${APP_USER_NAME?}
|
||||||
|
- COMPOSER_VERSION=${COMPOSER_VERSION?}
|
||||||
|
- ENV=${ENV?}
|
||||||
|
- TARGET_PHP_VERSION=${PHP_VERSION?}
|
||||||
|
target: ${ENV?}
|
||||||
110
.docker/docker-compose/docker-compose.local.yml
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
version: '3.7'
|
||||||
|
|
||||||
|
networks:
|
||||||
|
network:
|
||||||
|
driver: ${NETWORKS_DRIVER?}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql:
|
||||||
|
name: mysql-${ENV?}
|
||||||
|
driver: ${VOLUMES_DRIVER?}
|
||||||
|
mongodb:
|
||||||
|
name: mongodb-${ENV?}
|
||||||
|
driver: ${VOLUMES_DRIVER?}
|
||||||
|
|
||||||
|
services:
|
||||||
|
php-fpm:
|
||||||
|
environment:
|
||||||
|
- PHP_IDE_CONFIG=${PHP_IDE_CONFIG?}
|
||||||
|
# cap_add and security_opt are required to enable strace
|
||||||
|
# @see https://stackoverflow.com/a/46676868
|
||||||
|
cap_add:
|
||||||
|
- "SYS_PTRACE"
|
||||||
|
security_opt:
|
||||||
|
- "seccomp=unconfined"
|
||||||
|
volumes:
|
||||||
|
- ${APP_CODE_PATH_HOST?}:${APP_CODE_PATH_CONTAINER?}
|
||||||
|
networks:
|
||||||
|
- network
|
||||||
|
extra_hosts:
|
||||||
|
- host.docker.internal:host-gateway
|
||||||
|
php-cron:
|
||||||
|
environment:
|
||||||
|
- PHP_IDE_CONFIG=${PHP_IDE_CONFIG?}
|
||||||
|
volumes:
|
||||||
|
- ${APP_CODE_PATH_HOST?}:${APP_CODE_PATH_CONTAINER?}
|
||||||
|
cap_add:
|
||||||
|
- "SYS_PTRACE"
|
||||||
|
security_opt:
|
||||||
|
- "seccomp=unconfined"
|
||||||
|
extra_hosts:
|
||||||
|
- host.docker.internal:host-gateway
|
||||||
|
|
||||||
|
web:
|
||||||
|
volumes:
|
||||||
|
- ${APP_CODE_PATH_HOST?}:${APP_CODE_PATH_CONTAINER?}
|
||||||
|
ports:
|
||||||
|
- "${NGINX_HOST_HTTP_PORT:-80}:80"
|
||||||
|
- "${NGINX_HOST_HTTPS_PORT:-443}:443"
|
||||||
|
networks:
|
||||||
|
network:
|
||||||
|
aliases:
|
||||||
|
- ${APP_HOST?}
|
||||||
|
depends_on:
|
||||||
|
- php-fpm
|
||||||
|
tp:
|
||||||
|
image: registry.gitlab.com/printshopcreator/docker/docker_tp:v21x1x1
|
||||||
|
networks:
|
||||||
|
- network
|
||||||
|
|
||||||
|
application:
|
||||||
|
image: ${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/application-${ENV?}:${TAG?}
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: ./images/php/application/Dockerfile
|
||||||
|
args:
|
||||||
|
- BASE_IMAGE=${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/php-base-${ENV?}:${TAG?}
|
||||||
|
- APP_SSH_PASSWORD=${APP_SSH_PASSWORD?}
|
||||||
|
- ENV=${ENV?}
|
||||||
|
environment:
|
||||||
|
- PHP_IDE_CONFIG=${PHP_IDE_CONFIG?}
|
||||||
|
# cap_add and security_opt are required to enable strace
|
||||||
|
# @see https://stackoverflow.com/a/46676868
|
||||||
|
cap_add:
|
||||||
|
- "SYS_PTRACE"
|
||||||
|
security_opt:
|
||||||
|
- "seccomp=unconfined"
|
||||||
|
volumes:
|
||||||
|
- ${APP_CODE_PATH_HOST?}:${APP_CODE_PATH_CONTAINER?}
|
||||||
|
ports:
|
||||||
|
- "${APPLICATION_SSH_HOST_PORT:-2222}:22"
|
||||||
|
tty: true
|
||||||
|
networks:
|
||||||
|
- network
|
||||||
|
extra_hosts:
|
||||||
|
- host.docker.internal:host-gateway
|
||||||
|
mongodb:
|
||||||
|
image: mongo:${MONGODB_VERSION?}
|
||||||
|
platform: linux/amd64
|
||||||
|
volumes:
|
||||||
|
- mongodb:/data/db
|
||||||
|
networks:
|
||||||
|
- network
|
||||||
|
ports:
|
||||||
|
- "${MONGODB_HOST_PORT:-27017}:27017"
|
||||||
|
mysql:
|
||||||
|
image: mariadb:${MYSQL_VERSION?}
|
||||||
|
platform: linux/amd64
|
||||||
|
environment:
|
||||||
|
- MYSQL_DATABASE=${MYSQL_DATABASE:-application_db}
|
||||||
|
- MYSQL_USER=${MYSQL_USER:-application_user}
|
||||||
|
- MYSQL_PASSWORD=${MYSQL_PASSWORD?}
|
||||||
|
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD?}
|
||||||
|
- TZ=${TIMEZONE:-UTC}
|
||||||
|
volumes:
|
||||||
|
- mysql:/var/lib/mysql
|
||||||
|
command: mysqld --sql_mode="ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" --character-set-server=utf8 --collation-server=utf8_slovenian_ci --init-connect='SET NAMES UTF8;' --innodb-flush-log-at-trx-commit=0
|
||||||
|
networks:
|
||||||
|
- network
|
||||||
|
ports:
|
||||||
|
- "${MYSQL_HOST_PORT:-3306}:3306"
|
||||||
31
.docker/docker-compose/docker-compose.yml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
version: '3.7'
|
||||||
|
|
||||||
|
services:
|
||||||
|
php-fpm:
|
||||||
|
image: ${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/php-fpm-${ENV?}:${TAG?}
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: ./images/php/fpm/Dockerfile
|
||||||
|
target: ${ENV?}
|
||||||
|
args:
|
||||||
|
- BASE_IMAGE=${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/php-base-${ENV?}:${TAG?}
|
||||||
|
- TARGET_PHP_VERSION=${PHP_VERSION?}
|
||||||
|
|
||||||
|
php-cron:
|
||||||
|
image: ${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/php-cron-${ENV?}:${TAG?}
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: ./images/php/cron/Dockerfile
|
||||||
|
target: ${ENV?}
|
||||||
|
args:
|
||||||
|
- BASE_IMAGE=${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/php-base-${ENV?}:${TAG?}
|
||||||
|
|
||||||
|
web:
|
||||||
|
image: ${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/web-${ENV?}:${TAG?}
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: ./images/nginx/Dockerfile
|
||||||
|
target: ${ENV?}
|
||||||
|
args:
|
||||||
|
- NGINX_VERSION=${NGINX_VERSION?}
|
||||||
|
- APP_CODE_PATH=${APP_CODE_PATH_CONTAINER?}
|
||||||
10
.docker/images/nginx/Dockerfile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ARG NGINX_VERSION
|
||||||
|
FROM nginx:${NGINX_VERSION} as base
|
||||||
|
|
||||||
|
COPY --chown=nginx:nginx ./images/nginx/conf.d/default.conf /etc/nginx/conf.d
|
||||||
|
|
||||||
|
ARG APP_CODE_PATH
|
||||||
|
RUN sed -i "s#__NGINX_ROOT_NEW;#$APP_CODE_PATH/new/web;#" /etc/nginx/conf.d/default.conf
|
||||||
|
RUN sed -i "s#__NGINX_ROOT_OLD;#$APP_CODE_PATH/old/public;#" /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
FROM base as local
|
||||||
103
.docker/images/nginx/conf.d/default.conf
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
server {
|
||||||
|
index index.php index.html app.php;
|
||||||
|
error_log /var/log/nginx/error.log;
|
||||||
|
access_log /var/log/nginx/access.log;
|
||||||
|
|
||||||
|
set $frontRoot __NGINX_ROOT_NEW;
|
||||||
|
set $sfApp app.php; # Change to app.php for prod
|
||||||
|
client_max_body_size 1000M;
|
||||||
|
root __NGINX_ROOT_OLD;
|
||||||
|
charset UTF-8;
|
||||||
|
location / {
|
||||||
|
|
||||||
|
client_max_body_size 1024M;
|
||||||
|
try_files $uri $uri/ @notfile;
|
||||||
|
location ~ \.php$ {
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*';
|
||||||
|
#
|
||||||
|
# Om nom nom cookies
|
||||||
|
#
|
||||||
|
add_header 'Access-Control-Allow-Credentials' 'true';
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
||||||
|
#
|
||||||
|
# Custom headers and headers various browsers *should* be OK with but aren't
|
||||||
|
#
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,apikey';
|
||||||
|
#
|
||||||
|
# Tell client that this pre-flight info is valid for 20 days
|
||||||
|
#
|
||||||
|
add_header 'Access-Control-Max-Age' 1728000;
|
||||||
|
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
||||||
|
add_header 'Content-Length' 0;
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_header Access-Control-Allow-Origin * always;
|
||||||
|
add_header Access-Control-Allow-Credentials true always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
|
||||||
|
add_header Access-Control-Expose-Headers Access-Control-Allow-Origin always;
|
||||||
|
fastcgi_temp_path /tmp/fastcgi 1 2;
|
||||||
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||||
|
fastcgi_pass php-fpm:9000;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
|
fastcgi_param SERVER_NAME $http_host;
|
||||||
|
include fastcgi_params;
|
||||||
|
fastcgi_pass_header *;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
location @notfile {
|
||||||
|
rewrite ^(.*) /index.php last;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /apps/ { # Static files
|
||||||
|
client_max_body_size 1024M;
|
||||||
|
root $frontRoot;
|
||||||
|
rewrite ^/apps/(.*)$ /$1 break;
|
||||||
|
try_files $uri @sfFront;
|
||||||
|
}
|
||||||
|
|
||||||
|
#location /w2p/ {
|
||||||
|
# proxy_pass http://tp:8080/w2p/;
|
||||||
|
# proxy_temp_path /tmp/proxy;
|
||||||
|
#}
|
||||||
|
|
||||||
|
location @sfFront { # Symfony
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*';
|
||||||
|
#
|
||||||
|
# Om nom nom cookies
|
||||||
|
#
|
||||||
|
add_header 'Access-Control-Allow-Credentials' 'true';
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
||||||
|
#
|
||||||
|
# Custom headers and headers various browsers *should* be OK with but aren't
|
||||||
|
#
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,apikey';
|
||||||
|
#
|
||||||
|
# Tell client that this pre-flight info is valid for 20 days
|
||||||
|
#
|
||||||
|
add_header 'Access-Control-Max-Age' 1728000;
|
||||||
|
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
||||||
|
add_header 'Content-Length' 0;
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_header Access-Control-Allow-Origin * always;
|
||||||
|
add_header Access-Control-Allow-Credentials true always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
|
||||||
|
add_header Access-Control-Expose-Headers Access-Control-Allow-Origin always;
|
||||||
|
fastcgi_temp_path /tmp/fastcgi 1 2;
|
||||||
|
fastcgi_pass php-fpm:9000;
|
||||||
|
include fastcgi_params;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $frontRoot/$sfApp;
|
||||||
|
fastcgi_param SCRIPT_NAME /apps/$sfApp;
|
||||||
|
fastcgi_param REQUEST_URI /apps$uri?$args;
|
||||||
|
fastcgi_param SERVER_NAME $http_host;
|
||||||
|
fastcgi_buffers 16 16k;
|
||||||
|
fastcgi_buffer_size 32k;
|
||||||
|
fastcgi_param HTTPS off;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
.docker/images/nginx/nginx.conf
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
user nginx;
|
||||||
|
worker_processes 1;
|
||||||
|
|
||||||
|
error_log /var/log/nginx/error.log warn;
|
||||||
|
pid /var/run/nginx.pid;
|
||||||
|
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
|
||||||
|
#access_log /var/log/nginx/access.log main;
|
||||||
|
|
||||||
|
sendfile off;
|
||||||
|
#tcp_nopush on;
|
||||||
|
|
||||||
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
client_body_temp_path /tmp 1 2;
|
||||||
|
client_body_buffer_size 256k;
|
||||||
|
client_body_in_file_only off;
|
||||||
|
|
||||||
|
#gzip on;
|
||||||
|
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
}
|
||||||
28
.docker/images/php/application/Dockerfile
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
ARG BASE_IMAGE
|
||||||
|
FROM ${BASE_IMAGE} as base
|
||||||
|
|
||||||
|
FROM base as prod
|
||||||
|
|
||||||
|
USER $APP_USER_NAME
|
||||||
|
|
||||||
|
FROM base as ci
|
||||||
|
|
||||||
|
USER $APP_USER_NAME
|
||||||
|
|
||||||
|
FROM base as local
|
||||||
|
|
||||||
|
#RUN apt install -y \
|
||||||
|
# openssh-server
|
||||||
|
#
|
||||||
|
#ARG APP_SSH_PASSWORD
|
||||||
|
#RUN echo "$APP_USER_NAME:$APP_SSH_PASSWORD" | chpasswd 2>&1
|
||||||
|
#
|
||||||
|
## Required to start sshd, otherwise the container will error out on startup with the message
|
||||||
|
## "sshd: no hostkeys available -- exiting."
|
||||||
|
## @see https://stackoverflow.com/a/65348102/413531
|
||||||
|
#RUN ssh-keygen -A
|
||||||
|
#
|
||||||
|
## we use SSH deployment configuration in PhpStorm for local development
|
||||||
|
#EXPOSE 22
|
||||||
|
#
|
||||||
|
#CMD ["/usr/sbin/sshd", "-D"]
|
||||||
9
.docker/images/php/base/.bashrc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export PS1='$(whoami):$(pwd)# '
|
||||||
|
alias ll='ls -l'
|
||||||
|
alias lc='ls --color=auto'
|
||||||
|
|
||||||
|
# see https://stackoverflow.com/questions/4188324/bash-completion-of-makefile-target
|
||||||
|
# -h to grep to hide filenames
|
||||||
|
# -s to grep to hide error messages
|
||||||
|
# include Makefile and .make directory
|
||||||
|
complete -W "\`grep -shoE '^[a-zA-Z0-9_.-]+:([^=]|$)' ?akefile .make/*.mk | sed 's/[^a-zA-Z0-9_.-]*$//' | grep -v PHONY\`" make
|
||||||
227
.docker/images/php/base/Dockerfile
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
ARG COMPOSER_VERSION
|
||||||
|
ARG TARGET_PHP_VERSION
|
||||||
|
FROM composer:${COMPOSER_VERSION} as composer
|
||||||
|
FROM php:${TARGET_PHP_VERSION}-fpm as base
|
||||||
|
|
||||||
|
# make build args available as ENV variables to downstream images
|
||||||
|
# so that we don't have to pass the same build args again
|
||||||
|
ARG APP_USER_ID
|
||||||
|
ARG APP_GROUP_ID
|
||||||
|
ARG APP_USER_NAME
|
||||||
|
ARG APP_GROUP_NAME
|
||||||
|
ARG APP_CODE_PATH
|
||||||
|
|
||||||
|
ARG ENV
|
||||||
|
ENV APP_USER_ID=${APP_USER_ID}
|
||||||
|
ENV APP_GROUP_ID=${APP_GROUP_ID}
|
||||||
|
ENV APP_USER_NAME=${APP_USER_NAME}
|
||||||
|
ENV APP_GROUP_NAME=${APP_GROUP_NAME}
|
||||||
|
ENV APP_CODE_PATH=${APP_CODE_PATH}
|
||||||
|
ENV TARGET_PHP_VERSION=${TARGET_PHP_VERSION}
|
||||||
|
|
||||||
|
ENV ENV=${ENV}
|
||||||
|
|
||||||
|
RUN addgroup -gid $APP_GROUP_ID $APP_GROUP_NAME && \
|
||||||
|
adduser --disabled-password --uid $APP_USER_ID --shell /bin/bash --ingroup $APP_GROUP_NAME $APP_USER_NAME && \
|
||||||
|
mkdir -p $APP_CODE_PATH && \
|
||||||
|
chown $APP_USER_NAME: $APP_CODE_PATH
|
||||||
|
|
||||||
|
# install git-secret
|
||||||
|
# @see https://git-secret.io/installation#alpine
|
||||||
|
ADD https://gitsecret.jfrog.io/artifactory/api/security/keypair/public/repositories/git-secret-apk /etc/apk/keys/git-secret-apk.rsa.pub
|
||||||
|
|
||||||
|
# FYI, we are NOT using a cache mount to store the apk cache via
|
||||||
|
# RUN --mount=type=cache,target=/var/cache/apk ln -vs /var/cache/apk /etc/apk/cache && \
|
||||||
|
# @see https://github.com/FernandoMiguel/BuildKit#new-dockerfile
|
||||||
|
# @see https://wiki.alpinelinux.org/wiki/Local_APK_cache#Enabling_Local_Cache_on_HDD_installs
|
||||||
|
# because we run --update anyways to get the latest files
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y \
|
||||||
|
bash \
|
||||||
|
git \
|
||||||
|
git-secret \
|
||||||
|
# required for git-secret
|
||||||
|
gawk \
|
||||||
|
gnupg \
|
||||||
|
make \
|
||||||
|
strace \
|
||||||
|
sudo \
|
||||||
|
vim
|
||||||
|
|
||||||
|
|
||||||
|
# Install intl
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
libicu-dev \
|
||||||
|
libssl-dev \
|
||||||
|
libcurl4-openssl-dev \
|
||||||
|
libfreetype6-dev \
|
||||||
|
libjpeg62-turbo-dev \
|
||||||
|
libpng-dev \
|
||||||
|
libxml2-dev \
|
||||||
|
libmagickwand-dev \
|
||||||
|
git \
|
||||||
|
zlib1g-dev \
|
||||||
|
unzip \
|
||||||
|
libzip-dev \
|
||||||
|
mupdf-tools \
|
||||||
|
imagemagick \
|
||||||
|
libmcrypt-dev
|
||||||
|
|
||||||
|
# Install fileinfo
|
||||||
|
RUN docker-php-ext-install -j$(nproc) fileinfo
|
||||||
|
# Install intl
|
||||||
|
RUN docker-php-ext-install -j$(nproc) intl
|
||||||
|
# Install mongodb
|
||||||
|
RUN pecl install mongodb \
|
||||||
|
&& docker-php-ext-enable mongodb
|
||||||
|
# Install mcrypt
|
||||||
|
RUN pecl install mcrypt \
|
||||||
|
&& docker-php-ext-enable mcrypt
|
||||||
|
# Install curl
|
||||||
|
RUN docker-php-ext-install -j$(nproc) curl
|
||||||
|
# Install Zip
|
||||||
|
RUN docker-php-ext-install zip
|
||||||
|
# Install gd
|
||||||
|
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||||
|
&& docker-php-ext-install -j$(nproc) gd
|
||||||
|
# Install soap
|
||||||
|
RUN docker-php-ext-install -j$(nproc) soap
|
||||||
|
# Install imagick
|
||||||
|
RUN pecl install imagick \
|
||||||
|
&& docker-php-ext-enable imagick
|
||||||
|
# Install mysql
|
||||||
|
RUN docker-php-ext-install -j$(nproc) pdo_mysql
|
||||||
|
# Install opcache
|
||||||
|
RUN docker-php-ext-install -j$(nproc) opcache
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
libc-client-dev libkrb5-dev libldap2-dev && \
|
||||||
|
rm -r /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install ldap
|
||||||
|
RUN docker-php-ext-install -j$(nproc) ldap
|
||||||
|
|
||||||
|
RUN docker-php-ext-configure imap --with-kerberos --with-imap-ssl && \
|
||||||
|
docker-php-ext-install -j$(nproc) imap
|
||||||
|
|
||||||
|
# make bash default shell
|
||||||
|
RUN sed -e 's;/bin/ash$;/bin/bash;g' -i /etc/passwd
|
||||||
|
|
||||||
|
COPY ./.docker/images/php/base/conf.d/zz-app.ini $PHP_INI_DIR/conf.d/zz-app.ini
|
||||||
|
COPY ./.docker/images/php/base/conf.d/zz-app-${ENV}.ini $PHP_INI_DIR/conf.d/zz-ppp-${ENV}.ini
|
||||||
|
|
||||||
|
COPY ./.docker/images/php/base/.bashrc /home/${APP_USER_NAME}/.bashrc
|
||||||
|
COPY ./.docker/images/php/base/.bashrc /root/.bashrc
|
||||||
|
|
||||||
|
COPY --from=composer /usr/bin/composer /usr/local/bin/composer
|
||||||
|
|
||||||
|
# Fix git permission issue:
|
||||||
|
# `git` introduced a security feature to throw an error if the parent directory
|
||||||
|
# of the `.git` directory is owned by another user.
|
||||||
|
# @see https://github.blog/2022-04-12-git-security-vulnerability-announced/
|
||||||
|
# @see https://github.com/actions/checkout/issues/760
|
||||||
|
#
|
||||||
|
# Since we might not have full control over the owner
|
||||||
|
# ( see e.g. https://github.com/docker/for-win/issues/12742 )
|
||||||
|
# we will add the $APP_CODE_PATH as a "safe" directory to the global git config via
|
||||||
|
# git config --system --add safe.directory "/path/to/git/parent/folder"
|
||||||
|
# @see https://git-scm.com/docs/git-config/2.36.0#Documentation/git-config.txt-safedirectory
|
||||||
|
#
|
||||||
|
# Without this fix, git-secret will emit the error
|
||||||
|
# git-secret: abort: not in dir with git repo. Use 'git init' or 'git clone', then in repo use 'git secret init'
|
||||||
|
RUN git config --system --add safe.directory "$APP_CODE_PATH"
|
||||||
|
|
||||||
|
WORKDIR $APP_CODE_PATH
|
||||||
|
|
||||||
|
FROM base as codebase
|
||||||
|
|
||||||
|
# By only copying the composer files required to run composer install
|
||||||
|
# the layer will be cached and only invalidated when the composer dependencies are changed
|
||||||
|
COPY ./new/composer.json /dependencies/new/
|
||||||
|
COPY ./new/composer.lock /dependencies/new/
|
||||||
|
|
||||||
|
# use a cache mount to cache the composer dependencies
|
||||||
|
# this is essentially a cache that lives in Docker BuildKit (i.e. has nothing to do with the host system)
|
||||||
|
RUN --mount=type=cache,target=/tmp/.composer \
|
||||||
|
cd /dependencies/new && \
|
||||||
|
# COMPOSER_HOME=/tmp/.composer sets the home directory of composer that
|
||||||
|
# also controls where composer looks for the cache
|
||||||
|
# so we don't have to download dependencies again (if they are cached)
|
||||||
|
# @see https://stackoverflow.com/a/60518444 for the correct if-then-else syntax:
|
||||||
|
# - end all commands with ; \
|
||||||
|
# - except THEN and ELSE
|
||||||
|
if [ "$ENV" == "prod" ] ; \
|
||||||
|
then \
|
||||||
|
# on production, we don't want test dependencies
|
||||||
|
COMPOSER_HOME=/tmp/.composer composer install --no-scripts --no-plugins --no-progress -o --no-dev; \
|
||||||
|
else \
|
||||||
|
COMPOSER_HOME=/tmp/.composer composer install --no-scripts --no-plugins --no-progress -o; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# copy the full codebase
|
||||||
|
COPY . /codebase
|
||||||
|
|
||||||
|
# move the dependencies
|
||||||
|
RUN mv /dependencies/vendor /codebase/new/vendor
|
||||||
|
|
||||||
|
# remove files we don't require in the image to keep the image size small
|
||||||
|
RUN cd /codebase && \
|
||||||
|
rm -rf .docker/ .build/ .infrastructure/ && \
|
||||||
|
if [ "$ENV" == "prod" ] ; \
|
||||||
|
then \
|
||||||
|
# on production, we don't want tests
|
||||||
|
rm -rf tests/; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove all secrets that are NOT required for the given ENV:
|
||||||
|
# `find /codebase/.secrets -type f -print` lists all files in the .secrets directory
|
||||||
|
# `grep -v "/\(shared\|$ENV\)/"` matches only the files that are NOT in the shared/ or $ENV/ (e.g. prod/) directories
|
||||||
|
# `grep -v ".secret\$"` ensures that we remove all files that are NOT ending in .secret
|
||||||
|
# FYI:
|
||||||
|
# the "$" has to be escaped with a "\"
|
||||||
|
# "Escaping is possible by adding a \ before the variable"
|
||||||
|
# @see https://docs.docker.com/engine/reference/builder/#environment-replacement
|
||||||
|
# `xargs rm -f` retrieves the remaining file and deletes them
|
||||||
|
# FYI:
|
||||||
|
# `xargs` is necessary to convert the stdin to args for `rm`
|
||||||
|
# @see https://stackoverflow.com/a/20307392/413531
|
||||||
|
# the `-f` flag is required so that `rm` doesn't fail if no files are matched
|
||||||
|
RUN find /codebase/.secrets -type f -print | grep -v "/\(shared\|$ENV\)/" | xargs rm -f && \
|
||||||
|
find /codebase/.secrets -type f -print | grep -v ".secret\$" | xargs rm -f && \
|
||||||
|
# list the remaining files for debugging purposes
|
||||||
|
find /codebase/.secrets -type f -print
|
||||||
|
|
||||||
|
# We need a git repository for git-secret to work (can be an empty one)
|
||||||
|
RUN cd /codebase && \
|
||||||
|
git init
|
||||||
|
|
||||||
|
FROM base as prod
|
||||||
|
|
||||||
|
# We will use a custom ENTRYPOINT to decrypt the secrets when the container starts.
|
||||||
|
# This way, we can store the secrets in their encrypted form directly in the image.
|
||||||
|
# Note: Because we defined a custom ENTRYPOINT, the default CMD of the base image
|
||||||
|
# will be overriden. Thus, we must explicitly re-define it here via `CMD ["/bin/sh"]`.
|
||||||
|
# This behavior is described in the docs as:
|
||||||
|
# "If CMD is defined from the base image, setting ENTRYPOINT will reset CMD to an empty value. In this scenario, CMD must be defined in the current image to have a value."
|
||||||
|
# @see https://docs.docker.com/engine/reference/builder/#understand-how-cmd-and-entrypoint-interact
|
||||||
|
COPY ./.docker/images/php/base/decrypt-secrets.sh /decrypt-secrets.sh
|
||||||
|
RUN chmod +x /decrypt-secrets.sh
|
||||||
|
CMD ["/bin/sh"]
|
||||||
|
ENTRYPOINT ["/decrypt-secrets.sh"]
|
||||||
|
|
||||||
|
COPY --from=codebase --chown=$APP_USER_NAME:$APP_GROUP_NAME /codebase $APP_CODE_PATH
|
||||||
|
|
||||||
|
COPY --chown=$APP_USER_NAME:$APP_GROUP_NAME ./.build/build-info $APP_CODE_PATH/build-info
|
||||||
|
|
||||||
|
FROM base as ci
|
||||||
|
|
||||||
|
COPY --from=codebase --chown=$APP_USER_NAME:$APP_GROUP_NAME /codebase $APP_CODE_PATH
|
||||||
|
|
||||||
|
FROM base as local
|
||||||
|
|
||||||
|
# add app user to sudoers
|
||||||
|
# see https://ostechnix.com/add-delete-and-grant-sudo-privileges-to-users-in-alpine-linux/ for adding sudo
|
||||||
|
# see https://askubuntu.com/a/340669 for not requiring a sudo pw
|
||||||
|
RUN echo "root ALL=(ALL) NOPASSWD: ALL " | tee -a "/etc/sudoers.d/users" && \
|
||||||
|
echo "${APP_USER_NAME} ALL=(ALL) NOPASSWD: ALL " | tee -a "/etc/sudoers.d/users"
|
||||||
|
|
||||||
|
RUN pecl install xdebug
|
||||||
6
.docker/images/php/base/conf.d/zz-app-ci.ini
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
opcache.validate_timestamps = "1"
|
||||||
|
; "disable" (recheck on every request) on dev
|
||||||
|
opcache.revalidate_freq = "0"
|
||||||
|
; enable assert() statements for development
|
||||||
|
assert.exception = 1
|
||||||
|
zend.assertions = 1
|
||||||
15
.docker/images/php/base/conf.d/zz-app-local.ini
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
opcache.validate_timestamps = "1"
|
||||||
|
; "disable" (recheck on every request) on dev
|
||||||
|
opcache.revalidate_freq = "0"
|
||||||
|
opcache.enable = off
|
||||||
|
; enable assert() statements for development
|
||||||
|
assert.exception = 1
|
||||||
|
zend.assertions = 1
|
||||||
|
|
||||||
|
; Note:
|
||||||
|
display_error=1
|
||||||
|
error_reporting=E_ALL
|
||||||
|
zend_extension=xdebug
|
||||||
|
xdebug.client_host=host.docker.internal
|
||||||
|
xdebug.start_with_request=yes
|
||||||
|
xdebug.mode=develop,debug
|
||||||
6
.docker/images/php/base/conf.d/zz-app-prod.ini
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
opcache.validate_timestamps = "1"
|
||||||
|
; "disable" (recheck on every request) on dev
|
||||||
|
opcache.revalidate_freq = "0"
|
||||||
|
; enable assert() statements for development
|
||||||
|
assert.exception = 1
|
||||||
|
zend.assertions = 1
|
||||||
13
.docker/images/php/base/conf.d/zz-app.ini
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
; https://www.scalingphpbook.com/blog/2014/02/14/best-zend-opcache-settings.html
|
||||||
|
opcache.enable_cli = 1
|
||||||
|
opcache.enable = 1
|
||||||
|
opcache.fast_shutdown = 1
|
||||||
|
; check with find . -type f -print | grep php | wc -l
|
||||||
|
opcache.max_accelerated_files = 25000
|
||||||
|
opcache.validate_timestamps = 0
|
||||||
|
opcache.memory_consumption=64
|
||||||
|
opcache.interned_strings_buffer=12
|
||||||
|
|
||||||
|
memory_limit = -1
|
||||||
|
|
||||||
|
disable_functions =
|
||||||
20
.docker/images/php/base/decrypt-secrets.sh
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# exit immediately on error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# initialize make
|
||||||
|
make make-init ENVS="ENV=prod GPG_PASSWORD=$GPG_PASSWORD"
|
||||||
|
|
||||||
|
# read the secret gpg key
|
||||||
|
make gpg-init
|
||||||
|
|
||||||
|
# Only decrypt files required for production
|
||||||
|
files=$(make secret-list | grep "/\(shared\|prod\)/" | tr '\n' ' ')
|
||||||
|
make secret-decrypt-with-password FILES="$files"
|
||||||
|
|
||||||
|
cp .secrets/prod/app.env .env
|
||||||
|
|
||||||
|
# treat this script as a "decorator" and execute any other command after running it
|
||||||
|
# @see https://www.pascallandau.com/blog/structuring-the-docker-setup-for-php-projects/#using-entrypoint-for-pre-run-configuration
|
||||||
|
exec "$@"
|
||||||
22
.docker/images/php/cron/Dockerfile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
ARG BASE_IMAGE
|
||||||
|
FROM ${BASE_IMAGE} as base
|
||||||
|
|
||||||
|
COPY ./images/php/cron/conf.d/psc /etc/cron.d/
|
||||||
|
COPY ./images/php/cron/bin/ /usr/bin/
|
||||||
|
RUN chmod +x /usr/bin/start-cron.sh
|
||||||
|
RUN chmod +x /usr/bin/set-env.sh
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y cron rsyslog
|
||||||
|
RUN sed -i '/imklog/s/^/#/' /etc/rsyslog.conf
|
||||||
|
|
||||||
|
FROM base as prod
|
||||||
|
|
||||||
|
USER $APP_USER_NAME
|
||||||
|
|
||||||
|
FROM base as ci
|
||||||
|
|
||||||
|
USER $APP_USER_NAME
|
||||||
|
|
||||||
|
FROM base as local
|
||||||
|
|
||||||
|
CMD ["/usr/bin/set-env.sh"]
|
||||||
5
.docker/images/php/cron/bin/set-env.sh
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# start-cron.sh
|
||||||
|
declare -p > /container.env
|
||||||
|
|
||||||
|
/usr/bin/start-cron.sh
|
||||||
8
.docker/images/php/cron/bin/start-cron.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# start-cron.sh
|
||||||
|
rsyslogd
|
||||||
|
cron
|
||||||
|
touch /var/log/cron.log
|
||||||
|
chmod -R 0777 /data/www/new/var/cache
|
||||||
|
chmod -R 0777 /data/www/new/var/log
|
||||||
|
tail -F /var/log/syslog /var/log/cron.log
|
||||||
5
.docker/images/php/cron/conf.d/psc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
SHELL=/bin/bash
|
||||||
|
BASH_ENV=/container.env
|
||||||
|
#
|
||||||
|
* * * * * www-data cd /data/www/new/web && /usr/local/bin/php /data/www/new/bin/console --env=prod application:queue:do >> /var/log/cron.log 2>&1
|
||||||
|
#
|
||||||
21
.docker/images/php/fpm/Dockerfile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
ARG BASE_IMAGE
|
||||||
|
FROM ${BASE_IMAGE} as base
|
||||||
|
|
||||||
|
RUN echo ${TARGET_PHP_VERSION}
|
||||||
|
|
||||||
|
COPY ./images/php/fpm/php-fpm.d/ /etc/php7/php-fpm.d/
|
||||||
|
COPY ./images/php/fpm/conf.d/zz-app-fpm.ini $PHP_INI_DIR/conf.d/
|
||||||
|
COPY ./images/php/fpm/conf.d/policy.xml /etc/ImageMagick-6/policy.xml
|
||||||
|
|
||||||
|
RUN sed -i "s/__APP_USER_NAME/$APP_USER_NAME/" /etc/php7/php-fpm.d/* \
|
||||||
|
&& sed -i "s/__APP_GROUP_NAME/$APP_GROUP_NAME/" /etc/php7/php-fpm.d/*
|
||||||
|
|
||||||
|
USER $APP_USER_NAME
|
||||||
|
|
||||||
|
EXPOSE 9000
|
||||||
|
|
||||||
|
CMD ["php-fpm", "-F"]
|
||||||
|
|
||||||
|
FROM base as prod
|
||||||
|
|
||||||
|
FROM base as local
|
||||||
89
.docker/images/php/fpm/conf.d/policy.xml
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE policymap [
|
||||||
|
<!ELEMENT policymap (policy)+>
|
||||||
|
<!ATTLIST policymap xmlns CDATA #FIXED ''>
|
||||||
|
<!ELEMENT policy EMPTY>
|
||||||
|
<!ATTLIST policy xmlns CDATA #FIXED '' domain NMTOKEN #REQUIRED
|
||||||
|
name NMTOKEN #IMPLIED pattern CDATA #IMPLIED rights NMTOKEN #IMPLIED
|
||||||
|
stealth NMTOKEN #IMPLIED value CDATA #IMPLIED>
|
||||||
|
]>
|
||||||
|
<!--
|
||||||
|
Configure ImageMagick policies.
|
||||||
|
|
||||||
|
Domains include system, delegate, coder, filter, path, or resource.
|
||||||
|
|
||||||
|
Rights include none, read, write, execute and all. Use | to combine them,
|
||||||
|
for example: "read | write" to permit read from, or write to, a path.
|
||||||
|
|
||||||
|
Use a glob expression as a pattern.
|
||||||
|
|
||||||
|
Suppose we do not want users to process MPEG video images:
|
||||||
|
|
||||||
|
<policy domain="delegate" rights="none" pattern="mpeg:decode" />
|
||||||
|
|
||||||
|
Here we do not want users reading images from HTTP:
|
||||||
|
|
||||||
|
<policy domain="coder" rights="none" pattern="HTTP" />
|
||||||
|
|
||||||
|
The /repository file system is restricted to read only. We use a glob
|
||||||
|
expression to match all paths that start with /repository:
|
||||||
|
|
||||||
|
<policy domain="path" rights="read" pattern="/repository/*" />
|
||||||
|
|
||||||
|
Lets prevent users from executing any image filters:
|
||||||
|
|
||||||
|
<policy domain="filter" rights="none" pattern="*" />
|
||||||
|
|
||||||
|
Any large image is cached to disk rather than memory:
|
||||||
|
|
||||||
|
<policy domain="resource" name="area" value="1GP"/>
|
||||||
|
|
||||||
|
Define arguments for the memory, map, area, width, height and disk resources
|
||||||
|
with SI prefixes (.e.g 100MB). In addition, resource policies are maximums
|
||||||
|
for each instance of ImageMagick (e.g. policy memory limit 1GB, -limit 2GB
|
||||||
|
exceeds policy maximum so memory limit is 1GB).
|
||||||
|
|
||||||
|
Rules are processed in order. Here we want to restrict ImageMagick to only
|
||||||
|
read or write a small subset of proven web-safe image types:
|
||||||
|
|
||||||
|
<policy domain="delegate" rights="none" pattern="*" />
|
||||||
|
<policy domain="filter" rights="none" pattern="*" />
|
||||||
|
<policy domain="coder" rights="none" pattern="*" />
|
||||||
|
<policy domain="coder" rights="read|write" pattern="{GIF,JPEG,PNG,WEBP}" />
|
||||||
|
-->
|
||||||
|
<policymap>
|
||||||
|
<!-- <policy domain="system" name="shred" value="2"/> -->
|
||||||
|
<!-- <policy domain="system" name="precision" value="6"/> -->
|
||||||
|
<!-- <policy domain="system" name="memory-map" value="anonymous"/> -->
|
||||||
|
<!-- <policy domain="system" name="max-memory-request" value="256MiB"/> -->
|
||||||
|
<!-- <policy domain="resource" name="temporary-path" value="/tmp"/> -->
|
||||||
|
<policy domain="resource" name="memory" value="256MiB"/>
|
||||||
|
<policy domain="resource" name="map" value="512MiB"/>
|
||||||
|
<policy domain="resource" name="width" value="16KP"/>
|
||||||
|
<policy domain="resource" name="height" value="16KP"/>
|
||||||
|
<!-- <policy domain="resource" name="list-length" value="128"/> -->
|
||||||
|
<policy domain="resource" name="area" value="128MB"/>
|
||||||
|
<policy domain="resource" name="disk" value="1GiB"/>
|
||||||
|
<!-- <policy domain="resource" name="file" value="768"/> -->
|
||||||
|
<!-- <policy domain="resource" name="thread" value="4"/> -->
|
||||||
|
<!-- <policy domain="resource" name="throttle" value="0"/> -->
|
||||||
|
<!-- <policy domain="resource" name="time" value="3600"/> -->
|
||||||
|
<!-- <policy domain="coder" rights="none" pattern="MVG" /> -->
|
||||||
|
<policy domain="module" rights="read | write" pattern="{PS,PDF,XPS}" />
|
||||||
|
<!-- <policy domain="delegate" rights="none" pattern="HTTPS" /> -->
|
||||||
|
<!-- <policy domain="path" rights="none" pattern="@*" /> -->
|
||||||
|
<!-- <policy domain="cache" name="memory-map" value="anonymous"/> -->
|
||||||
|
<!-- <policy domain="cache" name="synchronize" value="True"/> -->
|
||||||
|
<!-- <policy domain="cache" name="shared-secret" value="passphrase" stealth="true"/> -->
|
||||||
|
<!-- <policy domain="system" name="pixel-cache-memory" value="anonymous"/> -->
|
||||||
|
<!-- <policy domain="system" name="shred" value="2"/> -->
|
||||||
|
<!-- <policy domain="system" name="precision" value="6"/> -->
|
||||||
|
<!-- not needed due to the need to use explicitly by mvg: -->
|
||||||
|
<!-- <policy domain="delegate" rights="none" pattern="MVG" /> -->
|
||||||
|
<!-- use curl -->
|
||||||
|
<policy domain="delegate" rights="none" pattern="URL" />
|
||||||
|
<policy domain="delegate" rights="none" pattern="HTTPS" />
|
||||||
|
<policy domain="delegate" rights="none" pattern="HTTP" />
|
||||||
|
<!-- in order to avoid to get image with password text -->
|
||||||
|
<policy domain="path" rights="none" pattern="@*"/>
|
||||||
|
</policymap>
|
||||||
11
.docker/images/php/fpm/conf.d/zz-app-fpm.ini
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
; overriding defaults
|
||||||
|
default_socket_timeout=4000
|
||||||
|
request_terminate_timeout=4000
|
||||||
|
max_execution_time = 4000
|
||||||
|
max_input_vars = 10000
|
||||||
|
memory_limit=1024M
|
||||||
|
date.timezone=Europe/Berlin
|
||||||
|
upload_max_filesize = 1024M
|
||||||
|
post_max_size = 1024M
|
||||||
|
intl.default_locale=de
|
||||||
|
short_open_tag=On
|
||||||
15
.docker/images/php/fpm/php-fpm.d/www.conf
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
error_log = /proc/self/fd/2
|
||||||
|
|
||||||
|
[www]
|
||||||
|
access.log = /proc/self/fd/1
|
||||||
|
access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
|
||||||
|
catch_workers_output = yes
|
||||||
|
|
||||||
|
user = __APP_USER_NAME
|
||||||
|
group = __APP_GROUP_NAME
|
||||||
|
listen = 0.0.0.0:9000
|
||||||
|
pm = dynamic
|
||||||
|
pm.max_children = 5
|
||||||
|
pm.start_servers = 2
|
||||||
|
pm.min_spare_servers = 1
|
||||||
|
pm.max_spare_servers = 3
|
||||||
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
!.env.example
|
||||||
|
.env
|
||||||
|
.idea
|
||||||
|
src/
|
||||||
22
.make/01-application-setup.mk
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
##@ [Application: Setup]
|
||||||
|
|
||||||
|
.PHONY: setup
|
||||||
|
setup: ## Setup the application
|
||||||
|
"$(MAKE)" composer ARGS="--working-dir=/data/www/new install"
|
||||||
|
"$(MAKE)" setup-db
|
||||||
|
|
||||||
|
.PHONY: setup-db
|
||||||
|
setup-db: ## Setup the DB tables
|
||||||
|
$(DOCKER_COMPOSE) cp ./.setup $(DOCKER_SERVICE_NAME_PHP_MYSQL):/setup
|
||||||
|
$(DOCKER_COMPOSE) exec -T $(DOCKER_SERVICE_NAME_PHP_MYSQL) bash -c 'mysql --password=$$MYSQL_ROOT_PASSWORD psc < /setup/mysql/backup.sql'
|
||||||
|
$(DOCKER_COMPOSE) cp ./.setup $(DOCKER_SERVICE_NAME_PHP_MONGODB):/setup
|
||||||
|
$(DOCKER_COMPOSE) exec -T $(DOCKER_SERVICE_NAME_PHP_MONGODB) bash -c 'mongorestore /setup/mongodb/'
|
||||||
|
|
||||||
|
.PHONY: composer
|
||||||
|
composer: ## Run composer commands. Specify the command e.g. via ARGS="install"
|
||||||
|
$(EXECUTE_IN_APPLICATION_CONTAINER) composer $(ARGS);
|
||||||
|
|
||||||
|
.PHONY: phpunit
|
||||||
|
phpunit: ## Run PHPUNIT
|
||||||
|
$(EXECUTE_IN_APPLICATION_CONTAINER) /data/www/new/vendor/bin/phpunit;
|
||||||
|
|
||||||
31
.make/02-application-commands.mk
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
##@ [Application: Commands]
|
||||||
|
|
||||||
|
# @see https://stackoverflow.com/a/43076457
|
||||||
|
.PHONY: restart-php-fpm
|
||||||
|
restart-php-fpm: ## Restart the php-fpm service
|
||||||
|
"$(MAKE)" execute-in-container DOCKER_SERVICE_NAME=$(DOCKER_SERVICE_NAME_PHP_FPM) COMMAND="kill -USR2 1"
|
||||||
|
|
||||||
|
.PHONY: execute-in-container
|
||||||
|
execute-in-container: ## Execute a command in a container. E.g. via "make execute-in-container DOCKER_SERVICE_NAME=php-fpm COMMAND="echo 'hello'"
|
||||||
|
@$(if $(DOCKER_SERVICE_NAME),,$(error DOCKER_SERVICE_NAME is undefined))
|
||||||
|
@$(if $(COMMAND),,$(error COMMAND is undefined))
|
||||||
|
$(EXECUTE_IN_ANY_CONTAINER) $(COMMAND)
|
||||||
|
|
||||||
|
.PHONY: execute-in-application-container
|
||||||
|
execute-in-application-container: ## Execute a command in a container. E.g. via "make execute-in-container DOCKER_SERVICE_NAME=php-fpm COMMAND="echo 'hello'"
|
||||||
|
@$(if $(COMMAND),,$(error COMMAND is undefined))
|
||||||
|
$(EXECUTE_IN_APPLICATION_CONTAINER) $(COMMAND)
|
||||||
|
|
||||||
|
.PHONY: copy-in-mysql
|
||||||
|
copy-in-mysql: ## Execute a command in a container. E.g. via "make execute-in-container DOCKER_SERVICE_NAME=php-fpm COMMAND="echo 'hello'"
|
||||||
|
@$(if $(FROM),,$(error FROM is undefined))
|
||||||
|
@$(if $(TO),,$(error TO is undefined))
|
||||||
|
$(COPY_IN_MYSQL_CONTAINER)
|
||||||
|
|
||||||
|
.PHONY: enable-xdebug
|
||||||
|
enable-xdebug: ## Enable xdebug in the given container specified by "DOCKER_SERVICE_NAME". E.g. "make enable-xdebug DOCKER_SERVICE_NAME=php-fpm"
|
||||||
|
"$(MAKE)" execute-in-container APP_USER_NAME="root" DOCKER_SERVICE_NAME=$(DOCKER_SERVICE_NAME) COMMAND="sed -i 's/.*zend_extension=xdebug/zend_extension=xdebug/' '/etc/php8/conf.d/zz-app-local.ini'"
|
||||||
|
|
||||||
|
.PHONY: disable-xdebug
|
||||||
|
disable-xdebug: ## Disable xdebug in the given container specified by "DOCKER_SERVICE_NAME". E.g. "make disable-xdebug DOCKER_SERVICE_NAME=php-fpm"
|
||||||
|
"$(MAKE)" execute-in-container APP_USER_NAME="root" DOCKER_SERVICE_NAME=$(DOCKER_SERVICE_NAME) COMMAND="sed -i 's/.*zend_extension=xdebug/;zend_extension=xdebug/' '/etc/php8/conf.d/zz-app-local.ini'"
|
||||||
109
.make/03-application-qa.mk
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
##@ [Application: QA]
|
||||||
|
|
||||||
|
# variables
|
||||||
|
CORES?=$(shell (nproc || sysctl -n hw.ncpu) 2> /dev/null)
|
||||||
|
|
||||||
|
# constants
|
||||||
|
## files
|
||||||
|
ALL_FILES=./
|
||||||
|
APP_FILES=src/
|
||||||
|
TEST_FILES=tests/
|
||||||
|
|
||||||
|
## bash colors
|
||||||
|
RED:=\033[0;31m
|
||||||
|
GREEN:=\033[0;32m
|
||||||
|
YELLOW:=\033[0;33m
|
||||||
|
NO_COLOR:=\033[0m
|
||||||
|
|
||||||
|
# Tool CLI config
|
||||||
|
PHPUNIT_CMD=php vendor/bin/phpunit
|
||||||
|
PHPUNIT_ARGS= -c phpunit.xml
|
||||||
|
PHPUNIT_FILES=
|
||||||
|
PHPSTAN_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/phpstan analyse
|
||||||
|
PHPSTAN_ARGS=--level=9
|
||||||
|
PHPSTAN_FILES=$(APP_FILES) $(TEST_FILES)
|
||||||
|
PHPCS_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/phpcs
|
||||||
|
PHPCS_ARGS=--parallel=$(CORES) --standard=psr12
|
||||||
|
PHPCS_FILES=$(APP_FILES)
|
||||||
|
PHPCBF_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/phpcbf
|
||||||
|
PHPCBF_ARGS=$(PHPCS_ARGS)
|
||||||
|
PHPCBF_FILES=$(PHPCS_FILES)
|
||||||
|
PARALLEL_LINT_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/parallel-lint
|
||||||
|
PARALLEL_LINT_ARGS=-j 4 --exclude vendor/ --exclude .docker --exclude .git
|
||||||
|
PARALLEL_LINT_FILES=$(ALL_FILES)
|
||||||
|
COMPOSER_REQUIRE_CHECKER_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/composer-require-checker
|
||||||
|
COMPOSER_REQUIRE_CHECKER_ARGS=--ignore-parse-errors
|
||||||
|
|
||||||
|
# call with NO_PROGRESS=true to hide tool progress (makes sense when invoking multiple tools together)
|
||||||
|
NO_PROGRESS?=false
|
||||||
|
ifeq ($(NO_PROGRESS),true)
|
||||||
|
PHPSTAN_ARGS+= --no-progress
|
||||||
|
PARALLEL_LINT_ARGS+= --no-progress
|
||||||
|
else
|
||||||
|
PHPCS_ARGS+= -p
|
||||||
|
PHPCBF_ARGS+= -p
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Use NO_PROGRESS=false when running individual tools.
|
||||||
|
# On NO_PROGRESS=true the corresponding tool has no output on success
|
||||||
|
# apart from its runtime but it will still print
|
||||||
|
# any errors that occured.
|
||||||
|
define execute
|
||||||
|
if [ "$(NO_PROGRESS)" = "false" ]; then \
|
||||||
|
eval "$(EXECUTE_IN_APPLICATION_CONTAINER) bash -c 'cd new && $(1) $(2) $(3) $(4)'"; \
|
||||||
|
else \
|
||||||
|
START=$$(date +%s); \
|
||||||
|
printf "%-35s" "$@"; \
|
||||||
|
if OUTPUT=$$(eval "$(EXECUTE_IN_APPLICATION_CONTAINER) bash -c 'cd new && $(1) $(2) $(3) $(4)'" 2>&1); then \
|
||||||
|
printf " $(GREEN)%-6s$(NO_COLOR)" "done"; \
|
||||||
|
END=$$(date +%s); \
|
||||||
|
RUNTIME=$$((END-START)) ;\
|
||||||
|
printf " took $(YELLOW)$${RUNTIME}s$(NO_COLOR)\n"; \
|
||||||
|
else \
|
||||||
|
printf " $(RED)%-6s$(NO_COLOR)" "fail"; \
|
||||||
|
END=$$(date +%s); \
|
||||||
|
RUNTIME=$$((END-START)) ;\
|
||||||
|
printf " took $(YELLOW)$${RUNTIME}s$(NO_COLOR)\n"; \
|
||||||
|
echo "$$OUTPUT"; \
|
||||||
|
printf "\n"; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
fi
|
||||||
|
endef
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: ## Run all tests
|
||||||
|
@$(EXECUTE_IN_APPLICATION_CONTAINER) $(PHPUNIT_CMD) $(PHPUNIT_ARGS) $(ARGS)
|
||||||
|
|
||||||
|
.PHONY: phplint
|
||||||
|
phplint: ## Run phplint on all files
|
||||||
|
@$(call execute,$(PARALLEL_LINT_CMD),$(PARALLEL_LINT_ARGS),$(PARALLEL_LINT_FILES), $(ARGS))
|
||||||
|
|
||||||
|
.PHONY: phpcs
|
||||||
|
phpcs: ## Run style check on all application files
|
||||||
|
@$(call execute,$(PHPCS_CMD),$(PHPCS_ARGS),$(PHPCS_FILES), $(ARGS))
|
||||||
|
|
||||||
|
.PHONY: phpcbf
|
||||||
|
phpcbf: ## Run style fixer on all application files
|
||||||
|
@$(call execute,$(PHPCBF_CMD),$(PHPCBF_ARGS),$(PHPCBF_FILES), $(ARGS))
|
||||||
|
|
||||||
|
.PHONY: phpstan
|
||||||
|
phpstan: ## Run static analyzer on all application and test files
|
||||||
|
@$(call execute,$(PHPSTAN_CMD),$(PHPSTAN_ARGS),$(PHPSTAN_FILES), $(ARGS))
|
||||||
|
|
||||||
|
.PHONY: composer-require-checker
|
||||||
|
composer-require-checker: ## Run dependency checker
|
||||||
|
@$(call execute,$(COMPOSER_REQUIRE_CHECKER_CMD),$(COMPOSER_REQUIRE_CHECKER_ARGS),"", $(ARGS))
|
||||||
|
|
||||||
|
.PHONY: qa
|
||||||
|
qa: ## Run code quality tools on all files
|
||||||
|
@"$(MAKE)" -j $(CORES) -k --no-print-directory --output-sync=target qa-exec NO_PROGRESS=true
|
||||||
|
|
||||||
|
.PHONY: qa-exec
|
||||||
|
qa-exec: phpstan \
|
||||||
|
phplint \
|
||||||
|
phpcs
|
||||||
|
|
||||||
|
|
||||||
|
#composer-require-checker \
|
||||||
|
|
||||||
144
.make/04-docker.mk
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
# For local builds we always want to use "latest" as tag per default
|
||||||
|
ifeq ($(ENV),local)
|
||||||
|
TAG:=latest
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Enable buildkit for docker and docker-compose by default for every environment.
|
||||||
|
# For specific environments (e.g. MacBook with Apple Silicon M1 CPU) it should be turned off to work stable
|
||||||
|
# - this can be done in the .make/.env file
|
||||||
|
COMPOSE_DOCKER_CLI_BUILD?=1
|
||||||
|
DOCKER_BUILDKIT?=1
|
||||||
|
|
||||||
|
export COMPOSE_DOCKER_CLI_BUILD
|
||||||
|
export DOCKER_BUILDKIT
|
||||||
|
|
||||||
|
# Container names
|
||||||
|
## must match the names used in the docker-composer.yml files
|
||||||
|
DOCKER_SERVICE_NAME_WEB:=web
|
||||||
|
DOCKER_SERVICE_NAME_PHP_BASE:=php-base
|
||||||
|
DOCKER_SERVICE_NAME_PHP_FPM:=php-fpm
|
||||||
|
DOCKER_SERVICE_NAME_PHP_CRON:=cron
|
||||||
|
DOCKER_SERVICE_NAME_PHP_MYSQL:=mysql
|
||||||
|
DOCKER_SERVICE_NAME_PHP_MONGODB:=mongodb
|
||||||
|
DOCKER_SERVICE_NAME_APPLICATION:=application
|
||||||
|
|
||||||
|
# FYI:
|
||||||
|
# Naming convention for images is $(DOCKER_REGISTRY)/$(DOCKER_NAMESPACE)/$(DOCKER_SERVICE_NAME)-$(ENV)
|
||||||
|
# e.g. docker.io/dofroscra/nginx-local
|
||||||
|
# $(DOCKER_REGISTRY)---^ ^ ^ ^ docker.io
|
||||||
|
# $(DOCKER_NAMESPACE)-------------^ ^ ^ dofroscra
|
||||||
|
# $(DOCKER_SERVICE_NAME)------------------^ ^ nginx
|
||||||
|
# $(ENV)-----------------------------------------^ local
|
||||||
|
|
||||||
|
DOCKER_DIR:=./.docker
|
||||||
|
DOCKER_ENV_FILE:=$(DOCKER_DIR)/.env
|
||||||
|
DOCKER_COMPOSE_DIR:=$(DOCKER_DIR)/docker-compose
|
||||||
|
DOCKER_COMPOSE_FILE:=$(DOCKER_COMPOSE_DIR)/docker-compose.yml
|
||||||
|
DOCKER_COMPOSE_FILE_LOCAL:=$(DOCKER_COMPOSE_DIR)/docker-compose.local.yml
|
||||||
|
DOCKER_COMPOSE_FILE_PHP_BASE:=$(DOCKER_COMPOSE_DIR)/docker-compose-php-base.yml
|
||||||
|
DOCKER_COMPOSE_PROJECT_NAME:=tp_$(ENV)
|
||||||
|
|
||||||
|
# we need a couple of environment variables for docker-compose so we define a make-variable that we can
|
||||||
|
# then reference later in the Makefile without having to repeat all the environment variables
|
||||||
|
DOCKER_COMPOSE_COMMAND:=ENV=$(ENV) \
|
||||||
|
TAG=$(TAG) \
|
||||||
|
DOCKER_REGISTRY=$(DOCKER_REGISTRY) \
|
||||||
|
DOCKER_NAMESPACE=$(DOCKER_NAMESPACE) \
|
||||||
|
APP_USER_ID=$(APP_USER_ID) \
|
||||||
|
APP_GROUP_ID=$(APP_GROUP_ID) \
|
||||||
|
APP_USER_NAME=$(APP_USER_NAME) \
|
||||||
|
docker compose -p $(DOCKER_COMPOSE_PROJECT_NAME) --env-file $(DOCKER_ENV_FILE)
|
||||||
|
|
||||||
|
DOCKER_COMPOSE:=$(DOCKER_COMPOSE_COMMAND) -f $(DOCKER_COMPOSE_FILE) -f $(DOCKER_COMPOSE_FILE_LOCAL)
|
||||||
|
DOCKER_COMPOSE_PHP_BASE:=$(DOCKER_COMPOSE_COMMAND) -f $(DOCKER_COMPOSE_FILE_PHP_BASE)
|
||||||
|
|
||||||
|
EXECUTE_IN_ANY_CONTAINER?=
|
||||||
|
EXECUTE_IN_CRON_CONTAINER?=
|
||||||
|
EXECUTE_IN_APPLICATION_CONTAINER?=
|
||||||
|
EXECUTE_IN_MONGODB_CONTAINER?=
|
||||||
|
EXECUTE_IN_mYSQL_CONTAINER?=
|
||||||
|
|
||||||
|
COPY_IN_ANY_CONTAINER?=
|
||||||
|
COPY_IN_CRON_CONTAINER?=
|
||||||
|
COPY_IN_APPLICATION_CONTAINER?=
|
||||||
|
COPY_IN_MONGODB_CONTAINER?=
|
||||||
|
COPY_IN_mYSQL_CONTAINER?=
|
||||||
|
|
||||||
|
DOCKER_SERVICE_NAME?=
|
||||||
|
FROM?=
|
||||||
|
TO?=
|
||||||
|
|
||||||
|
# we can pass EXECUTE_IN_CONTAINER=true to a make invocation in order to execute the target in a docker container.
|
||||||
|
# Caution: this only works if the command in the target is prefixed with a $(EXECUTE_IN_*_CONTAINER) variable.
|
||||||
|
# If EXECUTE_IN_CONTAINER is NOT defined, we will check if make is ALREADY executed in a docker container.
|
||||||
|
# We still need a way to FORCE the execution in a container, e.g. for Gitlab CI, because the Gitlab
|
||||||
|
# Runner is executed as a docker container BUT we want to execute commands in OUR OWN docker containers!
|
||||||
|
EXECUTE_IN_CONTAINER?=
|
||||||
|
ifndef EXECUTE_IN_CONTAINER
|
||||||
|
# check if 'make' is executed in a docker container, see https://stackoverflow.com/a/25518538/413531
|
||||||
|
# `wildcard $file` checks if $file exists, see https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html
|
||||||
|
# i.e. if the result is "empty" then $file does NOT exist => we are NOT in a container
|
||||||
|
ifeq ("$(wildcard /.dockerenv)","")
|
||||||
|
EXECUTE_IN_CONTAINER=true
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
ifeq ($(EXECUTE_IN_CONTAINER),true)
|
||||||
|
EXECUTE_IN_ANY_CONTAINER:=$(DOCKER_COMPOSE) exec -T --user $(APP_USER_NAME) $(DOCKER_SERVICE_NAME)
|
||||||
|
EXECUTE_IN_APPLICATION_CONTAINER:=$(DOCKER_COMPOSE) exec -w /data/www/new -T --user $(APP_USER_NAME) $(DOCKER_SERVICE_NAME_APPLICATION)
|
||||||
|
EXECUTE_IN_CRON_CONTAINER:=$(DOCKER_COMPOSE) exec -T --user $(APP_USER_NAME) $(DOCKER_SERVICE_NAME_PHP_CRON)
|
||||||
|
EXECUTE_IN_MYSQL_CONTAINER:=$(DOCKER_COMPOSE) exec -T $(DOCKER_SERVICE_NAME_PHP_MYSQL)
|
||||||
|
EXECUTE_IN_MONGODB_CONTAINER:=$(DOCKER_COMPOSE) exec -T $(DOCKER_SERVICE_NAME_PHP_MONGODB)
|
||||||
|
|
||||||
|
COPY_IN_ANY_CONTAINER:=$(DOCKER_COMPOSE) cp $(FROM) $(DOCKER_SERVICE_NAME):$(TO)
|
||||||
|
COPY_IN_APPLICATION_CONTAINER:=$(DOCKER_COMPOSE) cp $(FROM) $(DOCKER_SERVICE_NAME_APPLICATION):$(TO)
|
||||||
|
COPY_IN_CRON_CONTAINER:=$(DOCKER_COMPOSE) cp $(FROM) $(DOCKER_SERVICE_NAME_PHP_CRON):$(TO)
|
||||||
|
COPY_IN_MYSQL_CONTAINER:=$(DOCKER_COMPOSE) cp $(FROM) $(DOCKER_SERVICE_NAME_PHP_MYSQL):$(TO)
|
||||||
|
COPY_IN_MONGODB_CONTAINER:=$(DOCKER_COMPOSE) cp $(FROM) $(DOCKER_SERVICE_NAME_PHP_MONGODB):$(TO)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
##@ [Docker]
|
||||||
|
|
||||||
|
.PHONY: docker-clean
|
||||||
|
docker-clean: ## Remove the .env file for docker
|
||||||
|
@rm -f $(DOCKER_ENV_FILE)
|
||||||
|
|
||||||
|
.PHONY: validate-docker-variables
|
||||||
|
validate-docker-variables: .docker/.env
|
||||||
|
@$(if $(TAG),,$(error TAG is undefined))
|
||||||
|
@$(if $(ENV),,$(error ENV is undefined))
|
||||||
|
@$(if $(DOCKER_REGISTRY),,$(error DOCKER_REGISTRY is undefined - Did you run make-init?))
|
||||||
|
@$(if $(DOCKER_NAMESPACE),,$(error DOCKER_NAMESPACE is undefined - Did you run make-init?))
|
||||||
|
@$(if $(APP_USER_ID),,$(error APP_USER_ID is undefined - Did you run make-init?))
|
||||||
|
@$(if $(APP_GROUP_ID),,$(error APP_GROUP_ID is undefined - Did you run make-init?))
|
||||||
|
@$(if $(APP_USER_NAME),,$(error APP_USER_NAME is undefined - Did you run make-init?))
|
||||||
|
|
||||||
|
.docker/.env:
|
||||||
|
@cp $(DOCKER_ENV_FILE).example $(DOCKER_ENV_FILE)
|
||||||
|
|
||||||
|
.PHONY:docker-build-image
|
||||||
|
docker-build-image: validate-docker-variables ## Build all docker images OR a specific image by providing the service name via: make docker-build DOCKER_SERVICE_NAME=<service>
|
||||||
|
$(DOCKER_COMPOSE) build $(DOCKER_SERVICE_NAME)
|
||||||
|
|
||||||
|
.PHONY: docker-build-php
|
||||||
|
docker-build-php: validate-docker-variables ## Build the php base image
|
||||||
|
$(DOCKER_COMPOSE_PHP_BASE) build $(DOCKER_SERVICE_NAME_PHP_BASE)
|
||||||
|
|
||||||
|
.PHONY: docker-build
|
||||||
|
docker-build: docker-build-php docker-build-image ## Build the php image and then all other docker images
|
||||||
|
|
||||||
|
.PHONY: docker-up
|
||||||
|
docker-up: validate-docker-variables ## Create and start all docker containers. To create/start only a specific container, use DOCKER_SERVICE_NAME=<service>
|
||||||
|
$(DOCKER_COMPOSE) up -d $(DOCKER_SERVICE_NAME)
|
||||||
|
|
||||||
|
.PHONY: docker-down
|
||||||
|
docker-down: validate-docker-variables ## Stop and remove all docker containers.
|
||||||
|
@$(DOCKER_COMPOSE) down
|
||||||
|
|
||||||
|
.PHONY: docker-config
|
||||||
|
docker-config: validate-docker-variables ## List the configuration
|
||||||
|
@$(DOCKER_COMPOSE) config
|
||||||
|
|
||||||
|
.PHONY: docker-prune
|
||||||
|
docker-prune: ## Remove ALL unused docker resources, including volumes
|
||||||
|
@docker system prune -a -f --volumes
|
||||||
5
.make/05-symfony.mk
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
##@ [Application: Symfony]
|
||||||
|
|
||||||
|
.PHONY: console
|
||||||
|
console: ## Run composer commands. Specify the command e.g. via ARGS="install"
|
||||||
|
$(EXECUTE_IN_APPLICATION_CONTAINER) php "/data/www/new/bin/console" $(ARGS);
|
||||||
26
.make/variables.env
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
DOCKER_REGISTRY=gitlab.com/boonkerz
|
||||||
|
DOCKER_NAMESPACE=boonkerz
|
||||||
|
|
||||||
|
APP_USER_NAME=application
|
||||||
|
APP_USER_ID=10000
|
||||||
|
APP_GROUP_ID=10001
|
||||||
|
APP_CODE_PATH_CONTAINER=/data/www
|
||||||
|
|
||||||
|
|
||||||
|
DOCKER_SERVICE_NAME_WEB:=web
|
||||||
|
DOCKER_SERVICE_NAME_PHP_BASE:=php-base
|
||||||
|
DOCKER_SERVICE_NAME_PHP_FPM:=php-fpm
|
||||||
|
DOCKER_SERVICE_NAME_PHP_CRON:=php-cron
|
||||||
|
DOCKER_SERVICE_NAME_APPLICATION:=application
|
||||||
|
DOCKER_SERVICE_NAME_MYSQL:=mysql
|
||||||
|
DOCKER_SERVICE_NAME_MONGODB:=mongodb
|
||||||
|
|
||||||
|
# VM / instance names
|
||||||
|
VM_NAME_APPLICATION=$(DOCKER_SERVICE_NAME_APPLICATION)-vm
|
||||||
|
VM_NAME_PHP_FPM=$(DOCKER_SERVICE_NAME_PHP_FPM)-vm
|
||||||
|
VM_NAME_PHP_CRON=$(DOCKER_SERVICE_NAME_PHP_CRON)-vm
|
||||||
|
VM_NAME_WEB=$(DOCKER_SERVICE_NAME_WEB)-vm
|
||||||
|
VM_NAME_MYSQL=$(DOCKER_SERVICE_NAME_MYSQL)-vm
|
||||||
|
VM_NAME_MONGODB=$(DOCKER_SERVICE_NAME_MONGODB)-vm
|
||||||
|
# Helpers
|
||||||
|
ALL_VM_SERVICE_NAMES=$(VM_NAME_APPLICATION):$(DOCKER_SERVICE_NAME_APPLICATION) $(VM_NAME_PHP_FPM):$(DOCKER_SERVICE_NAME_PHP_FPM) $(VM_NAME_PHP_CRON):$(DOCKER_SERVICE_NAME_PHP_CRON) $(VM_NAME_WEB):$(DOCKER_SERVICE_NAME_WEB)
|
||||||
BIN
.setup/media/612a096de36f4d50f82c7295/abriss-a4.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
.setup/media/612a0a32e36f4d50f82c7296/abriss-a4.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
.setup/media/612a0a3abc4ef8348d3f0ae7/abriss-a4-klebend.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
.setup/media/612a0a40e36f4d50f82c7297/abriss-a4-klebend.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
.setup/media/612a0a47bc4ef8348d3f0ae8/aufkleber.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
.setup/media/612a0a4ae36f4d50f82c7298/aufkleber.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
.setup/media/612a0a59bc4ef8348d3f0ae9/beachflag.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
.setup/media/612a0a61e36f4d50f82c7299/beachflag.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
.setup/media/612a0a64bc4ef8348d3f0aea/bericht-a4.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
.setup/media/612a0a6fe36f4d50f82c729a/bericht-a4.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
.setup/media/612a0a75bc4ef8348d3f0aeb/bericht-a5.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
.setup/media/612a0a84dce6920e443e6224/bierdeckel.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
.setup/media/612a0a8fbc4ef8348d3f0aec/briefpapier.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
.setup/media/612a0a99bc4ef8348d3f0aed/broschuere.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
.setup/media/612a0a9edce6920e443e6225/bericht-a5.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
.setup/media/612a0aa4bc4ef8348d3f0aee/broschuere-a4.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
.setup/media/612a0aabdce6920e443e6226/bierdeckel.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
.setup/media/612a0aaebc4ef8348d3f0aef/broschuere-a5.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
.setup/media/612a0ab8e36f4d50f82c729b/buch-a4.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
.setup/media/612a0ac0dce6920e443e6227/briefpapier.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
.setup/media/612a0ac2e36f4d50f82c729c/buch-a5.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
.setup/media/612a0acadce6920e443e6228/buch-b5.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
.setup/media/612a0acde36f4d50f82c729d/broschuere.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
.setup/media/612a0ad4dce6920e443e6229/buch-softcover.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
.setup/media/612a0adebc4ef8348d3f0af0/cd.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
.setup/media/612a0ae6bc4ef8348d3f0af1/broschuere-a4.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
.setup/media/612a0ae8dce6920e443e622a/cd-booklet.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
.setup/media/612a0af1dce6920e443e622b/cd-produktionen.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
.setup/media/612a0afbdce6920e443e622c/checkkarten.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
.setup/media/612a0afddce6920e443e622d/broschuere-a5.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
.setup/media/612a0b04bc4ef8348d3f0af2/copypapier.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
.setup/media/612a0b0ebc4ef8348d3f0af3/din-plots.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
.setup/media/612a0b18bc4ef8348d3f0af4/dinlang-flyer-gefalzt.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
.setup/media/612a0b21bc4ef8348d3f0af5/dvd.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
.setup/media/612a0b26bc4ef8348d3f0af6/buch-a4.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
.setup/media/612a0b2ce36f4d50f82c729e/dvd-booklet.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
.setup/media/612a0b32e36f4d50f82c729f/buch-a5.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
.setup/media/612a0b37dce6920e443e622e/dvd-produktionen.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
.setup/media/612a0b40dce6920e443e622f/eintrittskarte.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
.setup/media/612a0b44dce6920e443e6230/buch-softcover.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
.setup/media/612a0b49e36f4d50f82c72a0/examenstitel.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
.setup/media/612a0b53e36f4d50f82c72a1/cd.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
.setup/media/612a0b57bc4ef8348d3f0af7/faltflyer-dl-hoch-8s.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
.setup/media/612a0b60bc4ef8348d3f0af8/cd-booklet.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
.setup/media/612a0b67bc4ef8348d3f0af9/faltflyer-dl-quer-8s.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
.setup/media/612a0b6dbc4ef8348d3f0afa/cd-produktionen.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
.setup/media/612a0b70e36f4d50f82c72a2/flagge.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
.setup/media/612a0b79dce6920e443e6231/flyer.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
.setup/media/612a0b7bdce6920e443e6232/checkkarten.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
.setup/media/612a0b84dce6920e443e6233/fotobuch-eckig.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
.setup/media/612a0b89dce6920e443e6234/copypapier.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 61 KiB |
BIN
.setup/media/612a0b97dce6920e443e6236/din-plots.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
.setup/media/612a0b9cdce6920e443e6237/fotobuch-leder-eckig.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
.setup/media/612a0ba5dce6920e443e6238/dinlang-flyer-gefalzt.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
.setup/media/612a0ba7dce6920e443e6239/fotobuch-softcover-a4.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 54 KiB |
BIN
.setup/media/612a0bbbbc4ef8348d3f0afc/dvd.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
.setup/media/612a0bc3bc4ef8348d3f0afd/frei-plots.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
.setup/media/612a0bc8bc4ef8348d3f0afe/dvd-booklet.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
.setup/media/612a0bcebc4ef8348d3f0aff/freieform-aufkleber.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
.setup/media/612a0bd5bc4ef8348d3f0b00/dvd-produktionen.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
.setup/media/612a0bd9bc4ef8348d3f0b01/freiform-wallmount.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
.setup/media/612a0be0bc4ef8348d3f0b02/eintrittskarte.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 18 KiB |
BIN
.setup/media/612a0beebc4ef8348d3f0b04/examenstitel.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 23 KiB |
BIN
.setup/media/612a0bfabc4ef8348d3f0b06/faltflyer-dl-hoch-8s.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
.setup/media/612a0bfebc4ef8348d3f0b07/grusskarten.png
Normal file
|
After Width: | Height: | Size: 68 KiB |