Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docker/dev/.env → .env.dev.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Development environment configuration for Docker
APP_ENV=dev
APP_DEBUG=true
SERVER_NAME=:80
Expand Down
File renamed without changes.
12 changes: 12 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Application environment: dev, test, prod
APP_ENV=dev

# Enable debug mode (true/false)
APP_DEBUG=true

# Docker-specific settings (optional for non-Docker deployments)
# SERVER_NAME=:80
# XDEBUG_MODE=develop
# COMPOSER_CACHE_DIR=/app/runtime/cache/composer
# APP_C3=false
# APP_HOST_PATH=/path/to/app
3 changes: 3 additions & 0 deletions .env.override.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Override settings for local development (optional)
# Copy this file to .env.dev for custom local settings
# APP_HOST_PATH=/your/custom/path
4 changes: 4 additions & 0 deletions .env.prod.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Production environment configuration for Docker
APP_ENV=prod
APP_DEBUG=false
SERVER_NAME=:80
1 change: 1 addition & 0 deletions docker/test/.env → .env.test.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Test environment configuration for Docker
APP_ENV=test
APP_DEBUG=false
APP_C3=true
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ Thumbs.db

# Codeception C3
c3.php

# Environment configuration
/.env
/.env.dev
/.env.prod
/.env.test
/.env.override
/.env.docker
2 changes: 1 addition & 1 deletion docker/Dockerfile → Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ USER ${USER_NAME}

FROM base AS prod-builder
COPY --from=composer /composer /usr/bin/composer
COPY .. /app
COPY . /app
RUN --mount=type=cache,target=/tmp/cache \
composer install --no-dev --no-progress --no-interaction --classmap-authoritative && \
rm composer.lock composer.json
Expand Down
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ else
PRIMARY_GOAL := $(firstword $(MAKECMDGOALS))
endif

include docker/.env
-include .env.docker

# Current user ID and group ID except MacOS where it conflicts with Docker abilities
ifeq ($(shell uname), Darwin)
Expand All @@ -19,8 +19,8 @@ else
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
DOCKER_COMPOSE_DEV := docker compose -f compose.yml -f compose.dev.yml
DOCKER_COMPOSE_TEST := docker compose -f compose.yml -f compose.test.yml

#
# Development
Expand Down Expand Up @@ -112,7 +112,7 @@ endif

ifeq ($(PRIMARY_GOAL),prod-build)
prod-build: ## PROD | Build an image
docker build --file docker/Dockerfile --target prod --pull -t ${IMAGE}:${IMAGE_TAG} .
docker build --file Dockerfile --target prod --pull -t ${IMAGE}:${IMAGE_TAG} .
endif

ifeq ($(PRIMARY_GOAL),prod-push)
Expand All @@ -122,7 +122,7 @@ endif

ifeq ($(PRIMARY_GOAL),prod-deploy)
prod-deploy: ## PROD | Deploy to production
docker -H ${PROD_SSH} stack deploy --prune --detach=false --with-registry-auth -c docker/compose.yml -c docker/prod/compose.yml ${STACK_NAME}
docker -H ${PROD_SSH} stack deploy --prune --detach=false --with-registry-auth -c compose.yml -c compose.prod.yml ${STACK_NAME}
endif

#
Expand Down
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,27 @@ composer create-project yiisoft/app myproject
cd myproject
```

Configure the environment by creating a `.env` file from the example:

```shell
cp .env.example .env
```

The `.env` file allows you to configure the application environment and other settings:
- `APP_ENV`: Application environment (`dev`, `test`, or `prod`)
- `APP_DEBUG`: Enable debug mode (`true` or `false`)

> **Note:** The `.env` file is excluded from version control. When deployed to production without a `.env` file,
> the application will default to the `prod` environment.

To run the app:

```shell
./yii serve
```

Or with explicit environment override:

```shell
APP_ENV=dev ./yii serve
```
Expand All @@ -62,9 +81,18 @@ Fork the repository, clone it, then:

```shell
cd myproject
cp .env.docker.example .env.docker
make composer update
```

Docker uses environment-specific configuration files from the root directory:
- `.env.docker` - Docker-specific variables (stack name, ports, image names, etc.)
- `.env.dev.example` - Development environment (used by default)
- `.env.prod.example` - Production environment
- `.env.test.example` - Test environment

You can customize settings by creating override files (e.g., `.env.dev`) which are automatically loaded if present.

To run the app:

```shell
Expand All @@ -90,13 +118,24 @@ make help
The application template has the following structure:

