diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..2e2b20d
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,15 @@
+# Ignore everything
+*
+
+# except:
+
+!/config
+!/public
+!/src
+!/vendor
+!autoload.php
+!configuration.php
+!yii
+!composer.json
+!composer.lock
+!.env*
diff --git a/.gitignore b/.gitignore
index aaf6784..2d4aeb0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,7 +34,7 @@ phpunit.phar
# NPM packages
/node_modules
-.env
+/.env
# Codeception
c3.php
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..e1ada0f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,59 @@
+.DEFAULT_GOAL := help
+
+# Run silent.
+MAKEFLAGS += --silent
+
+RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
+$(eval $(RUN_ARGS):;@:)
+
+include docker/.env
+
+# Current user ID and group ID.
+export UID=$(shell id -u)
+export GID=$(shell id -g)
+
+export COMPOSE_PROJECT_NAME=${STACK_NAME}
+
+up: ## Up the dev environment.
+ docker compose -f docker/compose.yml -f docker/compose.dev.yml up -d --remove-orphans
+
+up-build: ## Up the dev environment rebuilding images.
+ docker compose -f docker/compose.yml -f docker/compose.dev.yml up -d --remove-orphans --build
+
+down: ## Down the dev environment.
+ docker compose -f docker/compose.yml -f docker/compose.dev.yml down --remove-orphans
+
+exec: ## Run a command within the existing container.
+ docker compose -f docker/compose.yml -f docker/compose.dev.yml exec app $(CMD) $(RUN_ARGS)
+
+run: ## Run a command within a temporary container.
+ docker compose -f docker/compose.yml -f docker/compose.dev.yml run --rm --entrypoint $(CMD) app $(RUN_ARGS)
+
+shell: CMD="/bin/sh" ## Get into container shell.
+shell: exec
+
+yii: CMD="./yii" ## Execute Yii command.
+yii: run
+
+composer: CMD="composer" ## Run Composer.
+composer: run
+
+codecept: CMD="./vendor/bin/codecept" ## Run Codeception.
+codecept: run
+
+psalm: CMD="./vendor/bin/psalm" ## Run Psalm.
+psalm: run
+
+build-prod: ## Build an image.
+ docker build --file docker/Dockerfile --target prod --pull -t ${IMAGE}:${IMAGE_TAG} .
+
+push-prod: ## Push image to repository.
+ docker push ${IMAGE}:${IMAGE_TAG}
+
+deploy-prod: ## Deploy to production.
+ docker -H ${PROD_SSH} stack deploy --with-registry-auth -d -c docker/compose.yml -c docker/compose.prod.yml ${STACK_NAME}
+
+# Output the help for each task, see https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
+.PHONY: help
+help: ## This help.
+ @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
diff --git a/README.md b/README.md
index d5f016d..3b4fc2b 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,8 @@
[![static analysis](https://github.com/yiisoft/app/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/app/actions?query=workflow%3A%22static+analysis%22)
[![type-coverage](https://shepherd.dev/github/yiisoft/app/coverage.svg)](https://shepherd.dev/github/yiisoft/app)
+Web application template for Yii 3.
+
@@ -24,32 +26,57 @@
- PHP 8.1 or higher.
-## Installation
+## Local installation
If you do not have [Composer](https://getcomposer.org/), you may install it by following the instructions
at [getcomposer.org](https://getcomposer.org/doc/00-intro.md).
-You can then install this project template using the following command:
+Create a project:
```shell
-composer create-project --stability=dev yiisoft/app
+composer create-project --stability=dev yiisoft/app myproject
+cd myproject
```
-In order to launch development web server run:
+To run the app:
-```shell
-composer run serve
+```
+./yii serve
```
Now you should be able to access the application through the URL printed to console.
Usually it is `http://localhost:8080`.
+## Installation with Docker
+
+Fork the repository, clone it, then:
+
+```shell
+cd myproject
+make composer update
+```
+
+To run the app:
+
+```shell
+make up
+```
+
+To stop the app:
+
+```shell
+make down
+```
+
+The application is available at `https://localhost`.
+
## Directory structure
The application template has the following structure:
```
config/ Configuration files.
+docker/ Docker-specific files.
docs/ Documentation.
public/ Files publically accessible from the Internet.
assets/ Published assets.
@@ -69,6 +96,7 @@ src/ Application source code.
ViewInjection/
tests/ A set of Codeception tests for the application.
vendor/ Installed Composer packages.
+Makefile Config for make command.
```
## Configuration
@@ -130,7 +158,7 @@ use Psr\Log\LogLevel;
],
],
'file-rotator' => [
- // maximum file size, in kilo-bytes. Defaults to 10240, meaning 10MB.
+ // maximum file size, in kilobytes. Defaults to 10240, meaning 10MB.
'maxfilesize' => 10,
// number of files used for rotation. Defaults to 5.
'maxfiles' => 5,
@@ -199,11 +227,21 @@ See ["Logging"](https://github.com/yiisoft/docs/blob/master/guide/en/runtime/log
## Testing
The template comes with ready to use [Codeception](https://codeception.com/) configuration.
-In order to execute tests run:
+To execute tests, in local installation run:
```shell
-composer run serve > ./runtime/yii.log 2>&1 &
-vendor/bin/codecept run
+./vendor/bin/codecept build
+
+./yii serve > ./runtime/yii.log 2>&1 &
+./vendor/bin/codecept run
+```
+
+For Docker:
+
+```shell
+make codecept build
+
+make codecept run
```
## Static analysis
@@ -214,6 +252,12 @@ The code is statically analyzed with [Psalm](https://psalm.dev/). To run static
./vendor/bin/psalm
```
+or, using Docker:
+
+```shell
+make psalm
+```
+
## Support
If you need help or have a question, the [Yii Forum](https://forum.yiiframework.com/c/yii-3-0/63) is a good place for that.
diff --git a/config/common/di/logger.php b/config/common/di/logger.php
index b49b94b..4754a74 100644
--- a/config/common/di/logger.php
+++ b/config/common/di/logger.php
@@ -5,6 +5,7 @@
use Psr\Log\LoggerInterface;
use Yiisoft\Definitions\ReferencesArray;
use Yiisoft\Log\Logger;
+use Yiisoft\Log\StreamTarget;
use Yiisoft\Log\Target\File\FileTarget;
/** @var array $params */
@@ -15,6 +16,7 @@
'__construct()' => [
'targets' => ReferencesArray::from([
FileTarget::class,
+ StreamTarget::class,
]),
],
],
diff --git a/docker/.env b/docker/.env
new file mode 100644
index 0000000..c761910
--- /dev/null
+++ b/docker/.env
@@ -0,0 +1,11 @@
+STACK_NAME=app
+
+PROD_HOST=app.example.com
+PROD_SSH="ssh://docker-web"
+
+IMAGE=app
+IMAGE_TAG=latest
+
+DEV_PORT=80
+
+# XDEBUG_MODE=develop,debug
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000..b799cf9
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,64 @@
+FROM composer/composer:latest-bin AS composer
+
+FROM ghcr.io/shyim/wolfi-php/frankenphp:8.3 AS base
+ARG UID=10001
+ARG GID=10001
+RUN <