diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..ba64667f1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,20 @@ +/.git +/public/build +/public/bundles +/var/log/* +var/sessions/* +/vendor +.dockerignore +.editorconfig +.env.local +.env.test +.gitignore +.php_cs.dist +.travis.yml +appveyor.yml +docker-compose.override.yml.dist +docker-compose.yml +Dockerfile +Makefile +phpunit.xml.dist +README.md diff --git a/.gitignore b/.gitignore index 7d5655849..dcd594ffe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ /public/build/fonts/glyphicons-* /public/build/images/glyphicons-* +###> docker ### +docker-compose.override.yml +###< docker ### + ###> symfony/framework-bundle ### /.env.local /.env.*.local diff --git a/.php_cs.dist b/.php_cs.dist index edafec3af..d94c8dcc6 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -12,6 +12,7 @@ COMMENT; $finder = PhpCsFixer\Finder::create() ->in(__DIR__) ->exclude('config') + ->exclude('src/Migrations') ->exclude('var') ->exclude('public/bundles') ->exclude('public/build') diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..3fe91b2a4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,179 @@ +ARG NODE_VERSION=11.6.0 +ARG COMPOSER_VERSION=1.8.0 +ARG PHP_VERSION=7.2.13 +ARG ICU_VERSION=63.1 +ARG APCU_VERSION=5.1.16 +ARG XDEBUG_VERSION=2.6.1 + + +##################################### +## APP ## +##################################### +FROM php:${PHP_VERSION}-fpm as app + +ARG ICU_VERSION +ARG APCU_VERSION + +WORKDIR /app + +EXPOSE 80 + +# Install paquet requirements +RUN export PHP_CPPFLAGS="${PHP_CPPFLAGS} -std=c++11"; \ + set -ex; \ + # Install required system packages + apt-get update; \ + apt-get install -qy --no-install-recommends \ + libzip-dev \ + ; \ + # Compile ICU (required by intl php extension) + curl -L -o /tmp/icu.tar.gz http://download.icu-project.org/files/icu4c/${ICU_VERSION}/icu4c-$(echo ${ICU_VERSION} | sed s/\\./_/g)-src.tgz; \ + tar -zxf /tmp/icu.tar.gz -C /tmp; \ + cd /tmp/icu/source; \ + ./configure --prefix=/usr/local; \ + make clean; \ + make; \ + make install; \ + #Install the PHP extensions + docker-php-ext-configure intl --with-icu-dir=/usr/local; \ + docker-php-ext-install -j "$(nproc)" \ + intl \ + pdo \ + zip \ + bcmath \ + ; \ + pecl install \ + apcu-${APCU_VERSION} \ + ; \ + docker-php-ext-enable \ + opcache \ + apcu \ + ; \ + docker-php-source delete; \ + # Clean aptitude cache and tmp directory + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*; + +## set recommended PHP.ini settings +RUN { \ + echo 'date.timezone = UTC'; \ + echo 'short_open_tag = off'; \ + echo 'expose_php = off'; \ + echo 'error_log = /proc/self/fd/2'; \ + echo 'memory_limit = 128m'; \ + echo 'post_max_size = 110m'; \ + echo 'upload_max_filesize = 100m'; \ + echo 'opcache.enable = 1'; \ + echo 'opcache.enable_cli = 1'; \ + echo 'opcache.memory_consumption = 256'; \ + echo 'opcache.interned_strings_buffer = 16'; \ + echo 'opcache.max_accelerated_files = 20011'; \ + echo 'opcache.fast_shutdown = 1'; \ + echo 'realpath_cache_size = 4096K'; \ + echo 'realpath_cache_ttl = 600'; \ + } > /usr/local/etc/php/php.ini + +RUN { \ + echo 'date.timezone = UTC'; \ + echo 'short_open_tag = off'; \ + echo 'memory_limit = -1'; \ + } > /usr/local/etc/php/php-cli.ini + +CMD ["php-fpm"] + + +##################################### +## APP DEV ## +##################################### +FROM app as app-dev + +ARG NODE_VERSION +ARG COMPOSER_VERSION +ARG XDEBUG_VERSION + +ENV COMPOSER_ALLOW_SUPERUSER=1 +ENV APP_ENV=dev + +# Install paquet requirements +RUN set -ex; \ + # Install required system packages + apt-get update; \ + apt-get install -qy --no-install-recommends \ + unzip \ + git \ + ; \ + # Clean aptitude cache and tmp directory + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*; + +# Install Node +RUN set -ex; \ + curl -L -o /tmp/nodejs.tar.gz https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz; \ + tar xfvz /tmp/nodejs.tar.gz -C /usr/local --strip-components=1; \ + rm -f /tmp/nodejs.tar.gz; \ + npm install yarn -g + +# Install Composer +RUN set -ex; \ + EXPECTED_SIGNATURE="$(curl -L https://getcomposer.org/download/${COMPOSER_VERSION}/composer.phar.sha256sum)"; \ + curl -L -o composer.phar https://getcomposer.org/download/${COMPOSER_VERSION}/composer.phar; \ + ACTUAL_SIGNATURE="$(sha256sum composer.phar)"; \ + if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]; then >&2 echo 'ERROR: Invalid installer signature' && rm /usr/local/bin/composer && exit 1 ; fi; \ + chmod +x composer.phar && mv composer.phar /usr/local/bin/composer; \ + RESULT=$?; \ + exit $RESULT; + +# Edit OPCache configuration +RUN set -ex; \ + { \ + echo 'opcache.validate_timestamps = 1'; \ + echo 'opcache.revalidate_freq = 0'; \ + } >> /usr/local/etc/php/php.ini + +# Install Xdebug +RUN set -ex; \ + if [ "${XDEBUG_VERSION}" != 0 ]; \ + then \ + pecl install xdebug-${XDEBUG_VERSION}; \ + docker-php-ext-enable xdebug; \ + { \ + echo 'xdebug.remote_enable = on'; \ + echo 'xdebug.remote_connect_back = on'; \ + } >> /usr/local/etc/php/php.ini \ + ; fi + + +##################################### +## PROD ASSETS BUILDER ## +##################################### +FROM node:${NODE_VERSION} as assets-builder + +COPY . /app +WORKDIR /app + +RUN yarn install && yarn build && rm -R node_modules + +##################################### +## PROD VENDOR BUILDER ## +##################################### +FROM composer:${COMPOSER_VERSION} as vendor-builder + +COPY --chown=www-data --from=assets-builder /app /app +WORKDIR /app + +RUN APP_ENV=prod composer install -o -n --no-ansi --no-dev + + +##################################### +## APP PROD ## +##################################### +FROM app as app-prod + +ENV APP_ENV=prod + +COPY --from=vendor-builder /app /app +WORKDIR /app + +# Edit OPCache configuration +RUN set -ex; \ + { \ + echo 'opcache.validate_timestamps = 0'; \ + } >> /usr/local/etc/php/php.ini diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..e3a2662fc --- /dev/null +++ b/Makefile @@ -0,0 +1,166 @@ +DOCKER_COMPOSE?=docker-compose +EXEC?=$(DOCKER_COMPOSE) exec app +CONSOLE=php bin/console +PHPCSFIXER?=$(EXEC) php -d memory_limit=1024m vendor/bin/php-cs-fixer + +.DEFAULT_GOAL := help +.PHONY: help start stop restart install uninstall reset clear-cache shell clear clean +.PHONY: db-diff db-migrate db-rollback db-fixtures db-validate +.PHONY: watch assets assets-build +.PHONY: tests lint lint-symfony lint-yaml lint-twig lint-xliff php-cs php-cs-fix security-check test-schema test-all +.PHONY: deps +.PHONY: build up perm docker-compose.override.yml + +help: + @grep -E '(^[a-zA-Z_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/' + + +## +## Project setup +##--------------------------------------------------------------------------- + +start: ## Start docker containers + $(DOCKER_COMPOSE) start + +stop: ## Stop docker containers + $(DOCKER_COMPOSE) stop + +restart: ## Restart docker containers + $(DOCKER_COMPOSE) restart + +install: docker-compose.override.yml build up deps perm ## Create and start docker containers + +uninstall: stop ## Remove docker containers + $(DOCKER_COMPOSE) rm -vf + +reset: uninstall install ## Remove and re-create docker containers + +clear-cache: perm + $(EXEC) $(CONSOLE) cache:clear --no-warmup + $(EXEC) $(CONSOLE) cache:warmup + +shell: ## Run app container in interactive mode + $(EXEC) /bin/bash + +clear: perm ## Remove all the cache, the logs, the sessions and the built assets + $(EXEC) rm -rf var/cache/* + rm -rf var/log/* + rm -rf public/build + rm -f var/.php_cs.cache + +clean: clear ## Clear and remove dependencies + rm -rf vendor node_modules + + +## +## Database +##--------------------------------------------------------------------------- + +db-diff: vendor ## Generate a migration by comparing your current database to your mapping information + $(EXEC) $(CONSOLE) doctrine:migration:diff + +db-migrate: vendor ## Migrate database schema to the latest available version + $(EXEC) $(CONSOLE) doctrine:migration:migrate -n + +db-rollback: vendor ## Rollback the latest executed migration + $(EXEC) $(CONSOLE) doctrine:migration:migrate prev -n + +db-fixtures: vendor ## Apply doctrine fixtures + $(EXEC) $(CONSOLE) doctrine:fixtures:load -n + +db-validate: vendor ## Check the ORM mapping + $(EXEC) $(CONSOLE) doctrine:schema:validate + + +## +## Assets +##--------------------------------------------------------------------------- + +watch: node_modules ## Watch the assets and build their development version on change + $(EXEC) yarn watch + +assets: node_modules ## Build the development version of the assets + $(EXEC) yarn dev + +assets-build: node_modules ## Build the production version of the assets + $(EXEC) yarn build + + +## +## Tests +##--------------------------------------------------------------------------- + +tests: ## Run all the PHP tests + $(EXEC) bin/phpunit + +lint: lint-symfony php-cs ## Run lint on Twig, YAML, XLIFF, and PHP files + +lint-symfony: lint-yaml lint-twig lint-xliff ## Lint Symfony (Twig and YAML) files + +lint-yaml: ## Lint YAML files + $(EXEC) $(CONSOLE) lint:yaml config + +lint-twig: ## Lint Twig files + $(EXEC) $(CONSOLE) lint:twig templates + +lint-xliff: ## Lint Translation files + $(EXEC) $(CONSOLE) lint:xliff translations + +php-cs: vendor ## Lint PHP code + $(PHPCSFIXER) fix --diff --dry-run --no-interaction -v + +php-cs-fix: vendor ## Fix PHP code to follow the convention + $(PHPCSFIXER) fix + +security-check: vendor ## Check for vulnerable dependencies + $(EXEC) vendor/bin/security-checker security:check + +test-schema: vendor ## Test the doctrine Schema + $(EXEC) $(CONSOLE) doctrine:schema:validate --skip-sync -vvv --no-interaction + +test-all: lint test-schema security-check tests ## Lint all, run schema and security check, then unit and functionnal tests + + +## +## Dependencies +##--------------------------------------------------------------------------- + +deps: vendor assets ## Install the project dependencies + + +## + + +# Internal rules + +build: + $(DOCKER_COMPOSE) pull --ignore-pull-failures + $(DOCKER_COMPOSE) build --force-rm + +up: + $(DOCKER_COMPOSE) up -d --remove-orphans + +perm: + $(EXEC) chmod -R 777 var public/build node_modules vendor + $(EXEC) chown -R www-data:root var public/build node_modules vendor + +docker-compose.override.yml: +ifneq ($(wildcard docker-compose.override.yml),docker-compose.override.yml) + @echo docker-compose.override.yml do not exists, copy docker-compose.override.yml.dist to create it, and fill it. + exit 1 +endif + + +# Rules from files + +vendor: composer.lock + $(EXEC) composer install -n + +composer.lock: composer.json + @echo composer.lock is not up to date. + +node_modules: yarn.lock + $(EXEC) yarn install + +yarn.lock: package.json + @echo yarn.lock is not up to date. diff --git a/docker-compose.override.yml.dist b/docker-compose.override.yml.dist new file mode 100644 index 000000000..d06d68fad --- /dev/null +++ b/docker-compose.override.yml.dist @@ -0,0 +1,6 @@ +version: '3.4' + +services: + nginx: + ports: + - 127.0.0.1:8080:80 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..4f7fa8653 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3.4' + +services: + nginx: + build: + context: docker + dockerfile: NginxDockerfile + depends_on: + - app + volumes: + - .:/app + + app: + build: + context: . + target: app-dev + volumes: + - .:/app diff --git a/docker/NginxDockerfile b/docker/NginxDockerfile new file mode 100644 index 000000000..3e157ffe5 --- /dev/null +++ b/docker/NginxDockerfile @@ -0,0 +1,4 @@ +FROM nginx:1.15.8 + +# set nginx config +ADD nginx-default.conf /etc/nginx/conf.d/default.conf diff --git a/docker/nginx-default.conf b/docker/nginx-default.conf new file mode 100644 index 000000000..907d3adbb --- /dev/null +++ b/docker/nginx-default.conf @@ -0,0 +1,22 @@ + server { + listen 80; + server_name _; + root /app/public; + + location / { + try_files $uri /index.php$is_args$args; + } + + location ~ ^/index\.php(/|$) { + fastcgi_pass app:9000; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT $realpath_root; + internal; + } + + location ~ \.php$ { + return 404; + } +}