```
.dockerignore Docker ignore file
.env.example Example environment configuration for local development
.env.docker.example Docker-specific variables (stack name, ports, image names, etc.)
.env.dev.example Docker development environment configuration
.env.prod.example Docker production environment configuration
.env.test.example Docker test environment configuration
.env.override.example Example override file for custom local settings
Dockerfile Docker image definition
compose.yml Base Docker Compose configuration
compose.dev.yml Docker Compose configuration for development
compose.prod.yml Docker Compose configuration for production
compose.test.yml Docker Compose configuration for testing
assets/ Asset bundle source files.
config/ Configuration files.
common/ Common configuration and DI definitions.
console/ Console-specific configuration.
environments/ Environment-specific configuration (dev/test/prod).
web/ Web-specific configuration.
docker/ Docker-specific files.
public/ Files publically accessible from the Internet.
assets/ Published/compiled assets.
index.php Entry script.
Expand Down
12 changes: 6 additions & 6 deletions docker/dev/compose.yml → compose.dev.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
services:
app:
build:
dockerfile: docker/Dockerfile
context: ..
dockerfile: Dockerfile
context: .
target: dev
args:
USER_ID: ${UID}
GROUP_ID: ${GID}
env_file:
- path: ./dev/.env
- path: ./dev/override.env
- path: .env.dev.example
- path: .env.dev
required: false
ports:
- "${DEV_PORT:-80}:80"
volumes:
- ../:/app
- ../runtime:/app/runtime
- ./:/app
- ./runtime:/app/runtime
- caddy_data:/data
- caddy_config:/config
tty: true
Expand Down
4 changes: 2 additions & 2 deletions docker/prod/compose.yml → compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ services:
- caddy_data:/data
- caddy_config:/config
env_file:
- path: ./prod/.env
- path: ./prod/override.env
- path: .env.prod.example
- path: .env.prod
required: false
deploy:
replicas: 2
Expand Down
12 changes: 6 additions & 6 deletions docker/test/compose.yml → compose.test.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
services:
app:
build:
dockerfile: docker/Dockerfile
context: ..
dockerfile: Dockerfile
context: .
target: dev
args:
USER_ID: ${UID}
GROUP_ID: ${GID}
env_file:
- path: ./test/.env
- path: ./test/override.env
- path: .env.test.example
- path: .env.test
required: false
volumes:
- ../:/app
- ../runtime:/app/runtime
- ./:/app
- ./runtime:/app/runtime
- caddy_data:/data
- caddy_config:/config
tty: true
File renamed without changes.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"psr/http-server-handler": "^1.0.2",
"psr/log": "^3.0.2",
"symfony/console": "^7.3.4",
"vlucas/phpdotenv": "^5.6",
"yiisoft/aliases": "^3.1",
"yiisoft/assets": "^5.1.1",
"yiisoft/config": "^1.6",
Expand Down
1 change: 0 additions & 1 deletion docker/dev/.gitignore

This file was deleted.

1 change: 0 additions & 1 deletion docker/dev/override.env.example

This file was deleted.

3 changes: 0 additions & 3 deletions docker/prod/.env

This file was deleted.

1 change: 0 additions & 1 deletion docker/prod/.gitignore

This file was deleted.

1 change: 0 additions & 1 deletion docker/test/.gitignore

This file was deleted.

12 changes: 6 additions & 6 deletions src/Environment.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ private static function setEnvironment(): void
{
$environment = self::getRawValue('APP_ENV');

if (!in_array($environment, self::ENVIRONMENTS, true)) {
if ($environment === null) {
$message = 'APP_ENV environment variable is empty.';
} else {
$message = sprintf('APP_ENV="%s" environment is invalid.', $environment);
}
// Default to prod when APP_ENV is not set (production deployment scenario)
if ($environment === null) {
$environment = self::PROD;
}

if (!in_array($environment, self::ENVIRONMENTS, true)) {
$message = sprintf('APP_ENV="%s" environment is invalid.', $environment);
$message .= sprintf(' Valid values are "%s".', implode('", "', self::ENVIRONMENTS));

throw new RuntimeException($message);
Expand Down
11 changes: 11 additions & 0 deletions src/autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@
declare(strict_types=1);

use App\Environment;
use Dotenv\Dotenv;

require_once dirname(__DIR__) . '/vendor/autoload.php';

// Load .env file if it exists (for non-Docker environments)
// Skip loading if APP_ENV is already set (Docker/CI optimization)
if (!isset($_ENV['APP_ENV']) && getenv('APP_ENV') === false) {
$rootDir = dirname(__DIR__);
if (file_exists($rootDir . '/.env')) {
$dotenv = Dotenv::createImmutable($rootDir);
$dotenv->safeLoad();
}
}

Environment::prepare();