This commit is contained in:
Thomas Peterson 2023-06-30 13:09:42 +02:00
parent cda99ff767
commit 81affe09e6
4 changed files with 310 additions and 302 deletions

View File

@ -1,28 +1,28 @@
ARG BASE_IMAGE ARG BASE_IMAGE
FROM ${BASE_IMAGE} as base FROM ${BASE_IMAGE} as base
RUN apt update && apt install -y \ RUN apt update && apt install -y \
sqlite3 sqlite3
FROM base as prod FROM base as prod
USER $APP_USER_NAME USER $APP_USER_NAME
FROM base as ci FROM base as ci
USER $APP_USER_NAME USER $APP_USER_NAME
FROM base as local FROM base as local
#ARG APP_SSH_PASSWORD #ARG APP_SSH_PASSWORD
#RUN echo "$APP_USER_NAME:$APP_SSH_PASSWORD" | chpasswd 2>&1 #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 ## Required to start sshd, otherwise the container will error out on startup with the message
## "sshd: no hostkeys available -- exiting." ## "sshd: no hostkeys available -- exiting."
## @see https://stackoverflow.com/a/65348102/413531 ## @see https://stackoverflow.com/a/65348102/413531
#RUN ssh-keygen -A #RUN ssh-keygen -A
# #
## we use SSH deployment configuration in PhpStorm for local development ## we use SSH deployment configuration in PhpStorm for local development
#EXPOSE 22 #EXPOSE 22
# #
#CMD ["/usr/sbin/sshd", "-D"] #CMD ["/usr/sbin/sshd", "-D"]

View File

