gitlab ci

parent 95839c03
Pipeline #5926 skipped with stages
stages:
- build
- deploy
- migrations
- db
- stop
variables:
PROJECT_PREFIX: lk-intercollege
REVIEW_HOST: intercollege-stage.adnm.ru
APP_HOST: ${CI_COMMIT_REF_SLUG}.${REVIEW_HOST}
APP_URL: https://${CI_COMMIT_REF_SLUG}.${REVIEW_HOST}
APP_ENV: review-${CI_COMMIT_REF_SLUG}
# мануальный деплой с подготовленной базой
build (review_manual):
stage: build
before_script:
- ssh www-data@94.241.139.131 "cd /var/www/${PROJECT_PREFIX} && git pull origin ${CI_COMMIT_REF_NAME}"
- ssh www-data@94.241.139.131 "/var/www/${PROJECT_PREFIX}/docker/infra/clear_containers.sh ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX} ${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}"
- ssh www-data@94.241.139.131 "cp /var/www/${PROJECT_PREFIX}/docker/.env.review /var/www/tmp/.env.${PROJECT_PREFIX} && echo PROJECT_PREFIX=${PROJECT_PREFIX} >> /var/www/tmp/.env.${PROJECT_PREFIX} && echo CI_COMMIT_REF_SLUG=${CI_COMMIT_REF_SLUG} >> /var/www/tmp/.env.${PROJECT_PREFIX} && echo APP_HOST=${APP_HOST} >> /var/www/tmp/.env.${PROJECT_PREFIX}"
script:
- ssh www-data@94.241.139.131 "docker compose --env-file /var/www/tmp/.env.${PROJECT_PREFIX} -f /var/www/${PROJECT_PREFIX}/docker/docker-compose-review.yml -p ${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG} up -d --build --force-recreate --remove-orphans"
after_script:
- ssh www-data@94.241.139.131 "rm /var/www/tmp/.env.${PROJECT_PREFIX}"
environment:
name: review/${CI_COMMIT_REF_SLUG}
url: https://${CI_COMMIT_REF_SLUG}.${REVIEW_HOST}
on_stop: "stop_review"
variables:
APP_HOST: ${CI_COMMIT_REF_SLUG}.${REVIEW_HOST}
APP_URL: https://${CI_COMMIT_REF_SLUG}.${REVIEW_HOST}
APP_ENV: review-${CI_COMMIT_REF_SLUG}
PROJECT_PREFIX: lk-intercollege
REVIEW_HOST: intercollege-stage.adnm.ru
when: manual
except:
- master
migrations:
stage: migrations
except:
- master
when: manual
script:
- ssh www-data@94.241.139.131 "docker exec -i ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX}_app php artisan migrate --force"
variables:
PROJECT_PREFIX: lk-intercollege
db_dump_from_stage:
stage: db
except:
- master
when: manual
script:
- ssh fastuser@80.78.244.171 "cd /var/www/fastuser/data/www/intercollege-backend.orog.ru && mysqldump -uintercollege -p34ciFD3hcjEUW9sO intercollege > dump.sql"
- ssh www-data@94.241.139.131 "cd /var/www/${PROJECT_PREFIX}/storage/app && scp fastuser@80.78.244.171:/var/www/fastuser/data/www/intercollege-backend.orog.ru/dump.sql ./dump.sql"
- ssh www-data@94.241.139.131 "sleep 3s && docker exec -i ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX}_mysql mysql -uintercollege -pintercollege intercollege < /var/www/${PROJECT_PREFIX}/storage/app/dump.sql"
- ssh www-data@94.241.139.131 "rm /var/www/${PROJECT_PREFIX}/storage/app/dump.sql"
- ssh fastuser@80.78.244.171 "rm /var/www/fastuser/data/www/intercollege-backend.orog.ru/dump.sql"
variables:
APP_HOST: ${CI_COMMIT_REF_SLUG}.${REVIEW_HOST}
APP_URL: https://${CI_COMMIT_REF_SLUG}.${REVIEW_HOST}
APP_ENV: review-${CI_COMMIT_REF_SLUG}
PROJECT_PREFIX: lk-intercollege
REVIEW_HOST: intercollege-stage.adnm.ru
# остановка окружения и очистка все волюмов
stop_review:
when: manual
stage: stop
# variables:
# <<: *review_variables
# GIT_STRATEGY: none
environment:
name: review/${CI_COMMIT_REF_SLUG}
action: stop
before_script: []
script:
- ssh www-data@94.241.139.131 "/var/www/${PROJECT_PREFIX}/docker/infra/clear_containers.sh ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX} ${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}"
except:
- master
variables:
APP_HOST: ${CI_COMMIT_REF_SLUG}.${REVIEW_HOST}
APP_URL: https://${CI_COMMIT_REF_SLUG}.${REVIEW_HOST}
APP_ENV: review-${CI_COMMIT_REF_SLUG}
PROJECT_PREFIX: lk-intercollege
REVIEW_HOST: intercollege-stage.adnm.ru
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:Y/bnxuNxBsXdvWhJwKyFxhxarO23NWAbC1wwaNETwHU=
APP_DEBUG=true
APP_URL=http://intercollege.adn
LOG_CHANNEL=elastic
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=intercollege
DB_USERNAME=intercollege
DB_PASSWORD=intercollege
DB_OROG_DATABASE=intercollege
DB_OROG_USERNAME=intercollege
DB_OROG_PASSWORD=34ciFD3hcjEUW9sO
PROJECT_PREFIX=lk-intercollege
REVIEW_HOST=intercollege-stage.adnm.ru
COMPOSER_ALLOW_SUPERUSER=1
BROADCAST_DRIVER=reverb
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=predis
REDIS_HOST=fishredis
REDIS_PASSWORD=eYVX7EwVmmxKPCDmwMtyKVge8oLd2t81
REDIS_PORT=6379
REDIS_QUEUE=default
#REDIS_HOST=127.0.0.1
#REDIS_PASSWORD=null
#REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.yandex.ru
MAIL_PORT=587
MAIL_USERNAME=info@vkusezona.ru
MAIL_PASSWORD=Andrey76=
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=info@vkusezona.ru
MAIL_FROM_NAME=ВкуСезона
AWS_ACCESS_KEY_ID=b7c50c7cbe934dde9403183c9d5aeb7d
AWS_SECRET_ACCESS_KEY=f53b9f1a12d14597a170b1a88439c6ae
AWS_DEFAULT_REGION=ru-1
AWS_BUCKET=intercollege2023
AWS_USE_PATH_STYLE_ENDPOINT=false
AWS_ENDPOINT=https://s3.storage.selcloud.ru
AWS_PUBLIC_DOMAIN=https://d3eff1b5-0605-4b61-a1a3-aa102dedaf2c.selstorage.ru
AWS_URL=https://d3eff1b5-0605-4b61-a1a3-aa102dedaf2c.selstorage.ru
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1
VITE_APP_NAME="${APP_NAME}"
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
SCOUT_DRIVER=null
SERVICE_IEAC_URL=http://service.ieac.ru
SENTRY_LARAVEL_DSN=http://e077ff0c21f719c15983f73b3a9ef6ae@localhost:9000/2
# Specify a fixed sample rate
SENTRY_TRACES_SAMPLE_RATE=1.0
SMS_RU_API_ID=F28CC9EA-72B2-8A77-0BBB-1DAEFB497C06
DASHBOARD_FILESYSTEM_DISK=s3
FRONTEND_URL=https://my.intercollege.su
SBER_USER_NAME=T7715020079-api
SBER_PASSWORD=T7715020079
SBER_FAIL_URL=https://intercollege-frontend.orog.ru/payment-message-error.html
SBER_RETURN_URL=https://intercollege-frontend.orog.ru/payment-message.html
TELEGRAM_BOT_TOKEN=6984974334:AAEXj6YJKJM6cJhr8JM1ixizQIGbCbZ5zEk
TELEGRAM_BOT_NAME=InterCollegeDemoBot
TELEGRAM_WEBHOOK_URL=https://intercollege-backend.orog.ru/telegram/webhook
GOOGLE_RECAPTCHA_KEY=6LfAlGQpAAAAAHrsgXizu8ncUdqPMg-HmxEEFYq9
GOOGLE_RECAPTCHA_SECRET=6LfAlGQpAAAAABvMJBsQR2DqewJflgQNr8NVAIH-
RECAPTCHA_URL=https://www.google.com/recaptcha/api/siteverify
#https://www.recaptcha.net/recaptcha/api/siteverify
YOOKASSA_SITE_ID=347408
YOOKASSA_SECRET_KEY=test_9vKZvT9LqDZBSIZDT9Czffbd5PpV9Q5ZNqHLFtzXzqs
ELASTIC_API_KEY=VHdKZmRZNEJOVk40cmZlZURVS3Q6MU51OVJQeGtSVC15eVRHd2YwTU55UQ==
ELASTIC_URL=elk.orog.ru:9200
SENTRY_LARAVEL_DSN=https://fbdddad8d0b23fb1e80f5e89236c8272@sentry.orog.ru/12
SENTRY_TRACES_SAMPLE_RATE=1.0
REVERB_APP_ID=743095
REVERB_APP_KEY=rvoczanjjm5mzrieagtp
REVERB_APP_SECRET=57fqblxcokveyebojzqv
REVERB_HOST="localhost"
REVERB_PORT=8080
REVERB_SCHEME=http
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
x-logging: &logging
driver: "json-file"
options:
max-size: "1m"
max-file: "1"
x-app: &app-tpl
restart: always
env_file: .env
# volumes: &vols
# - /var/www/${PROJECT_PREFIX}/:/app
networks:
- internal
labels:
- traefik.enable=false
environment:
- TASK_SLOT=1
- CI_COMMIT_REF_SLUG=${CI_COMMIT_REF_SLUG}
- APP_ENV=${APP_ENV}
- APP_HOST=${APP_HOST}
- APP_URL=${APP_URL}
- PROJECT_PREFIX=${PROJECT_PREFIX}
depends_on:
- mysql
- redis
logging: *logging
services:
nginx:
container_name: ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX}_nginx
image: ${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}_nginx
build:
context: ../
dockerfile: docker/infra/nginx/Dockerfile
restart: always
environment:
- TASK_SLOT=1
- CI_COMMIT_REF_SLUG=${CI_COMMIT_REF_SLUG}
- APP_ENV=${APP_ENV}
- APP_HOST=${APP_HOST}
- APP_URL=${APP_URL}
- PROJECT_PREFIX=${PROJECT_PREFIX}
# volumes: *vols
networks:
- internal
- traefik-network
labels:
- "traefik.enable=true"
- "traefik.http.routers.${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}.rule=Host(`${APP_HOST}`)"
- "traefik.http.routers.${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}.entrypoints=websecure"
- "traefik.http.routers.${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}.tls.certresolver=myresolver"
- "traefik.docker.network=traefik-network"
depends_on:
- app
logging: *logging
# healthcheck:
# test: curl --silent --show-error --fail localhost/ping
# start_period: 60s
# interval: 5s
# timeout: 5s
# retries: 3
app:
container_name: ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX}_app
image: ${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}_app
<<: *app-tpl
build:
context: ../
dockerfile: docker/infra/php/Dockerfile
cron:
container_name: ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX}_cron
image: ${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}_cron
<<: *app-tpl
build:
context: ../
dockerfile: docker/infra/php/Dockerfile
depends_on:
- app
command: /app/docker/infra/cmd_cron.sh
queue_default:
container_name: ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX}_queue_default
image: ${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}_queue_default
build:
context: ../
dockerfile: docker/infra/php/Dockerfile
<<: *app-tpl
depends_on:
- app
command: /app/docker/infra/cmd_queue_default.sh
queue_elastic-log:
container_name: ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX}_elastic_log
image: ${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}_elastic_log
build:
context: ../
dockerfile: docker/infra/php/Dockerfile
<<: *app-tpl
depends_on:
- app
command: /app/docker/infra/cmd_queue_elastic-log.sh
# использовать подготовленный образ БД
mysql:
container_name: ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX}_mysql
image: mysql:8.0.19
restart: always
environment:
- TASK_SLOT=1
- CI_COMMIT_REF_SLUG=${CI_COMMIT_REF_SLUG}
- APP_ENV=${APP_ENV}
- APP_HOST=${APP_HOST}
- APP_URL=${APP_URL}
- PROJECT_PREFIX=${PROJECT_PREFIX}
- CI_COMMIT_REF_SLUG=${CI_COMMIT_REF_SLUG}
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=${DB_DATABASE}
- MYSQL_USER=${DB_USERNAME}
- MYSQL_PASSWORD=${DB_PASSWORD}
networks:
- internal
labels:
- traefik.enable=false
- ops.dns=db.${APP_HOST}
# healthcheck:
# test: mysqladmin ping -h localhost -p$$MYSQL_ROOT_PASSWORD
# timeout: 45s
# interval: 10s
# retries: 10
logging: *logging
redis:
container_name: ${CI_COMMIT_REF_SLUG}_${PROJECT_PREFIX}_redis
image: redis:7.2.1
restart: always
environment:
CI_COMMIT_REF_SLUG: ${CI_COMMIT_REF_SLUG}
networks:
- internal
# volumes:
# - /work/data/${PROJECT_PREFIX}_${CI_COMMIT_REF_SLUG}/redis:/data
labels:
- traefik.enable=false
# healthcheck:
# test: [ "CMD", "redis-cli", "ping" ]
# interval: 1s
# timeout: 3s
# retries: 30
logging: *logging
networks:
internal:
review:
external: true
traefik-network:
external: true
#!/bin/sh
if [ $( docker ps -a | grep $1_mysql | wc -l ) -gt 0 ]; then
docker stop $1_mysql && docker rm $1_mysql
echo $1_mysql "runned"
else
echo $1_mysql "not runned"
fi
if [ $( docker ps -a | grep $1_redis | wc -l ) -gt 0 ]; then
docker stop $1_redis && docker rm $1_redis
echo $1_redis "runned"
else
echo $1_redis "not runned"
fi
if [ $( docker ps -a | grep $1_nginx | wc -l ) -gt 0 ]; then
docker stop $1_nginx && docker rm $1_nginx && docker rmi $2_nginx
echo $1_nginx "runned"
else
echo $1_nginx "not runned"
fi
if [ $( docker ps -a | grep $1_app | wc -l ) -gt 0 ]; then
docker stop $1_app && docker rm $1_app && docker rmi $2_app
echo $1_app "runned"
else
echo $1_app "not runned"
fi
if [ $( docker ps -a | grep $1_queue_default | wc -l ) -gt 0 ]; then
docker stop $_queue_default && docker rm $1_queue_default && docker rmi $2_queue_default
echo $1_queue_default "runned"
else
echo $1_queue_default "not runned"
fi
if [ $( docker ps -a | grep $1_elastic_log | wc -l ) -gt 0 ]; then
docker stop $_elastic_log && docker rm $1_elastic_log && docker rmi $2_elastic_log
echo $1_elastic_log "runned"
else
echo $1_elastic_log "not runned"
fi
if [ $( docker ps -a | grep $1_cron | wc -l ) -gt 0 ]; then
docker stop $_cron && docker rm $1_cron && docker rmi $2_cron
echo $1_cron "runned"
else
echo $1_cron "not runned"
fi
#!/bin/sh
php-fpm
#!/bin/sh
env > /etc/environment
cron -f
#!/bin/sh
echo ${APP_HOST}
echo 1234567
#!/bin/sh
php artisan queue:work --daemon --queue=default --delay=0 --memory=512 --sleep=3 --tries=1 --timeout=7150
#!/bin/sh
php artisan queue:work --daemon --queue=elastic-log --delay=0 --memory=128 --sleep=3 --tries=1
* * * * * www-data cd /app && /usr/local/bin/php artisan schedule:run
FROM mysql:8.0.28
RUN rm -f /etc/mysql/conf.d/mysqldump.cnf
COPY docker/infra/mysql/my.cnf /etc/mysql/conf.d/
[mysqld]
innodb_buffer_pool_size=4G
skip-log-bin
max_allowed_packet=2G
character-set-server=utf8
collation-server=utf8_general_ci
sql_mode=''
default-authentication-plugin=mysql_native_password
default-time-zone='+03:00'
innodb_flush_log_at_trx_commit=2
[mysqldump]
quick
quote-names
max_allowed_packet=2G
FROM nginx:latest
WORKDIR /app/
COPY ../../../ /app/
COPY docker/infra/nginx/vhost.conf /etc/nginx/conf.d/default.conf
server {
listen 80 default_server;
server_name localhost _;
access_log off;
error_log /dev/stdout;
client_max_body_size 100m;
root /app/public;
index index.php;
location ~ /\. {
deny all;
}
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# php-fpm: pm.status_path = /status
location ~ ^/(status|ping)$ {
allow 127.0.0.1;
deny all;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
fastcgi_pass app:9000;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SERVER_NAME $host;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS $http_x_https if_not_empty;
fastcgi_pass app:9000;
fastcgi_read_timeout 90;
}
}
FROM php:8.2.17-fpm
ARG COMPOSER_INSTALL=true
ENV COMPOSER_ALLOW_SUPERUSER=1
WORKDIR /app
RUN apt-get update \
&& apt-get install -y \
cron \
apt-utils \
man \
curl \
git \
bash \
vim \
zip unzip \
acl \
iproute2 \
dnsutils \
fonts-freefont-ttf \
fontconfig \
dbus \
openssh-client \
sendmail \
libfreetype6-dev \
libjpeg62-turbo-dev \
icu-devtools \
libicu-dev \
libmcrypt4 \
libmcrypt-dev \
libpng-dev \
zlib1g-dev \
libxml2-dev \
libzip-dev \
libonig-dev \
graphviz \
libcurl4-openssl-dev \
pkg-config \
libldap2-dev \
libpq-dev \
libwebp-dev
#&& echo "extension=mongodb.so" > /usr/local/etc/php/conf.d/mongodb-ext.ini
RUN docker-php-ext-configure intl --enable-intl && \
docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp && \
docker-php-ext-install -j$(nproc) gd && \
docker-php-ext-install pdo \
pgsql pdo_pgsql \
mysqli pdo_mysql \
intl iconv mbstring \
zip pcntl \
exif opcache \
&& docker-php-source delete
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
COPY ../../../ /app/
COPY docker/.env.review /app/.env
RUN if [ "$COMPOSER_INSTALL" = "true" ] ; then \
composer install -n --ansi --no-scripts --no-progress \
&& composer clearcache \
&& composer dump-autoload --optimize --no-scripts \
; \
fi
COPY docker/infra/php/www.conf /usr/local/etc/php-fpm.d/
COPY docker/infra/php/custom.php.ini /usr/local/etc/php/conf.d/php.ini
COPY docker/infra/cron/crontab /etc/cron.d/
COPY docker/infra/php/php-fpm-healthcheck /bin/
RUN chmod +x /app/docker/infra/cmd_*.sh && \
chmod +x /bin/php-fpm-healthcheck && \
chown -R www-data:www-data /app/bootstrap/cache /app/storage/framework && chown www-data:www-data public && \
ln -vsfn /app/storage/app/public /app/public/storage
#ENTRYPOINT ["/app/docker/infra/php/entrypoint_app.sh"]
CMD ["php-fpm"]
#CMD /app/docker/infra/cmd_app.sh
date.timezone = Europe/Moscow
upload_max_filesize = 100M
post_max_size = 100M
max_execution_time = 30
memory_limit = 256M
opcache.memory_consumption=256
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.fast_shutdown=1
#!/bin/sh
if [ $TASK_SLOT -eq 1 ]; then
chown www-data:www-data -R /app/storage/
fi
exec "$@"
#!/bin/sh
# vim: set filetype=sh :
# Author: <Renato Mefi gh@mefi.in> https://github.com/renatomefi
# The original code lives in https://github.com/renatomefi/php-fpm-healthcheck
#
# A POSIX compliant shell script to healthcheck PHP fpm status, can be used only for pinging the status page
# or check for specific metrics
#
# i.e.: ./php-fpm-healthcheck --verbose --active-processes=6
# The script will fail in case the 'active processes' is bigger than 6.
#
# You can combine multiple options as well, the first one to fail will fail the healthcheck
# i.e.: ./php-fpm-healthcheck --listen-queue-len=10 --active-processes=6
#
# Ping mode (exit 0 if php-fpm returned data): ./php-fpm-healthcheck
#
# Ping mode with data (outputs php-fpm status text): ./php-fpm-healthcheck -v
#
# Exit status codes:
# 2,9,111 - Couldn't connect to PHP fpm, is it running?
# 8 - Couldn't reach PHP fpm status page, have you configured it with `pm.status_path = /status`?
# 1 - A healthcheck condition has failed
# 3 - Invalid option given
# 4 - One or more required softwares are missing
#
# Available options:
# -v|--verbose
#
# Metric options, fails in case the CURRENT VALUE is bigger than the GIVEN VALUE
# --accepted-conn=n
# --listen-queue=n
# --max-listen-queue=n
# --idle-processes=n
# --active-processes=n
# --total-processes=n
# --max-active-processes=n
# --max-children-reached=n
# --slow-requests=n
#
set -eu
OPTIND=1 # Reset getopt in case it has been used previously in the shell
# Required software
FCGI_CMD_PATH=$(command -v cgi-fcgi) || { >&2 echo "Make sure fcgi is installed (i.e. apk add --no-cache fcgi). Aborting."; exit 4; }
command -v sed 1> /dev/null || { >&2 echo "Make sure sed is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; }
command -v tail 1> /dev/null || { >&2 echo "Make sure tail is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; }
command -v grep 1> /dev/null || { >&2 echo "Make sure grep is installed (i.e. apk add --no-cache grep). Aborting."; exit 4; }
# Get status from fastcgi connection
# $1 - cgi-fcgi connect argument
get_fpm_status() {
if test "$VERBOSE" = 1; then printf "Trying to connect to php-fpm via: %s%s\\n" "$1" "$SCRIPT_NAME"; fi;
# Since I cannot use pipefail I'll just split these in two commands
FPM_STATUS=$(env -i REQUEST_METHOD="$REQUEST_METHOD" SCRIPT_NAME="$SCRIPT_NAME" SCRIPT_FILENAME="$SCRIPT_FILENAME" "$FCGI_CMD_PATH" -bind -connect "$1" 2> /dev/null)
FPM_STATUS=$(echo "$FPM_STATUS" | tail +5)
if test "$VERBOSE" = 1; then printf "php-fpm status output:\\n%s\\n" "$FPM_STATUS"; fi;
if test "$FPM_STATUS" = "File not found."; then
>&2 printf "php-fpm status page non reachable\\n";
exit 8;
fi;
}
# $1 - fpm option
# $2 - expected value threshold
check_fpm_health_by() {
OPTION=$(echo "$1" | sed 's/--//g; s/-/ /g;')
VALUE_EXPECTED="$2";
VALUE_ACTUAL=$(echo "$FPM_STATUS" | grep "^$OPTION:" | cut -d: -f2 | sed 's/ //g')
if test "$VERBOSE" = 1; then printf "'%s' value '%s' and expected is less than '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED"; fi;
if test "$VALUE_ACTUAL" -gt "$VALUE_EXPECTED"; then
>&2 printf "'%s' value '%s' is greater than expected '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED";
exit 1;
fi;
}
PARAM_AMOUNT=0
# $1 - fpm option
# $2 - expected value threshold
check_later() {
# The POSIX sh way to check if it's an integer, also the output is supressed since it's polution
if ! test "$2" -eq "$2" 2> /dev/null; then
>&2 printf "'%s' option value must be an integer, '%s' given\\n" "$1" "$2"; exit 3;
fi
PARAM_AMOUNT=$(( PARAM_AMOUNT + 1 ))
eval "PARAM_TO_CHECK$PARAM_AMOUNT=$1"
eval "VALUE_TO_CHECK$PARAM_AMOUNT=$2"
}
# From the PARAM_TO_CHECK/VALUE_TO_CHECK magic variables, do all the checks
check_fpm_health() {
j=1
while [ $j -le $PARAM_AMOUNT ]; do
eval "CURRENT_PARAM=\$PARAM_TO_CHECK$j"
eval "CURRENT_VALUE=\$VALUE_TO_CHECK$j"
check_fpm_health_by "$CURRENT_PARAM" "$CURRENT_VALUE"
j=$(( j + 1 ))
done
}
if ! GETOPT=$(getopt -o v --long verbose,accepted-conn:,listen-queue:,max-listen-queue:,listen-queue-len:,idle-processes:,active-processes:,total-processes:,max-active-processes:,max-children-reached:,slow-requests: -n 'php-fpm-healthcheck' -- "$@"); then
>&2 echo "Invalid options, terminating." ; exit 3
fi;
eval set -- "$GETOPT"
# FastCGI variables
FCGI_CONNECT_DEFAULT="localhost:9000"
FCGI_STATUS_PATH_DEFAULT="/status"
export REQUEST_METHOD="GET"
export SCRIPT_NAME="${FCGI_STATUS_PATH:-$FCGI_STATUS_PATH_DEFAULT}"
export SCRIPT_FILENAME="${FCGI_STATUS_PATH:-$FCGI_STATUS_PATH_DEFAULT}"
FCGI_CONNECT="${FCGI_CONNECT:-$FCGI_CONNECT_DEFAULT}"
VERBOSE=0
while test "$1"; do
case "$1" in
-v|--verbose ) VERBOSE=1; shift ;;
--) shift ; break ;;
* ) check_later "$1" "$2"; shift 2 ;;
esac
done
FPM_STATUS=false
get_fpm_status "$FCGI_CONNECT"
check_fpm_health
[global]
daemonize = no
error_log = /proc/self/fd/2
[www]
user = www-data
group = www-data
listen = 0.0.0.0:9000
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 16
pm.process_idle_timeout = 300
pm.max_requests = 500
pm.status_path = /status
ping.path = /ping
ping.response = pong
clear_env = no
catch_workers_output = yes
#!/usr/bin/env bash
# Use this script to test if a given TCP host/port are available
WAITFORIT_cmdname=${0##*/}
echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
usage()
{
cat << USAGE >&2
Usage:
$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST Host or IP under test
-p PORT | --port=PORT TCP port under test
Alternatively, you specify the host and port as host:port
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGE
exit 1
}
wait_for()
{
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
else
echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
fi
WAITFORIT_start_ts=$(date +%s)
while :
do
if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
nc -z $WAITFORIT_HOST $WAITFORIT_PORT
WAITFORIT_result=$?
else
(echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
WAITFORIT_result=$?
fi
if [[ $WAITFORIT_result -eq 0 ]]; then
WAITFORIT_end_ts=$(date +%s)
echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
break
fi
sleep 1
done
return $WAITFORIT_result
}
wait_for_wrapper()
{
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
else
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
fi
WAITFORIT_PID=$!
trap "kill -INT -$WAITFORIT_PID" INT
wait $WAITFORIT_PID
WAITFORIT_RESULT=$?
if [[ $WAITFORIT_RESULT -ne 0 ]]; then
echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
fi
return $WAITFORIT_RESULT
}
# process arguments
while [[ $# -gt 0 ]]
do
case "$1" in
*:* )
WAITFORIT_hostport=(${1//:/ })
WAITFORIT_HOST=${WAITFORIT_hostport[0]}
WAITFORIT_PORT=${WAITFORIT_hostport[1]}
shift 1
;;
--child)
WAITFORIT_CHILD=1
shift 1
;;
-q | --quiet)
WAITFORIT_QUIET=1
shift 1
;;
-s | --strict)
WAITFORIT_STRICT=1
shift 1
;;
-h)
WAITFORIT_HOST="$2"
if [[ $WAITFORIT_HOST == "" ]]; then break; fi
shift 2
;;
--host=*)
WAITFORIT_HOST="${1#*=}"
shift 1
;;
-p)
WAITFORIT_PORT="$2"
if [[ $WAITFORIT_PORT == "" ]]; then break; fi
shift 2
;;
--port=*)
WAITFORIT_PORT="${1#*=}"
shift 1
;;
-t)
WAITFORIT_TIMEOUT="$2"
if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
shift 2
;;
--timeout=*)
WAITFORIT_TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
WAITFORIT_CLI=("$@")
break
;;
--help)
usage
;;
*)
echoerr "Unknown argument: $1"
usage
;;
esac
done
if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
echoerr "Error: you need to provide a host and port to test."
usage
fi
WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}
# Check to see if timeout is from busybox?
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
WAITFORIT_BUSYTIMEFLAG=""
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
WAITFORIT_ISBUSY=1
# Check if busybox timeout uses -t flag
# (recent Alpine versions don't support -t anymore)
if timeout &>/dev/stdout | grep -q -e '-t '; then
WAITFORIT_BUSYTIMEFLAG="-t"
fi
else
WAITFORIT_ISBUSY=0
fi
if [[ $WAITFORIT_CHILD -gt 0 ]]; then
wait_for
WAITFORIT_RESULT=$?
exit $WAITFORIT_RESULT
else
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
wait_for_wrapper
WAITFORIT_RESULT=$?
else
wait_for
WAITFORIT_RESULT=$?
fi
fi
if [[ $WAITFORIT_CLI != "" ]]; then
if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
exit $WAITFORIT_RESULT
fi
exec "${WAITFORIT_CLI[@]}"
else
exit $WAITFORIT_RESULT
fi
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment