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
FROM ${BASE_IMAGE} as base
RUN apt update && apt install -y \
sqlite3
FROM base as prod
USER $APP_USER_NAME
FROM base as ci
USER $APP_USER_NAME
FROM base as local
#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"]
ARG BASE_IMAGE
FROM ${BASE_IMAGE} as base
RUN apt update && apt install -y \
sqlite3
FROM base as prod
USER $APP_USER_NAME
FROM base as ci
USER $APP_USER_NAME
FROM base as local
#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"]

View File

@ -1,165 +1,166 @@
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
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 && \
apt install -y \
bash \
git \
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
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
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
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 ./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)
RUN --mount=type=cache,target=/tmp/.composer \
cd /dependencies/new && \
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 ./src/ /codebase
# 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 && \
rm -rf .docker/ .build/ .infrastructure/ && \
if [ "$ENV" == "prod" ] ; \
then \
# on production, we don't want tests
rm -rf tests/; \
fi
FROM base as prod
COPY --from=codebase --chown=$APP_USER_NAME:$APP_GROUP_NAME /codebase $APP_CODE_PATH
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
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
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 && \
apt install -y \
bash \
git \
git-secret \
gawk \
gnupg \
make \
strace \
sudo \
vim \
nano
# 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
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
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
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 ./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)
RUN --mount=type=cache,target=/tmp/.composer \
cd /dependencies/new && \
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 ./src/ /codebase
# 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 && \
rm -rf .docker/ .build/ .infrastructure/ && \
if [ "$ENV" == "prod" ] ; \
then \
# on production, we don't want tests
rm -rf tests/; \
fi
FROM base as prod
COPY --from=codebase --chown=$APP_USER_NAME:$APP_GROUP_NAME /codebase $APP_CODE_PATH
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

View File

@ -3,7 +3,9 @@
rsyslogd
cron
touch /var/log/cron.log
touch /var/log/syslog.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/log/*
chmod -R 0777 /data/www/new/var/cache

View File

@ -1,109 +1,114 @@
##@ [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=
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) $(1) $(2) $(3) $(4)"; \
else \
START=$$(date +%s); \
printf "%-35s" "$@"; \
if OUTPUT=$$(eval "$(EXECUTE_IN_APPLICATION_CONTAINER) $(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 \
##@ [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 -dxdebug.mode=off vendor/bin/phpunit
PHPUNIT_CMD_XDEBUG=php vendor/bin/phpunit
PHPUNIT_ARGS=
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) $(1) $(2) $(3) $(4)"; \
else \
START=$$(date +%s); \
printf "%-35s" "$@"; \
if OUTPUT=$$(eval "$(EXECUTE_IN_APPLICATION_CONTAINER) $(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: test-xdebug
test-xdebug: ## Run all tests
@$(EXECUTE_IN_APPLICATION_CONTAINER) $(PHPUNIT_CMD_XDEBUG) $(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 \