@ -1,165 +1,166 @@
ARG COMPOSER_VERSION ARG COMPOSER_VERSION
ARG TARGET_PHP_VERSION ARG TARGET_PHP_VERSION
FROM composer:${COMPOSER_VERSION} as composer FROM composer:${COMPOSER_VERSION} as composer
FROM php:${TARGET_PHP_VERSION}-fpm as base FROM php:${TARGET_PHP_VERSION}-fpm as base
# make build args available as ENV variables to downstream images # make build args available as ENV variables to downstream images
# so that we don't have to pass the same build args again # so that we don't have to pass the same build args again
ARG APP_USER_ID ARG APP_USER_ID
ARG APP_GROUP_ID ARG APP_GROUP_ID
ARG APP_USER_NAME ARG APP_USER_NAME
ARG APP_GROUP_NAME ARG APP_GROUP_NAME
ARG APP_CODE_PATH ARG APP_CODE_PATH
ARG ENV ARG ENV
ENV APP_USER_ID=${APP_USER_ID} ENV APP_USER_ID=${APP_USER_ID}
ENV APP_GROUP_ID=${APP_GROUP_ID} ENV APP_GROUP_ID=${APP_GROUP_ID}
ENV APP_USER_NAME=${APP_USER_NAME} ENV APP_USER_NAME=${APP_USER_NAME}
ENV APP_GROUP_NAME=${APP_GROUP_NAME} ENV APP_GROUP_NAME=${APP_GROUP_NAME}
ENV APP_CODE_PATH=${APP_CODE_PATH} ENV APP_CODE_PATH=${APP_CODE_PATH}
ENV TARGET_PHP_VERSION=${TARGET_PHP_VERSION} ENV TARGET_PHP_VERSION=${TARGET_PHP_VERSION}
ENV ENV=${ENV} ENV ENV=${ENV}
RUN addgroup -gid $APP_GROUP_ID $APP_GROUP_NAME && \ 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 && \ adduser --disabled-password --uid $APP_USER_ID --shell /bin/bash --ingroup $APP_GROUP_NAME $APP_USER_NAME && \
mkdir -p $APP_CODE_PATH && \ mkdir -p $APP_CODE_PATH && \
chown $APP_USER_NAME: $APP_CODE_PATH chown $APP_USER_NAME: $APP_CODE_PATH
ADD https://gitsecret.jfrog.io/artifactory/api/security/keypair/public/repositories/git-secret-apk /etc/apk/keys/git-secret-apk.rsa.pub ADD https://gitsecret.jfrog.io/artifactory/api/security/keypair/public/repositories/git-secret-apk /etc/apk/keys/git-secret-apk.rsa.pub
RUN apt update && \ RUN apt update && \
apt install -y \ apt install -y \
bash \ bash \
git \ git \
git-secret \ git-secret \
gawk \ gawk \
gnupg \ gnupg \
make \ make \
strace \ strace \
sudo \ sudo \
vim vim \
nano
# Install intl
RUN apt-get update && apt-get install -y \ # Install intl
libicu-dev \ RUN apt-get update && apt-get install -y \
libssl-dev \ libicu-dev \
libcurl4-openssl-dev \ libssl-dev \
libfreetype6-dev \ libcurl4-openssl-dev \
libjpeg62-turbo-dev \ libfreetype6-dev \
libpng-dev \ libjpeg62-turbo-dev \
libxml2-dev \ libpng-dev \
libmagickwand-dev \ libxml2-dev \
git \ libmagickwand-dev \
zlib1g-dev \ git \
unzip \ zlib1g-dev \
libzip-dev \ unzip \
mupdf-tools \ libzip-dev \
imagemagick \ mupdf-tools \
libmcrypt-dev imagemagick \
libmcrypt-dev
# Install fileinfo
RUN docker-php-ext-install -j$(nproc) fileinfo # Install fileinfo
# Install intl RUN docker-php-ext-install -j$(nproc) fileinfo
RUN docker-php-ext-install -j$(nproc) intl # Install intl
# Install mongodb RUN docker-php-ext-install -j$(nproc) intl
RUN pecl install mongodb \ # Install mongodb
&& docker-php-ext-enable mongodb RUN pecl install mongodb \
# Install mcrypt && docker-php-ext-enable mongodb
RUN pecl install mcrypt \ # Install mcrypt
&& docker-php-ext-enable mcrypt RUN pecl install mcrypt \
# Install curl && docker-php-ext-enable mcrypt
RUN docker-php-ext-install -j$(nproc) curl # Install curl
# Install Zip RUN docker-php-ext-install -j$(nproc) curl
RUN docker-php-ext-install zip # Install Zip
# Install gd RUN docker-php-ext-install zip
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \ # Install gd
&& docker-php-ext-install -j$(nproc) gd RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
# Install soap && docker-php-ext-install -j$(nproc) gd
RUN docker-php-ext-install -j$(nproc) soap # Install soap
# Install imagick RUN docker-php-ext-install -j$(nproc) soap
RUN pecl install imagick \ # Install imagick
&& docker-php-ext-enable imagick RUN pecl install imagick \
# Install mysql && docker-php-ext-enable imagick
RUN docker-php-ext-install -j$(nproc) pdo_mysql # Install mysql
# Install opcache RUN docker-php-ext-install -j$(nproc) pdo_mysql
RUN docker-php-ext-install -j$(nproc) opcache # Install opcache
RUN apt-get update && apt-get install -y \ RUN docker-php-ext-install -j$(nproc) opcache
libc-client-dev libkrb5-dev libldap2-dev && \ RUN apt-get update && apt-get install -y \
rm -r /var/lib/apt/lists/* libc-client-dev libkrb5-dev libldap2-dev && \
rm -r /var/lib/apt/lists/*
# Install ldap
RUN docker-php-ext-install -j$(nproc) ldap # 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 RUN docker-php-ext-configure imap --with-kerberos --with-imap-ssl && \
docker-php-ext-install -j$(nproc) imap
COPY ./.docker/images/php/base/pdf/php_pdflib.so /pdflib.so
COPY ./.docker/images/php/base/pdf/php_pdflib.so /pdflib.so
# make bash default shell
RUN sed -e 's;/bin/ash$;/bin/bash;g' -i /etc/passwd # 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/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 ./.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
COPY --from=composer /usr/bin/composer /usr/local/bin/composer
RUN git config --system --add safe.directory "$APP_CODE_PATH"
RUN git config --system --add safe.directory "$APP_CODE_PATH"
WORKDIR $APP_CODE_PATH
WORKDIR $APP_CODE_PATH
FROM base as codebase
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 # By only copying the composer files required to run composer install
COPY ./src/new/composer.json /dependencies/new/ # the layer will be cached and only invalidated when the composer dependencies are changed
COPY ./src/new/composer.lock /dependencies/new/ COPY ./src/new/composer.json /dependencies/new/
COPY ./src/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) # use a cache mount to cache the composer dependencies
RUN --mount=type=cache,target=/tmp/.composer \ # this is essentially a cache that lives in Docker BuildKit (i.e. has nothing to do with the host system)
cd /dependencies/new && \ RUN --mount=type=cache,target=/tmp/.composer \
if [ "$ENV" == "prod" ] ; \ cd /dependencies/new && \
then \ if [ "$ENV" == "prod" ] ; \
# on production, we don't want test dependencies then \
COMPOSER_HOME=/tmp/.composer composer install --no-scripts --no-plugins --no-progress -o --no-dev; \ # on production, we don't want test dependencies
else \ COMPOSER_HOME=/tmp/.composer composer install --no-scripts --no-plugins --no-progress -o --no-dev; \
COMPOSER_HOME=/tmp/.composer composer install --no-scripts --no-plugins --no-progress -o; \ else \
fi COMPOSER_HOME=/tmp/.composer composer install --no-scripts --no-plugins --no-progress -o; \
fi
# copy the full codebase
COPY ./src/ /codebase # copy the full codebase
COPY ./src/ /codebase
# move the dependencies
RUN mv /dependencies/new/vendor /codebase/new/vendor # move the dependencies
RUN mv /dependencies/new/vendor /codebase/new/vendor
# remove files we don't require in the image to keep the image size small
RUN cd /codebase && \ # remove files we don't require in the image to keep the image size small
rm -rf .docker/ .build/ .infrastructure/ && \ RUN cd /codebase && \
if [ "$ENV" == "prod" ] ; \ rm -rf .docker/ .build/ .infrastructure/ && \
then \ if [ "$ENV" == "prod" ] ; \
# on production, we don't want tests then \
rm -rf tests/; \ # on production, we don't want tests
fi rm -rf tests/; \
fi
FROM base as prod
FROM base as prod
COPY --from=codebase --chown=$APP_USER_NAME:$APP_GROUP_NAME /codebase $APP_CODE_PATH
COPY --from=codebase --chown=$APP_USER_NAME:$APP_GROUP_NAME /codebase $APP_CODE_PATH
FROM base as ci
FROM base as ci
COPY --from=codebase --chown=$APP_USER_NAME:$APP_GROUP_NAME /codebase $APP_CODE_PATH
COPY --from=codebase --chown=$APP_USER_NAME:$APP_GROUP_NAME /codebase $APP_CODE_PATH
FROM base as local
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 # add app user to sudoers
# see https://askubuntu.com/a/340669 for not requiring a sudo pw # see https://ostechnix.com/add-delete-and-grant-sudo-privileges-to-users-in-alpine-linux/ for adding sudo
RUN echo "root ALL=(ALL) NOPASSWD: ALL " | tee -a "/etc/sudoers.d/users" && \ # see https://askubuntu.com/a/340669 for not requiring a sudo pw
echo "${APP_USER_NAME} ALL=(ALL) NOPASSWD: ALL " | tee -a "/etc/sudoers.d/users" 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
RUN pecl install xdebug

View File

@ -3,7 +3,9 @@
rsyslogd rsyslogd
cron cron
touch /var/log/cron.log touch /var/log/cron.log
touch /var/log/syslog.log
chmod -R 0777 /var/log/cron.log chmod -R 0777 /var/log/cron.log
chmod -R 0777 /var/log/syslog.log
rm /data/www/new/var/cache/* rm /data/www/new/var/cache/*
rm /data/www/new/var/log/* rm /data/www/new/var/log/*
chmod -R 0777 /data/www/new/var/cache chmod -R 0777 /data/www/new/var/cache

View File

@ -1,109 +1,114 @@
##@ [Application: QA] ##@ [Application: QA]
# variables # variables
CORES?=$(shell (nproc || sysctl -n hw.ncpu) 2> /dev/null) CORES?=$(shell (nproc || sysctl -n hw.ncpu) 2> /dev/null)
# constants # constants
## files ## files
ALL_FILES=./ ALL_FILES=./
APP_FILES=src/ APP_FILES=src/
TEST_FILES=tests/ TEST_FILES=tests/
## bash colors ## bash colors
RED:=\033[0;31m RED:=\033[0;31m
GREEN:=\033[0;32m GREEN:=\033[0;32m
YELLOW:=\033[0;33m YELLOW:=\033[0;33m
NO_COLOR:=\033[0m NO_COLOR:=\033[0m
# Tool CLI config # Tool CLI config
PHPUNIT_CMD=php vendor/bin/phpunit PHPUNIT_CMD=php -dxdebug.mode=off vendor/bin/phpunit
PHPUNIT_ARGS= PHPUNIT_CMD_XDEBUG=php vendor/bin/phpunit
PHPUNIT_FILES= PHPUNIT_ARGS=
PHPSTAN_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/phpstan analyse PHPUNIT_FILES=
PHPSTAN_ARGS=--level=9 PHPSTAN_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/phpstan analyse
PHPSTAN_FILES=$(APP_FILES) $(TEST_FILES) PHPSTAN_ARGS=--level=9
PHPCS_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/phpcs PHPSTAN_FILES=$(APP_FILES) $(TEST_FILES)
PHPCS_ARGS=--parallel=$(CORES) --standard=psr12 PHPCS_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/phpcs
PHPCS_FILES=$(APP_FILES) PHPCS_ARGS=--parallel=$(CORES) --standard=psr12
PHPCBF_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/phpcbf PHPCS_FILES=$(APP_FILES)
PHPCBF_ARGS=$(PHPCS_ARGS) PHPCBF_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/phpcbf
PHPCBF_FILES=$(PHPCS_FILES) PHPCBF_ARGS=$(PHPCS_ARGS)
PARALLEL_LINT_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/parallel-lint PHPCBF_FILES=$(PHPCS_FILES)
PARALLEL_LINT_ARGS=-j 4 --exclude vendor/ --exclude .docker --exclude .git PARALLEL_LINT_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/parallel-lint
PARALLEL_LINT_FILES=$(ALL_FILES) PARALLEL_LINT_ARGS=-j 4 --exclude vendor/ --exclude .docker --exclude .git
COMPOSER_REQUIRE_CHECKER_CMD=php -d xdebug.mode=off -d memory_limit=-1 vendor/bin/composer-require-checker PARALLEL_LINT_FILES=$(ALL_FILES)
COMPOSER_REQUIRE_CHECKER_ARGS=--ignore-parse-errors 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 # call with NO_PROGRESS=true to hide tool progress (makes sense when invoking multiple tools together)
ifeq ($(NO_PROGRESS),true) NO_PROGRESS?=false
PHPSTAN_ARGS+= --no-progress ifeq ($(NO_PROGRESS),true)
PARALLEL_LINT_ARGS+= --no-progress PHPSTAN_ARGS+= --no-progress
else PARALLEL_LINT_ARGS+= --no-progress
PHPCS_ARGS+= -p else
PHPCBF_ARGS+= -p PHPCS_ARGS+= -p
endif PHPCBF_ARGS+= -p
endif
# Use NO_PROGRESS=false when running individual tools.
# On NO_PROGRESS=true the corresponding tool has no output on success # Use NO_PROGRESS=false when running individual tools.
# apart from its runtime but it will still print # On NO_PROGRESS=true the corresponding tool has no output on success
# any errors that occured. # apart from its runtime but it will still print
define execute # any errors that occured.
if [ "$(NO_PROGRESS)" = "false" ]; then \ define execute
eval "$(EXECUTE_IN_APPLICATION_CONTAINER) $(1) $(2) $(3) $(4)"; \ if [ "$(NO_PROGRESS)" = "false" ]; then \
else \ eval "$(EXECUTE_IN_APPLICATION_CONTAINER) $(1) $(2) $(3) $(4)"; \
START=$$(date +%s); \ else \
printf "%-35s" "$@"; \ START=$$(date +%s); \
if OUTPUT=$$(eval "$(EXECUTE_IN_APPLICATION_CONTAINER) $(1) $(2) $(3) $(4)" 2>&1); then \ printf "%-35s" "$@"; \
printf " $(GREEN)%-6s$(NO_COLOR)" "done"; \ if OUTPUT=$$(eval "$(EXECUTE_IN_APPLICATION_CONTAINER) $(1) $(2) $(3) $(4)" 2>&1); then \
END=$$(date +%s); \ printf " $(GREEN)%-6s$(NO_COLOR)" "done"; \
RUNTIME=$$((END-START)) ;\ END=$$(date +%s); \
printf " took $(YELLOW)$${RUNTIME}s$(NO_COLOR)\n"; \ RUNTIME=$$((END-START)) ;\
else \ printf " took $(YELLOW)$${RUNTIME}s$(NO_COLOR)\n"; \
printf " $(RED)%-6s$(NO_COLOR)" "fail"; \ else \
END=$$(date +%s); \ printf " $(RED)%-6s$(NO_COLOR)" "fail"; \
RUNTIME=$$((END-START)) ;\ END=$$(date +%s); \
printf " took $(YELLOW)$${RUNTIME}s$(NO_COLOR)\n"; \ RUNTIME=$$((END-START)) ;\
echo "$$OUTPUT"; \ printf " took $(YELLOW)$${RUNTIME}s$(NO_COLOR)\n"; \
printf "\n"; \ echo "$$OUTPUT"; \
exit 1; \ printf "\n"; \
fi; \ exit 1; \
fi fi; \
endef fi
endef
.PHONY: test
test: ## Run all tests .PHONY: test
@$(EXECUTE_IN_APPLICATION_CONTAINER) $(PHPUNIT_CMD) $(PHPUNIT_ARGS) $(ARGS) test: ## Run all tests
@$(EXECUTE_IN_APPLICATION_CONTAINER) $(PHPUNIT_CMD) $(PHPUNIT_ARGS) $(ARGS)
.PHONY: phplint
phplint: ## Run phplint on all files .PHONY: test-xdebug
@$(call execute,$(PARALLEL_LINT_CMD),$(PARALLEL_LINT_ARGS),$(PARALLEL_LINT_FILES), $(ARGS)) test-xdebug: ## Run all tests
@$(EXECUTE_IN_APPLICATION_CONTAINER) $(PHPUNIT_CMD_XDEBUG) $(PHPUNIT_ARGS) $(ARGS)
.PHONY: phpcs
phpcs: ## Run style check on all application files .PHONY: phplint
@$(call execute,$(PHPCS_CMD),$(PHPCS_ARGS),$(PHPCS_FILES), $(ARGS)) phplint: ## Run phplint on all files
@$(call execute,$(PARALLEL_LINT_CMD),$(PARALLEL_LINT_ARGS),$(PARALLEL_LINT_FILES), $(ARGS))
.PHONY: phpcbf
phpcbf: ## Run style fixer on all application files .PHONY: phpcs
@$(call execute,$(PHPCBF_CMD),$(PHPCBF_ARGS),$(PHPCBF_FILES), $(ARGS)) phpcs: ## Run style check on all application files
@$(call execute,$(PHPCS_CMD),$(PHPCS_ARGS),$(PHPCS_FILES), $(ARGS))
.PHONY: phpstan
phpstan: ## Run static analyzer on all application and test files .PHONY: phpcbf
@$(call execute,$(PHPSTAN_CMD),$(PHPSTAN_ARGS),$(PHPSTAN_FILES), $(ARGS)) phpcbf: ## Run style fixer on all application files
@$(call execute,$(PHPCBF_CMD),$(PHPCBF_ARGS),$(PHPCBF_FILES), $(ARGS))
.PHONY: composer-require-checker
composer-require-checker: ## Run dependency checker .PHONY: phpstan
@$(call execute,$(COMPOSER_REQUIRE_CHECKER_CMD),$(COMPOSER_REQUIRE_CHECKER_ARGS),"", $(ARGS)) phpstan: ## Run static analyzer on all application and test files
@$(call execute,$(PHPSTAN_CMD),$(PHPSTAN_ARGS),$(PHPSTAN_FILES), $(ARGS))
.PHONY: qa
qa: ## Run code quality tools on all files .PHONY: composer-require-checker
@"$(MAKE)" -j $(CORES) -k --no-print-directory --output-sync=target qa-exec NO_PROGRESS=true composer-require-checker: ## Run dependency checker
@$(call execute,$(COMPOSER_REQUIRE_CHECKER_CMD),$(COMPOSER_REQUIRE_CHECKER_ARGS),"", $(ARGS))
.PHONY: qa-exec
qa-exec: phpstan \ .PHONY: qa
phplint \ qa: ## Run code quality tools on all files
phpcs @"$(MAKE)" -j $(CORES) -k --no-print-directory --output-sync=target qa-exec NO_PROGRESS=true
.PHONY: qa-exec
#composer-require-checker \ qa-exec: phpstan \
phplint \
phpcs
#composer-require-checker \