diff --git a/.dockerignore b/.dockerignore index 13ee54e..75687c0 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,9 +1,16 @@ .git/* .env -api/config/*-local.php -common/config/*-local.php -console/config/*-local.php -api/runtime -console/runtime + +# vendor будет заполнен уже внутри контейнера +vendor +# frontend и его node_modules внутри контейнера не нужны +frontend + +# Все -local файлы +*/config/*-local.php + +# Все временные файлы +runtime + +# Их по идее и не должно образовываться, но мало ли api/web/assets -#vendor diff --git a/.env b/.env deleted file mode 100644 index b068e70..0000000 --- a/.env +++ /dev/null @@ -1,16 +0,0 @@ -# Whether to enable debug mode in Yii. If not set this will be 0. -YII_DEBUG=1 - -# The application mode. If not set, this will be 'prod' -YII_ENV=dev - -# The log trace level. If not set, this will be 0 -#YII_TRACELEVEL=0 - -# Make sure that you provide a different unique cookie validation key in production -COOKIE_VALIDATION_KEY="SeCrEt_DeV_Key--DO-NOT-USE-IN-PRODUCTION!" - -# DB credentials. Default is to fetch the host form docker vars and use 'web' as db name, username and password -#DB_DSN=mysql:host=my.dbhost.com;dbname=web -#DB_USER=user -#DB_PASSWORD=secret diff --git a/.gitignore b/.gitignore index 63f5aae..a218a54 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ phpunit.phar # npm debug npm-debug* + +# Docker override file +docker-compose.override.yml diff --git a/Dockerfile b/Dockerfile index 0f89512..5ba392e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,51 @@ -FROM codemix/yii2-base:2.0.8-php-fpm +FROM php:7.0-fpm -# Composer packages are installed first. This will only add packages -# that are not already in the yii2-base image. -COPY composer.json /var/www/html/ -COPY composer.lock /var/www/html/ +ENV PATH $PATH:/root/.composer/vendor/bin -RUN composer self-update --no-progress \ - && composer install --no-progress --ignore-platform-reqs +# PHP extensions come first, as they are less likely to change between Yii releases +RUN apt-get update \ + && apt-get -y install \ + git \ + g++ \ + libicu-dev \ + libmcrypt-dev \ + zlib1g-dev \ + --no-install-recommends \ + + # Install PHP extensions + && docker-php-ext-install intl \ + && docker-php-ext-install pdo_mysql \ + && docker-php-ext-install mbstring \ + && docker-php-ext-install mcrypt \ + && docker-php-ext-install zip \ + && docker-php-ext-install bcmath \ + + && apt-get purge -y g++ \ + && apt-get autoremove -y \ + && rm -r /var/lib/apt/lists/* \ + + # Don't clear our valuable environment vars in PHP + && echo "\nclear_env = no" >> /usr/local/etc/php-fpm.conf \ + + # Fix write permissions with shared folders + && usermod -u 1000 www-data + +# Поставим xdebug отдельно, т.к. потом его потенциально придётся отсюда убирать +RUN yes | pecl install xdebug \ + && echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini \ + && echo "xdebug.remote_enable=on" >> /usr/local/etc/php/conf.d/xdebug.ini \ + && echo "xdebug.remote_autostart=off" >> /usr/local/etc/php/conf.d/xdebug.ini + +# Next composer and global composer package, as their versions may change from time to time +RUN curl -sS https://getcomposer.org/installer | php \ + && mv composer.phar /usr/local/bin/composer.phar \ + && composer.phar global require --no-progress "fxp/composer-asset-plugin:~1.1.4" \ + && composer.phar global require --no-progress "hirak/prestissimo:~0.2.2" + +COPY ./docker/php/composer.sh /usr/local/bin/composer +RUN chmod a+x /usr/local/bin/composer + +WORKDIR /var/www/html # Copy the working dir to the image's web root COPY . /var/www/html diff --git a/README.md b/README.md index 45e56ad..40c27cb 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,70 @@ -Yii 2 Advanced Project Template -=============================== +# Account Ely.by -Yii 2 Advanced Project Template is a skeleton [Yii 2](http://www.yiiframework.com/) application best for -developing complex Web applications with multiple tiers. +## Развёртывание dev -The template includes three tiers: front end, back end, and console, each of which -is a separate Yii application. +Предварительно нужно установить [git](https://git-scm.com/downloads), +[docker](https://docs.docker.com/engine/installation/) и его +[docker-compose](https://docs.docker.com/compose/install/). -The template is designed to work in a team development environment. It supports -deploying the application in different environments. +Сливаем репозиторий: -Documentation is at [docs/guide/README.md](docs/guide/README.md). +```sh +git clone git@bitbucket.org:ErickSkrauch/ely.by-account.git account.ely.by.local +cd account.ely.by.local +``` -[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2-app-advanced/v/stable.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced) -[![Total Downloads](https://poser.pugx.org/yiisoft/yii2-app-advanced/downloads.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced) -[![Build Status](https://travis-ci.org/yiisoft/yii2-app-advanced.svg?branch=master)](https://travis-ci.org/yiisoft/yii2-app-advanced) +Выполняем первый запуск контейнеров: -DIRECTORY STRUCTURE -------------------- +```sh +docker-compose up -d +``` + +Далее нужно влезть в работающие контейнеры и сделать что-нибудь, что их настроит. + +### Как влезть в работающий контейнер + +Сперва, с помощью команды `docker ps` мы увидим все запущенные контейнеры. Нас интересуют значения из первой колонки +CONTAINER ID. Узнать, чему они соответствуют можно прочитав название IMAGE из 2 колонки. Чтобы выполнить команду +внутри работабщего контейнера, нужно выполнить: ``` -common - config/ contains shared configurations - mail/ contains view files for e-mails - models/ contains model classes used in both backend and frontend -console - config/ contains console configurations - controllers/ contains console controllers (commands) - migrations/ contains database migrations - models/ contains console-specific model classes - runtime/ contains files generated during runtime -backend - assets/ contains application assets such as JavaScript and CSS - config/ contains backend configurations - controllers/ contains Web controller classes - models/ contains backend-specific model classes - runtime/ contains files generated during runtime - views/ contains view files for the Web application - web/ contains the entry script and Web resources -frontend - assets/ contains application assets such as JavaScript and CSS - config/ contains frontend configurations - controllers/ contains Web controller classes - models/ contains frontend-specific model classes - runtime/ contains files generated during runtime - views/ contains view files for the Web application - web/ contains the entry script and Web resources - widgets/ contains frontend widgets -vendor/ contains dependent 3rd-party packages -environments/ contains environment-based overrides -tests contains various tests for the advanced application - codeception/ contains tests developed with Codeception PHP Testing Framework +docker exec -it a7c267b27f49 /bin/bash +``` + +Где `a7c267b27f49` - одно из значений из первой колонки. Для выхода из контейнера используем `exit`. + +------------------------- + +Так вот, нам нужно выполнить ряд команд. Здесь и далее я буду писать имена контейнеров в их соответствии с compose +файлом, но в реалиях их нужно будет заменить на реальные значения: + +```sh +# Настройка php контейнера +docker exec -it app php init --env=Docker +docker exec -it app php composer install +docker exec -it app php ./yii migrate --interactive=0 + +# Настройка node контейнера +docker exec -it node-dev-server npm i +docker exec -it node-dev-server npm --prefix ./webpack i ./webpack + +# Настройка rabbitmq контейнера +docker exec -it rabbitmq /init.sh +``` + +После этого перезапускаем все контейнеры командой: + +```sh +docker-compose restart +``` + +## Тестирование php бэкэнда + +```sh +# Прежде чем тестировать, необходимо накатить миграции +docker exec -it db6366f120ee php tests/codeception/bin/yii migrate --interactive=0 +# Собрать все тестовые окружения +docker exec -it db6366f120ee /bin/sh -c 'cd tests; ./../vendor/bin/codecept build' +# И запустить собственно процесс тестирования +docker exec -it db6366f120ee /bin/sh -c 'cd tests; ./../vendor/bin/codecept run' ``` diff --git a/docker-compose.yml b/docker-compose.yml index fb11214..6f7de65 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,17 @@ version: '2' services: + app: + links: + - db + - redis + - rabbitmq + depends_on: + - app-console-account-queue + + environment: + ENABLE_ENV_FILE: 1 + ENABLE_LOCALCONF: 1 + web: build: ./docker/nginx ports: @@ -15,28 +27,9 @@ services: - "9000" volumes: - ./:/var/www/html/ - links: - - db - - redis - - rabbitmq - depends_on: - - node-dev-server - - app-console-account-queue environment: ENABLE_ENV_FILE: 1 ENABLE_LOCALCONF: 1 - API_TOKEN: "78bb3e46d818793a299ccfcedee213d5ecad07f7" - - app-console-account-queue: - image: php:7.0-cli - volumes: - - ./:/var/www/html/ - working_dir: /var/www/html/ - command: ./wait-for-it.sh rabbitmq:5672 -- ./yii account-queue - links: - - db - - redis - - rabbitmq node-dev-server: build: ./frontend @@ -44,33 +37,26 @@ services: - "8080:8080" volumes: - ./frontend/:/usr/src/app/ - - /usr/src/app/node_modules environment: DOCKERIZED: "true" + app-console-account-queue: + build: . + volumes: + - ./:/var/www/html/ + command: ./docker/wait-for-it.sh rabbitmq:5672 -- ./yii account-queue + links: + - db + - redis + - rabbitmq + db: - image: mariadb:10.0 - expose: - - "3306" - environment: - MYSQL_ROOT_PASSWORD: secret-root - MYSQL_DATABASE: ely_accounts - MYSQL_USER: ely-accounts-user - MYSQL_PASSWORD: ely-accounts-password - TERM: dumb - # Uncomment to autostart at boottime - #restart: always + build: ./docker/mariadb redis: image: redis:3.0 - expose: - - "6379" rabbitmq: - image: rabbitmq:3.6 - expose: - - "5672" - environment: - RABBITMQ_DEFAULT_USER: ely-accounts-app - RABBITMQ_DEFAULT_PASS: app-password - RABBITMQ_DEFAULT_VHOST: /account.ely.by + build: ./docker/rabbitmq + ports: + - "15672:15672" diff --git a/docker/mariadb/Dockerfile b/docker/mariadb/Dockerfile new file mode 100644 index 0000000..a203ef6 --- /dev/null +++ b/docker/mariadb/Dockerfile @@ -0,0 +1,13 @@ +FROM mariadb:10.0 + +COPY mariadb.cnf /etc/mysql/conf.d + +# Add script to create default users / vhosts +ADD init.sh /init.sh +ADD run.sh /run.sh + +# Run rabbitmq, execute init configuration and then shutdown +RUN chmod +x /init.sh /run.sh \ + && /init.sh + +ENTRYPOINT "/run.sh" diff --git a/docker/mariadb/init.sh b/docker/mariadb/init.sh new file mode 100644 index 0000000..9628fa5 --- /dev/null +++ b/docker/mariadb/init.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Копипаста. Я не знаю, что тут происходит + +set -e +set -x + +mysql_install_db + +# Start the MySQL daemon in the background. +/usr/sbin/mysqld & +mysql_pid=$! + +until mysqladmin ping &>/dev/null; do + echo -n "."; sleep 0.2 +done + +# Конец рандомной копипасты + +# Устаналиваем беспарольный доступ для рута +mysql -e "GRANT ALL ON *.* TO root@'%' IDENTIFIED BY '' WITH GRANT OPTION" + +# Создаём базу данных для приложения и для тестов +mysql -e "CREATE DATABASE IF NOT EXISTS ely_accounts CHARACTER SET utf8 COLLATE utf8_general_ci" +mysql -e "CREATE DATABASE IF NOT EXISTS ely_accounts_test CHARACTER SET utf8 COLLATE utf8_general_ci" + +# Tell the MySQL daemon to shutdown. +mysqladmin shutdown + +# Wait for the MySQL daemon to exit. +wait $mysql_pid + +# Сохраняем состояние базы данных +tar czvf default_mysql.tar.gz /var/lib/mysql diff --git a/docker/mariadb/mariadb.cnf b/docker/mariadb/mariadb.cnf new file mode 100644 index 0000000..e69de29 diff --git a/docker/mariadb/run.sh b/docker/mariadb/run.sh new file mode 100644 index 0000000..c8dffad --- /dev/null +++ b/docker/mariadb/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e +set -x + +# first, if the /var/lib/mysql directory is empty, unpack it from our predefined db +[ "$(ls -A /var/lib/mysql)" ] && echo "Running with existing database in /var/lib/mysql" || ( echo 'Populate initial db'; tar xpzvf default_mysql.tar.gz ) + +/usr/sbin/mysqld diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile index ceab9b8..231bba4 100644 --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -1,2 +1,3 @@ FROM nginx:1.9 + COPY nginx.conf /etc/nginx/nginx.conf diff --git a/docker/php/composer.sh b/docker/php/composer.sh new file mode 100644 index 0000000..517b5d0 --- /dev/null +++ b/docker/php/composer.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ -n "$API_TOKEN" ] +then + php /usr/local/bin/composer.phar config -g github-oauth.github.com $API_TOKEN +fi + +exec php /usr/local/bin/composer.phar "$@" diff --git a/docker/rabbitmq/Dockerfile b/docker/rabbitmq/Dockerfile new file mode 100644 index 0000000..6d18711 --- /dev/null +++ b/docker/rabbitmq/Dockerfile @@ -0,0 +1,10 @@ +FROM rabbitmq:3.6 + +RUN rabbitmq-plugins enable rabbitmq_management \ + && rabbitmq-plugins enable rabbitmq_web_stomp \ + && rabbitmq-plugins enable rabbitmq_mqtt + +# Add script to create default users / vhosts +ADD init.sh /init.sh + +RUN chmod +x /init.sh diff --git a/docker/rabbitmq/init.sh b/docker/rabbitmq/init.sh new file mode 100644 index 0000000..ec7be76 --- /dev/null +++ b/docker/rabbitmq/init.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +#( sleep 10 ; \ +# +## Create users +#rabbitmqctl add_user ely-accounts-app app-password ; \ +#rabbitmqctl add_user ely-accounts-tester tester-password ; \ +# +## Set user rights +#rabbitmqctl set_user_tags ely-accounts-app administrator ; \ +#rabbitmqctl set_user_tags ely-accounts-tester administrator ; \ +# +## Create vhosts +#rabbitmqctl add_vhost /account.ely.by ; \ +#rabbitmqctl add_vhost /account.ely.by/tests ; \ +# +## Set vhost permissions +#rabbitmqctl set_permissions -p /account.ely.by ely-accounts-app ".*" ".*" ".*" ; \ +#rabbitmqctl set_permissions -p /account.ely.by/tests ely-accounts-tester ".*" ".*" ".*" ; \ +#) & +#rabbitmq-server $@ + +#service rabbitmq-server start + +# Create users +rabbitmqctl add_user ely-accounts-app app-password +rabbitmqctl add_user ely-accounts-tester tester-password + +# Set user rights +rabbitmqctl set_user_tags ely-accounts-app administrator +rabbitmqctl set_user_tags ely-accounts-tester administrator + +# Create vhosts +rabbitmqctl add_vhost /account.ely.by +rabbitmqctl add_vhost /account.ely.by/tests + +# Set vhost permissions +rabbitmqctl set_permissions -p /account.ely.by ely-accounts-app ".*" ".*" ".*" +rabbitmqctl set_permissions -p /account.ely.by/tests ely-accounts-tester ".*" ".*" ".*" + +#service rabbitmq-server stop + +# Сохраняем состояние рэбита +#tar czvf default_rabbitmq.tar.gz /var/lib/rabbitmq/mnesia diff --git a/docker/rabbitmq/run.sh b/docker/rabbitmq/run.sh new file mode 100644 index 0000000..324fcf2 --- /dev/null +++ b/docker/rabbitmq/run.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e +set -x + +[ "$(ls -A /var/lib/rabbitmq/mnesia)" ] && echo "Running with existing rabbitmq in /var/lib/rabbitmq" || ( echo 'Populate initial rabbitmq'; tar xpzvf default_rabbitmq.tar.gz ) + +rabbitmq-server diff --git a/wait-for-it.sh b/docker/wait-for-it.sh similarity index 100% rename from wait-for-it.sh rename to docker/wait-for-it.sh diff --git a/environments/docker/api/config/main-local.php b/environments/docker/api/config/main-local.php new file mode 100644 index 0000000..224f3dd --- /dev/null +++ b/environments/docker/api/config/main-local.php @@ -0,0 +1,24 @@ + [ + 'request' => [ + // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation + 'cookieValidationKey' => '', + ], + 'reCaptcha' => [ + 'secret' => '', + ], + ], +]; + +if (!YII_ENV_TEST) { + // configuration adjustments for 'dev' environment + $config['bootstrap'][] = 'debug'; + $config['modules']['debug'] = \yii\debug\Module::class; + + $config['bootstrap'][] = 'gii'; + $config['modules']['gii'] = \yii\gii\Module::class; +} + +return $config; diff --git a/environments/docker/api/config/params-local.php b/environments/docker/api/config/params-local.php new file mode 100644 index 0000000..2481e4b --- /dev/null +++ b/environments/docker/api/config/params-local.php @@ -0,0 +1,4 @@ + 'some-long-secret-key', +]; diff --git a/environments/docker/api/web/index-test.php b/environments/docker/api/web/index-test.php new file mode 100644 index 0000000..1a1d417 --- /dev/null +++ b/environments/docker/api/web/index-test.php @@ -0,0 +1,18 @@ +run(); diff --git a/environments/docker/api/web/index.php b/environments/docker/api/web/index.php new file mode 100644 index 0000000..6038167 --- /dev/null +++ b/environments/docker/api/web/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/environments/docker/common/config/main-local.php b/environments/docker/common/config/main-local.php new file mode 100644 index 0000000..57ca3c0 --- /dev/null +++ b/environments/docker/common/config/main-local.php @@ -0,0 +1,26 @@ + [ + 'db' => [ + 'dsn' => 'mysql:host=db;dbname=ely_accounts', + 'username' => 'root', + 'password' => '', + ], + 'mailer' => [ + 'useFileTransport' => true, + ], + 'redis' => [ + 'hostname' => 'redis', + 'password' => null, + 'port' => 6379, + 'database' => 0, + ], + 'amqp' => [ + 'host' => 'rabbitmq', + 'port' => 5672, + 'user' => 'ely-accounts-app', + 'password' => 'app-password', + 'vhost' => '/account.ely.by', + ], + ], +]; diff --git a/environments/docker/common/config/params-local.php b/environments/docker/common/config/params-local.php new file mode 100644 index 0000000..c573d3a --- /dev/null +++ b/environments/docker/common/config/params-local.php @@ -0,0 +1,4 @@ + 'account@ely.by', +]; diff --git a/environments/docker/console/config/main-local.php b/environments/docker/console/config/main-local.php new file mode 100644 index 0000000..96bd118 --- /dev/null +++ b/environments/docker/console/config/main-local.php @@ -0,0 +1,7 @@ + ['gii'], + 'modules' => [ + 'gii' => \yii\gii\Module::class, + ], +]; diff --git a/environments/docker/console/config/params-local.php b/environments/docker/console/config/params-local.php new file mode 100644 index 0000000..d0b9c34 --- /dev/null +++ b/environments/docker/console/config/params-local.php @@ -0,0 +1,3 @@ +run(); +exit($exitCode); diff --git a/environments/index.php b/environments/index.php index 3fe42a0..fc854f2 100644 --- a/environments/index.php +++ b/environments/index.php @@ -43,6 +43,20 @@ return [ 'api/config/main-local.php', ], ], + 'Docker' => [ + 'path' => 'docker', + 'setWritable' => [ + 'api/runtime', + 'api/web/assets', + ], + 'setExecutable' => [ + 'yii', + 'tests/codeception/bin/yii', + ], + 'setCookieValidationKey' => [ + 'api/config/main-local.php', + ], + ], 'Production' => [ 'path' => 'prod', 'setWritable' => [ diff --git a/tests/codeception/api/functional.suite.yml b/tests/codeception/api/functional.suite.yml index 617cc31..a99b42f 100644 --- a/tests/codeception/api/functional.suite.yml +++ b/tests/codeception/api/functional.suite.yml @@ -11,11 +11,11 @@ modules: Yii2: configFile: '../config/api/functional.php' Redis: - host: localhost + host: redis port: 6379 database: 1 AMQP: - host: localhost + host: rabbitmq port: 5672 username: 'ely-accounts-tester' password: 'tester-password' diff --git a/tests/codeception/config/config.php b/tests/codeception/config/config.php index 7ce75ca..c6ea34b 100644 --- a/tests/codeception/config/config.php +++ b/tests/codeception/config/config.php @@ -14,7 +14,7 @@ return [ ], 'components' => [ 'db' => [ - 'dsn' => 'mysql:host=localhost;dbname=ely_accounts_test', + 'dsn' => 'mysql:host=db;dbname=ely_accounts_test', ], 'mailer' => [ 'useFileTransport' => true,