From 5a216f53827603880647a1ca90ba78a6453418b5 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Tue, 10 Mar 2026 02:30:41 +0300 Subject: [PATCH] New Docker config --- .gitignore | 7 - Makefile | 160 ++++++++ composer.json | 24 +- composer.lock | 483 +---------------------- config/authclients.php | 33 ++ config/authclients.php-orig | 19 - config/db.php | 12 + config/db.php-orig | 12 - config/key.php-orig | 2 - config/params-local.php-orig | 24 -- config/params.php | 58 ++- config/rollbar.php-orig | 7 - config/web.php | 17 +- docker/Dockerfile | 62 +++ docker/compose.yml | 8 + docker/crontab | 1 - docker/dev/.gitignore | 1 + docker/dev/compose.yml | 49 +++ docker/dev/override.env.example | 1 + docker/docker-cron-entrypoint | 7 - docker/nginx/Dockerfile | 8 - docker/nginx/local/yiipowered.conf | 31 -- docker/php-fpm-www-pool.conf | 26 -- docker/php/Dockerfile | 55 --- docker/prod/.gitignore | 1 + docker/prod/compose.yml | 39 ++ docker/test/.gitignore | 1 + docker/test/compose.yml | 19 + {web => public}/assets/.gitignore | 0 {web => public}/favicon.ico | Bin {web => public}/img/avatar/.gitignore | 0 {web => public}/img/project/.gitignore | 0 {web => public}/img/project_no_image.png | Bin {web => public}/img/yii-logo.png | Bin public/index.php | 11 + {web => public}/robots.txt | 0 web/index.php | 12 - yii | 4 +- 38 files changed, 473 insertions(+), 721 deletions(-) create mode 100644 Makefile create mode 100644 config/authclients.php delete mode 100644 config/authclients.php-orig create mode 100644 config/db.php delete mode 100644 config/db.php-orig delete mode 100644 config/key.php-orig delete mode 100644 config/params-local.php-orig delete mode 100644 config/rollbar.php-orig create mode 100644 docker/Dockerfile create mode 100644 docker/compose.yml delete mode 100644 docker/crontab create mode 100644 docker/dev/.gitignore create mode 100644 docker/dev/compose.yml create mode 100644 docker/dev/override.env.example delete mode 100644 docker/docker-cron-entrypoint delete mode 100644 docker/nginx/Dockerfile delete mode 100644 docker/nginx/local/yiipowered.conf delete mode 100644 docker/php-fpm-www-pool.conf delete mode 100644 docker/php/Dockerfile create mode 100644 docker/prod/.gitignore create mode 100644 docker/prod/compose.yml create mode 100644 docker/test/.gitignore create mode 100644 docker/test/compose.yml rename {web => public}/assets/.gitignore (100%) rename {web => public}/favicon.ico (100%) rename {web => public}/img/avatar/.gitignore (100%) rename {web => public}/img/project/.gitignore (100%) rename {web => public}/img/project_no_image.png (100%) rename {web => public}/img/yii-logo.png (100%) create mode 100644 public/index.php rename {web => public}/robots.txt (100%) delete mode 100644 web/index.php diff --git a/.gitignore b/.gitignore index e70012e..b5519ee 100644 --- a/.gitignore +++ b/.gitignore @@ -29,13 +29,6 @@ phpunit.phar tests/_output/* tests/_support/_generated -# local configs -/config/key.php -/config/db.php -/config/authclients.php -/config/rollbar.php -/config/params-local.php - # IDEs other settings .data diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f390e95 --- /dev/null +++ b/Makefile @@ -0,0 +1,160 @@ +CLI_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +$(eval $(sort $(subst :,\:,$(CLI_ARGS))):;@:) + +PRIMARY_GOAL := $(firstword $(MAKECMDGOALS)) +ifeq ($(PRIMARY_GOAL),) + PRIMARY_GOAL := help +endif + +include docker/.env + +# Current user ID and group ID except MacOS where it conflicts with Docker abilities +ifeq ($(shell uname), Darwin) + export UID=1000 + export GID=1000 +else + export UID=$(shell id -u) + export GID=$(shell id -g) +endif + +export COMPOSE_PROJECT_NAME=${STACK_NAME} +DOCKER_COMPOSE_DEV := docker compose -f docker/compose.yml -f docker/dev/compose.yml +DOCKER_COMPOSE_TEST := docker compose -f docker/compose.yml -f docker/test/compose.yml + +# +# Development +# + +ifeq ($(PRIMARY_GOAL),build) +build: ## Build docker images. + $(DOCKER_COMPOSE_DEV) build $(CLI_ARGS) +endif + +ifeq ($(PRIMARY_GOAL),up) +up: ## Up the dev environment. + $(DOCKER_COMPOSE_DEV) up -d --remove-orphans +endif + +ifeq ($(PRIMARY_GOAL),down) +down: ## Down the dev environment. + $(DOCKER_COMPOSE_DEV) down --remove-orphans +endif + +ifeq ($(PRIMARY_GOAL),stop) +stop: ## Stop the dev environment. + $(DOCKER_COMPOSE_DEV) stop +endif + +ifeq ($(PRIMARY_GOAL),clear) +clear: ## Remove development docker containers and volumes. + $(DOCKER_COMPOSE_DEV) down --volumes --remove-orphans +endif + +ifeq ($(PRIMARY_GOAL),shell) +shell: ## Get into container shell. + $(DOCKER_COMPOSE_DEV) exec app /bin/bash +endif + +# +# Tools +# + +ifeq ($(PRIMARY_GOAL),yii) +yii: ## Execute Yii command. + $(DOCKER_COMPOSE_DEV) run --rm app ./yii $(CLI_ARGS) +.PHONY: yii +endif + +ifeq ($(PRIMARY_GOAL),composer) +composer: ## Run Composer. + $(DOCKER_COMPOSE_DEV) run --rm app composer $(CLI_ARGS) +endif + +ifeq ($(PRIMARY_GOAL),rector) +rector: ## Run Rector. + $(DOCKER_COMPOSE_DEV) run --rm app ./vendor/bin/rector $(CLI_ARGS) +endif + +ifeq ($(PRIMARY_GOAL),cs-fix) +cs-fix: ## Run PHP CS Fixer. + $(DOCKER_COMPOSE_DEV) run --rm app ./vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --diff +endif + +# +# Tests and analysis +# + +ifeq ($(PRIMARY_GOAL),test) +test: ## Run tests. + $(DOCKER_COMPOSE_TEST) run --rm app ./vendor/bin/codecept run $(CLI_ARGS) +endif + +ifeq ($(PRIMARY_GOAL),test-coverage) +test-coverage: ## Run tests with coverage. + $(DOCKER_COMPOSE_TEST) run --rm app ./vendor/bin/codecept run --coverage --coverage-html --disable-coverage-php +endif + +ifeq ($(PRIMARY_GOAL),codecept) +codecept: ## Run Codeception. + $(DOCKER_COMPOSE_TEST) run --rm app ./vendor/bin/codecept $(CLI_ARGS) +endif + +ifeq ($(PRIMARY_GOAL),psalm) +psalm: ## Run Psalm. + $(DOCKER_COMPOSE_DEV) run --rm app ./vendor/bin/psalm $(CLI_ARGS) +endif + +ifeq ($(PRIMARY_GOAL),composer-dependency-analyser) +composer-dependency-analyser: ## Run Composer Dependency Analyser. + $(DOCKER_COMPOSE_DEV) run --rm app ./vendor/bin/composer-dependency-analyser --config=composer-dependency-analyser.php $(CLI_ARGS) +endif + +# +# Production +# + +ifeq ($(PRIMARY_GOAL),prod-build) +prod-build: ## Build an image. + docker build --file docker/Dockerfile --target prod --pull -t ${IMAGE}:${IMAGE_TAG} . +endif + +ifeq ($(PRIMARY_GOAL),prod-push) +prod-push: ## Push image to repository. + docker push ${IMAGE}:${IMAGE_TAG} +endif + +ifeq ($(PRIMARY_GOAL),prod-deploy) +prod-deploy: ## Deploy to production. + set -euo pipefail \ + docker -H ${PROD_SSH} stack deploy --prune --detach=false --with-registry-auth -c docker/compose.yml -c docker/prod/compose.yml ${STACK_NAME} 2>&1 | tee deploy.log \ + if grep -qiE 'rollback:|update rolled back' deploy.log then \ + FAILED_TASK_ID="$(grep -oiE 'task[[:space:]]+[a-z0-9]+' deploy.log | head -n 1 | awk '{print $2}')" \ + if [ -n "${FAILED_TASK_ID}" ]; then \ + echo "Docker Swarm update rolled back; failing job. Failed task ID: ${FAILED_TASK_ID}" \ + echo "--- docker service logs (${FAILED_TASK_ID}) ---" \ + docker -H ${PROD_SSH} service logs --timestamps --tail 500 "${FAILED_TASK_ID}" || true \ + else \ + echo 'Docker Swarm update rolled back; failing job. Failed task ID: not found in deploy output.' \ + fi \ + exit 1 \ + fi +endif + +# +# Other +# + +ifeq ($(PRIMARY_GOAL),help) +help: ## This help. + @awk 'BEGIN { printf "\nUsage:\n make \033[36m\033[0m\n" } \ + /^#$$/ { blank = 1; next } \ + blank && /^# [a-zA-Z]/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 3); blank = 0; next } \ + /^[a-zA-Z_-]+:([^=]|$$)/ { \ + split($$0, parts, "##"); \ + target = parts[1]; sub(/:.*/, "", target); \ + desc = parts[2]; \ + gsub(/^[[:space:]]+|[[:space:]]+$$/, "", desc); \ + printf " \033[36m%-25s\033[0m %s\n", target, desc; \ + blank = 0; \ + }' $(MAKEFILE_LIST) +endif \ No newline at end of file diff --git a/composer.json b/composer.json index 2d776b5..10a78de 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "license": "BSD-3-Clause", "minimum-stability": "stable", "require": { - "php": ">=7.0.0", + "php": ">=8.4.0", "yiisoft/yii2": "~2.0.35", "yiisoft/yii2-bootstrap": "~2.0.6", "yiisoft/yii2-swiftmailer": "~2.0.6", @@ -25,8 +25,7 @@ "bower-asset/font-awesome": "~4.7.0.0", "claviska/simpleimage": "^3.3", "abraham/twitteroauth": "^2.0.2", - "yiisoft/yii2-queue": "~2.3.3", - "vlucas/phpdotenv": "^5.6" + "yiisoft/yii2-queue": "~2.3.3" }, "require-dev": { "yiisoft/yii2-debug": "~2.1.13", @@ -41,25 +40,6 @@ "block-insecure": false } }, - "scripts": { - "post-create-project-cmd": [ - "yii\\composer\\Installer::postCreateProject" - ] - }, - "extra": { - "yii\\composer\\Installer::postCreateProject": { - "setPermission": [ - { - "runtime": "0777", - "web/assets": "0777", - "yii": "0755" - } - ], - "generateCookieValidationKey": [ - "config/web.php" - ] - } - }, "repositories": [ { "type": "composer", diff --git a/composer.lock b/composer.lock index 278d3ce..2cce0c2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f2398a665af93f926dd046ad613dfab8", + "content-hash": "329d860591f469a1ec021cda61dafd86", "packages": [ { "name": "abraham/twitteroauth", @@ -199,7 +199,7 @@ "version": "v4.7.0", "source": { "type": "git", - "url": "git@github.com:FortAwesome/Font-Awesome.git", + "url": "https://github.com/FortAwesome/Font-Awesome.git", "reference": "a8386aae19e200ddb0f6845b5feeee5eb7013687" }, "dist": { @@ -258,7 +258,7 @@ "version": "1.12.1", "source": { "type": "git", - "url": "git@github.com:components/jqueryui.git", + "url": "https://github.com/components/jqueryui.git", "reference": "44ecf3794cc56b65954cc19737234a3119d036cc" }, "dist": { @@ -330,7 +330,7 @@ "version": "2.0.9", "source": { "type": "git", - "url": "git@github.com:yiisoft/jquery-pjax.git", + "url": "https://github.com/yiisoft/jquery-pjax.git", "reference": "452b56b7124326487fd0d3be6b205fcaa66598a0" }, "dist": { @@ -730,68 +730,6 @@ }, "time": "2025-10-17T16:34:55+00:00" }, - { - "name": "graham-campbell/result-type", - "version": "v1.1.4", - "source": { - "type": "git", - "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b", - "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.5" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7" - }, - "type": "library", - "autoload": { - "psr-4": { - "GrahamCampbell\\ResultType\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - } - ], - "description": "An Implementation Of The Result Type", - "keywords": [ - "Graham Campbell", - "GrahamCampbell", - "Result Type", - "Result-Type", - "result" - ], - "support": { - "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", - "type": "tidelift" - } - ], - "time": "2025-12-27T19:43:20+00:00" - }, { "name": "league/color-extractor", "version": "0.3.2", @@ -1002,81 +940,6 @@ }, "time": "2020-10-15T08:29:30+00:00" }, - { - "name": "phpoption/phpoption", - "version": "1.9.5", - "source": { - "type": "git", - "url": "https://github.com/schmittjoh/php-option.git", - "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", - "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - }, - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpOption\\": "src/PhpOption/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com", - "homepage": "https://github.com/schmittjoh" - }, - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - } - ], - "description": "Option Type for PHP", - "keywords": [ - "language", - "option", - "php", - "type" - ], - "support": { - "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.5" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", - "type": "tidelift" - } - ], - "time": "2025-12-27T19:41:33+00:00" - }, { "name": "psr/log", "version": "1.1.4", @@ -1250,258 +1113,6 @@ "abandoned": "symfony/mailer", "time": "2018-07-31T09:26:32+00:00" }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-12-23T08:48:59+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-01-02T08:10:11+00:00" - }, { "name": "symfony/process", "version": "v7.4.5", @@ -1567,90 +1178,6 @@ ], "time": "2026-01-26T15:07:59+00:00" }, - { - "name": "vlucas/phpdotenv", - "version": "v5.6.3", - "source": { - "type": "git", - "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "955e7815d677a3eaa7075231212f2110983adecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", - "reference": "955e7815d677a3eaa7075231212f2110983adecc", - "shasum": "" - }, - "require": { - "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.4", - "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.5", - "symfony/polyfill-ctype": "^1.26", - "symfony/polyfill-mbstring": "^1.26", - "symfony/polyfill-php80": "^1.26" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "ext-filter": "*", - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" - }, - "suggest": { - "ext-filter": "Required to use the boolean validator." - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - }, - "branch-alias": { - "dev-master": "5.6-dev" - } - }, - "autoload": { - "psr-4": { - "Dotenv\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Vance Lucas", - "email": "vance@vancelucas.com", - "homepage": "https://github.com/vlucas" - } - ], - "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", - "keywords": [ - "dotenv", - "env", - "environment" - ], - "support": { - "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", - "type": "tidelift" - } - ], - "time": "2025-12-27T19:49:13+00:00" - }, { "name": "yiisoft/yii2", "version": "2.0.54", @@ -2576,7 +2103,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.0.0" + "php": ">=8.4.0" }, "platform-dev": {}, "plugin-api-version": "2.9.0" diff --git a/config/authclients.php b/config/authclients.php new file mode 100644 index 0000000..9a3961d --- /dev/null +++ b/config/authclients.php @@ -0,0 +1,33 @@ + GitHub::class, + 'clientId' => $githubClientId, + 'clientSecret' => $githubClientSecret, + 'scope' => 'user:email', + ]; +} + +if ($twitterConsumerKey !== null && $twitterConsumerSecret !== null) { + $clients['twitter'] = [ + 'class' => Twitter::class, + 'attributeParams' => [ + 'include_email' => 'true' + ], + 'consumerKey' => $twitterConsumerKey, + 'consumerSecret' => $twitterConsumerSecret, + ]; +} + +return $clients; diff --git a/config/authclients.php-orig b/config/authclients.php-orig deleted file mode 100644 index 93d4c1f..0000000 --- a/config/authclients.php-orig +++ /dev/null @@ -1,19 +0,0 @@ - [ - 'class' => GitHub::class, - 'clientId' => 'client_id', - 'clientSecret' => 'client_secret_key', - 'scope' => 'user:email', - ], - 'twitter' => [ - 'class' => \yii\authclient\clients\Twitter::class, - 'attributeParams' => [ - 'include_email' => 'true' - ], - 'consumerKey' => 'twitter_consumer_key', - 'consumerSecret' => 'twitter_consumer_secret', - ], -]; \ No newline at end of file diff --git a/config/db.php b/config/db.php new file mode 100644 index 0000000..34588ee --- /dev/null +++ b/config/db.php @@ -0,0 +1,12 @@ + Connection::class, + 'dsn' => 'mysql:host=' . $_ENV['DB_HOST'] . ';port=' . $_ENV['DB_PORT'] . ';dbname=' . $_ENV['DB_NAME'], + 'username' => $_ENV['DB_USERNAME'], + 'password' => $_ENV['DB_PASSWORD'], + 'charset' => 'utf8', + 'enableSchemaCache' => !$_ENV['APP_DEBUG'], +]; diff --git a/config/db.php-orig b/config/db.php-orig deleted file mode 100644 index 4aa86ba..0000000 --- a/config/db.php-orig +++ /dev/null @@ -1,12 +0,0 @@ - Connection::class, - 'dsn' => getenv('DB_DSN'), - 'username' => getenv('DB_USERNAME'), - 'password' => getenv('DB_PASSWORD'), - 'charset' => 'utf8', - 'enableSchemaCache' => true, -]; diff --git a/config/key.php-orig b/config/key.php-orig deleted file mode 100644 index 39926b2..0000000 --- a/config/key.php-orig +++ /dev/null @@ -1,2 +0,0 @@ - 'https://yiipowered.com', - - /** - * @see https://apps.twitter.com/app/new - * - * After creating an app you need to fill accessToken and accessTokenSecret: - * - * Open App -> Keys and Access Tokens -> You Access Token -> Create my access token - */ - 'twitter.consumerKey' => '', - 'twitter.consumerSecret' => '', - 'twitter.accessToken' => '', - 'twitter.accessTokenSecret' => '', - - // get these at https://screenshotlayer.com/dashboard - 'screenshotLayer.secret' => '', - 'screenshotLayer.accessKey' => '', - - // get these at https://apiflash.com/documentation#access - 'apiFlash.accessKey' => '', -]; diff --git a/config/params.php b/config/params.php index c3e7239..25a949c 100644 --- a/config/params.php +++ b/config/params.php @@ -2,6 +2,7 @@ use codemix\localeurls\UrlManager; use yii\helpers\ArrayHelper; +use yii\queue\db\Queue; use yii\web\UrlNormalizer; $languages = [ @@ -13,7 +14,7 @@ 'de' => ['de-DE', 'Deutsch'], ]; -return [ +$params = [ 'adminEmail' => 'sam+yiipowered@rmcreative.ru', 'notificationEmail' => 'noreply@yiipowered.com', 'supportEmail' => 'noreply@yiipowered.com', @@ -48,7 +49,7 @@ ], ], 'components.queue' => [ - 'class' => \yii\queue\db\Queue::class, + 'class' => Queue::class, 'channel' => 'default' ], @@ -58,5 +59,56 @@ 'HtmlPurifier.projectComment' => [ 'HTML.Allowed' => 'h1,h2,h3,h4,h5,h6,p,ul,ol,li,b,i,u,strong,br,sub,sup,a[href],img[src]', ], - ]; + +$appAbsoluteUrl = $_ENV['APP_ABSOLUTE_URL'] ?? null; +if ($appAbsoluteUrl) { + $params['siteAbsoluteUrl'] = $appAbsoluteUrl; +} + +/* + * @see https://apps.twitter.com/app/new + * + * After creating an app you need to fill accessToken and accessTokenSecret: + * + * Open App -> Keys and Access Tokens -> You Access Token -> Create my access token + */ +$twitterConsumerKey = $_ENV['TWITTER_CONSUMER_KEY'] ?? null; +if ($twitterConsumerKey !== null) { + $params['twitter.consumerKey'] = $twitterConsumerKey; +} + +$twitterConsumerSecret = $_ENV['TWITTER_CONSUMER_SECRET'] ?? null; +if ($twitterConsumerSecret !== null) { + $params['twitter.consumerSecret'] = $twitterConsumerSecret; +} + +$twitterAccessToken = $_ENV['TWITTER_ACCESS_TOKEN'] ?? null; +if ($twitterAccessToken !== null) { + $params['twitter.accessToken'] = $twitterAccessToken; +} + +$twitterAccessTokenSecret = $_ENV['TWITTER_ACCESS_TOKEN_SECRET'] ?? null; +if ($twitterAccessTokenSecret !== null) { + $params['twitter.accessTokenSecret'] = $twitterAccessTokenSecret; +} + + +// get these at https://screenshotlayer.com/dashboard +$screenshotLayerSecret = $_ENV['SCREENSHOT_LAYER_SECRET'] ?? null; +if ($screenshotLayerSecret !== null) { + $params['screenshotLayer.secret'] = $screenshotLayerSecret; +} + +$screenshotLayerAccessKey = $_ENV['SCREENSHOT_LAYER_ACCESS_KEY'] ?? null; +if ($screenshotLayerAccessKey !== null) { + $params['screenshotLayer.accessKey'] = $screenshotLayerAccessKey; +} + +// get these at https://apiflash.com/documentation#access +$apiFlashAccessKey = $_ENV['API_FLASH_ACCESS_KEY'] ?? null; +if ($apiFlashAccessKey !== null) { + $params['apiFlash.accessKey'] = $apiFlashAccessKey; +} + +return $params; \ No newline at end of file diff --git a/config/rollbar.php-orig b/config/rollbar.php-orig deleted file mode 100644 index bbad46e..0000000 --- a/config/rollbar.php-orig +++ /dev/null @@ -1,7 +0,0 @@ - Rollbar::class, - 'accessToken' => 'token_should_be_here', -]; \ No newline at end of file diff --git a/config/web.php b/config/web.php index 4280408..1737a8e 100644 --- a/config/web.php +++ b/config/web.php @@ -1,5 +1,6 @@ PhpManager::class, ], 'request' => [ - // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation - 'cookieValidationKey' => require __DIR__ . '/key.php', + 'cookieValidationKey' => $_ENV['COOKIE_KEY'], ], 'cache' => [ 'class' => FileCache::class, @@ -77,7 +77,7 @@ 'mailer' => [ 'class' => Mailer::class, // send all mails to a file by default. You have to set - // 'useFileTransport' to false and configure a transport + // 'useFileTransport' to false and configure transport // for the mailer to send real emails. 'useFileTransport' => YII_DEBUG, ], @@ -129,8 +129,15 @@ $config['bootstrap'][] = 'gii'; $config['modules']['gii'] = Module::class; -} else { - $config['components']['rollbar'] = require __DIR__ . '/rollbar.php'; +} + +$rollbarToken = $_ENV['ROLLBAR_TOKEN'] ?? null; + +if ($rollbarToken !== null) { + $config['components']['rollbar'] = [ + 'class' => Rollbar::class, + 'accessToken' => $rollbarToken, + ]; $config['bootstrap'][] = 'rollbar'; $config['components']['errorHandler']['class'] = ErrorHandler::class; } diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..bf44c34 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,62 @@ +FROM composer/composer:2-bin AS composer + +FROM dunglas/frankenphp:1-php8.4-trixie AS base + +RUN apt update && apt -y install \ + unzip \ + nodejs \ + npm + +RUN npm install -g less + +RUN install-php-extensions \ + zip \ + intl \ + opcache \ + xml \ + pdo \ + pdo_mysql \ + gd + +ENV LC_ALL=C.UTF-8 + +# +# Development +# + +FROM base AS dev +ARG USER_ID=10001 +ARG GROUP_ID=10001 +ARG USER_NAME=appuser +ARG GROUP_NAME=appuser + +RUN install-php-extensions \ + xdebug + +COPY --from=composer /composer /usr/bin/composer + +# Based on https://frankenphp.dev/docs/docker/#running-as-a-non-root-user +RUN \ + groupadd --gid ${GROUP_ID} ${GROUP_NAME}; \ + useradd --gid ${GROUP_ID} --uid ${USER_ID} ${GROUP_NAME}; \ + # Add additional capability to bind to port 80 and 443 \ + setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp; \ + # Give write access to /data/caddy and /config/caddy \ + chown -R ${USER_NAME}:${GROUP_NAME} /data/caddy && chown -R ${USER_NAME}:${GROUP_NAME} /config/caddy +USER ${USER_NAME} + +# +# Production +# + +FROM base AS prod-builder +COPY --from=composer /composer /usr/bin/composer +COPY .. /app +RUN --mount=type=cache,target=/tmp/cache \ + composer install --no-dev --no-progress --no-interaction --classmap-authoritative && \ + rm composer.lock composer.json + +FROM base AS prod +ENV APP_ENV=prod +COPY --from=prod-builder --chown=www-data:www-data /app /app +USER www-data \ No newline at end of file diff --git a/docker/compose.yml b/docker/compose.yml new file mode 100644 index 0000000..2e1df5a --- /dev/null +++ b/docker/compose.yml @@ -0,0 +1,8 @@ +services: + app: &appconfig + extra_hosts: + - "host.docker.internal:host-gateway" + +volumes: + caddy_data: + caddy_config: \ No newline at end of file diff --git a/docker/crontab b/docker/crontab deleted file mode 100644 index 8b13789..0000000 --- a/docker/crontab +++ /dev/null @@ -1 +0,0 @@ - diff --git a/docker/dev/.gitignore b/docker/dev/.gitignore new file mode 100644 index 0000000..aff6691 --- /dev/null +++ b/docker/dev/.gitignore @@ -0,0 +1 @@ +/override.env \ No newline at end of file diff --git a/docker/dev/compose.yml b/docker/dev/compose.yml new file mode 100644 index 0000000..d59c481 --- /dev/null +++ b/docker/dev/compose.yml @@ -0,0 +1,49 @@ +services: + app: + build: + dockerfile: docker/Dockerfile + context: .. + target: dev + args: + USER_ID: ${UID} + GROUP_ID: ${GID} + env_file: + - path: ./dev/.env + - path: ./dev/override.env + required: false + environment: + DB_HOST: 'db' + DB_NAME: ${DEV_DB_NAME} + DB_PORT: 3306 + DB_USERNAME: 'root' + DB_PASSWORD: ${DEV_DB_PASSWORD} + COOKIE_KEY: 'cookie_key' + ports: + - "${DEV_PORT:-80}:80" + volumes: + - ../:/app + - ../runtime:/app/runtime + - caddy_data:/data + - caddy_config:/config + tty: true + depends_on: + db: + condition: service_healthy + + db: + image: mariadb:lts + restart: always + healthcheck: + test: [ "CMD", "healthcheck.sh", "--connect", "--innodb_initialized" ] + start_period: 10s + interval: 10s + timeout: 5s + retries: 3 + ports: + - "${DEV_DB_PORT}:3306" + environment: + MARIADB_DATABASE: ${DEV_DB_NAME} + MARIADB_ROOT_PASSWORD: ${DEV_DB_PASSWORD} + MARIADB_AUTO_UPGRADE: 1 + volumes: + - "../runtime/db:/var/lib/mysql:Z" \ No newline at end of file diff --git a/docker/dev/override.env.example b/docker/dev/override.env.example new file mode 100644 index 0000000..5f9591c --- /dev/null +++ b/docker/dev/override.env.example @@ -0,0 +1 @@ +APP_HOST_PATH=/projects/yiisoft/app \ No newline at end of file diff --git a/docker/docker-cron-entrypoint b/docker/docker-cron-entrypoint deleted file mode 100644 index fb6f90d..0000000 --- a/docker/docker-cron-entrypoint +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -set -e - -# see: https://github.com/dubiousjim/dcron/issues/13 -# ignore using `exec` for `dcron` to get another pid instead of `1` -# exec "$@" -"$@" diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile deleted file mode 100644 index a2d7d15..0000000 --- a/docker/nginx/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM nginx:1.19-alpine - -# nginx user must be in www-data group -# to have access to PHP socket -RUN adduser nginx www-data \ - && echo "server_tokens off;" >> /etc/nginx/conf.d/privacy.conf - -ADD ./local /etc/nginx/conf.d \ No newline at end of file diff --git a/docker/nginx/local/yiipowered.conf b/docker/nginx/local/yiipowered.conf deleted file mode 100644 index 47f946e..0000000 --- a/docker/nginx/local/yiipowered.conf +++ /dev/null @@ -1,31 +0,0 @@ -server_names_hash_bucket_size 1024; - -server { - listen 80; - listen [::]:80; - - server_name yiipowered.test; - - client_max_body_size 10M; - - root /var/www/web; - - index index.php index.html index.htm; - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - - location ~ \.php$ { - try_files $uri =404; - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:/var/run/php/php-fpm.sock; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; - } - - location ~ /\.ht { - deny all; - } -} diff --git a/docker/php-fpm-www-pool.conf b/docker/php-fpm-www-pool.conf deleted file mode 100644 index d128bed..0000000 --- a/docker/php-fpm-www-pool.conf +++ /dev/null @@ -1,26 +0,0 @@ -[global] -daemonize = no - -[www] -user = www-data -group = www-data - -clear_env = no - -listen = /var/run/php/php-fpm.sock -listen.owner = www-data -listen.group = www-data -listen.mode = 0660 - -pm = dynamic -pm.max_children = 100 -pm.start_servers = 15 -pm.min_spare_servers = 15 -pm.max_spare_servers = 100 - -pm.process_idle_timeout = 10s; -pm.max_requests = 5000 - -chdir = / - -access.log = /dev/null diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile deleted file mode 100644 index 3c34798..0000000 --- a/docker/php/Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -FROM php:8.4-fpm-alpine - -RUN apk update --no-cache \ - && apk add --no-cache \ - autoconf \ - bash \ - dcron \ - icu-dev \ - libzip-dev \ - zip \ - libxml2-dev \ - nano \ - libpng libpng-dev libjpeg-turbo-dev libwebp-dev zlib-dev libxpm-dev \ - npm \ - && docker-php-ext-install -j$(nproc) \ - zip \ - intl \ - opcache \ - xml \ - pdo \ - pdo_mysql \ - gd \ - && apk add --no-cache $PHPIZE_DEPS linux-headers \ - && pecl install xdebug \ - && docker-php-ext-enable xdebug \ - && apk del libpng-dev libjpeg-turbo-dev libwebp-dev zlib-dev libxpm-dev $PHPIZE_DEPS linux-headers \ - && mv $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini \ - && sed -i "s/expose_php = On/expose_php = Off/g" $PHP_INI_DIR/php.ini \ - && echo "xdebug.mode=debug" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ - && echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ - && echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ - && rm /usr/local/etc/php-fpm.d/zz-docker.conf \ - && npm -g install less - -COPY --from=composer:2 /usr/bin/composer /usr/bin/composer - -WORKDIR /var/www - -COPY . . - -ENV COMPOSER_MEMORY_LIMIT -1 -RUN composer install - -COPY ./docker/php-fpm-www-pool.conf /usr/local/etc/php-fpm.d/www.conf -COPY ./docker/docker-cron-entrypoint /usr/local/bin/docker-cron-entrypoint - -RUN chmod 777 /var/www/docker/crontab \ - && crontab /var/www/docker/crontab \ - && chown -R www-data:www-data /var/www/runtime \ - && chown -R www-data:www-data /var/www/assets \ - && chmod -R 777 /usr/local/bin/docker-cron-entrypoint - -# Make binaries from composer packages -# available without path prefixes -ENV PATH ./vendor/bin:$PATH diff --git a/docker/prod/.gitignore b/docker/prod/.gitignore new file mode 100644 index 0000000..aff6691 --- /dev/null +++ b/docker/prod/.gitignore @@ -0,0 +1 @@ +/override.env \ No newline at end of file diff --git a/docker/prod/compose.yml b/docker/prod/compose.yml new file mode 100644 index 0000000..70e8b6a --- /dev/null +++ b/docker/prod/compose.yml @@ -0,0 +1,39 @@ +services: + app: + image: ${IMAGE}:${IMAGE_TAG} + networks: + - caddy_public + volumes: + - runtime:/app/runtime + - caddy_data:/data + - caddy_config:/config + env_file: + - path: ./prod/.env + - path: ./prod/override.env + required: false + deploy: + replicas: 2 + update_config: + delay: 10s + parallelism: 1 + order: start-first + failure_action: rollback + monitor: 10s + rollback_config: + parallelism: 0 + order: stop-first + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + window: 120s + labels: + caddy: ${PROD_HOST:-app.example.com} + caddy.reverse_proxy: "{{upstreams 80}}" + +volumes: + runtime: + +networks: + caddy_public: + external: true \ No newline at end of file diff --git a/docker/test/.gitignore b/docker/test/.gitignore new file mode 100644 index 0000000..aff6691 --- /dev/null +++ b/docker/test/.gitignore @@ -0,0 +1 @@ +/override.env \ No newline at end of file diff --git a/docker/test/compose.yml b/docker/test/compose.yml new file mode 100644 index 0000000..7c06c13 --- /dev/null +++ b/docker/test/compose.yml @@ -0,0 +1,19 @@ +services: + app: + build: + dockerfile: docker/Dockerfile + context: .. + target: dev + args: + USER_ID: ${UID} + GROUP_ID: ${GID} + env_file: + - path: ./test/.env + - path: ./test/override.env + required: false + volumes: + - ../:/app + - ../runtime:/app/runtime + - caddy_data:/data + - caddy_config:/config + tty: true \ No newline at end of file diff --git a/web/assets/.gitignore b/public/assets/.gitignore similarity index 100% rename from web/assets/.gitignore rename to public/assets/.gitignore diff --git a/web/favicon.ico b/public/favicon.ico similarity index 100% rename from web/favicon.ico rename to public/favicon.ico diff --git a/web/img/avatar/.gitignore b/public/img/avatar/.gitignore similarity index 100% rename from web/img/avatar/.gitignore rename to public/img/avatar/.gitignore diff --git a/web/img/project/.gitignore b/public/img/project/.gitignore similarity index 100% rename from web/img/project/.gitignore rename to public/img/project/.gitignore diff --git a/web/img/project_no_image.png b/public/img/project_no_image.png similarity index 100% rename from web/img/project_no_image.png rename to public/img/project_no_image.png diff --git a/web/img/yii-logo.png b/public/img/yii-logo.png similarity index 100% rename from web/img/yii-logo.png rename to public/img/yii-logo.png diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..6ebd34f --- /dev/null +++ b/public/index.php @@ -0,0 +1,11 @@ +run(); diff --git a/web/robots.txt b/public/robots.txt similarity index 100% rename from web/robots.txt rename to public/robots.txt diff --git a/web/index.php b/web/index.php deleted file mode 100644 index 02d5e1d..0000000 --- a/web/index.php +++ /dev/null @@ -1,12 +0,0 @@ -run(); diff --git a/yii b/yii index 2a2e8ed..915b880 100755 --- a/yii +++ b/yii @@ -8,8 +8,8 @@ * @license http://www.yiiframework.com/license/ */ -defined('YII_DEBUG') or define('YII_DEBUG', true); -defined('YII_ENV') or define('YII_ENV', 'dev'); +defined('YII_DEBUG') or define('YII_DEBUG', $_ENV['APP_DEBUG'] ?? true); +defined('YII_ENV') or define('YII_ENV', $_ENV['APP_ENV'] ?? 'dev'); require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';