├── .dockerignore ├── .env.dist ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── Dockerfile ├── README.md ├── README.production-test.md ├── README.production.md ├── UPGRADING.md ├── config ├── haproxy │ └── haproxy.cfg ├── nginx │ ├── conf.d │ │ ├── http-directives.conf.template │ │ ├── symfony-development.conf.template │ │ └── symfony-production.conf.template │ ├── docker-entrypoint.sh │ └── nginx.conf ├── node │ └── docker-entrypoint.sh ├── php │ ├── docker-entrypoint.sh │ ├── php-fpm-healthcheck.sh │ ├── php-fpm.d │ │ └── zzz-01-healthcheck.conf │ └── php-ini-directives.ini.template ├── postgres │ ├── docker-entrypoint-initdb.d │ │ ├── 10-create-app-user.sh │ │ ├── 10-create-required-extensions.sh │ │ ├── 20-create-app-db.sh │ │ └── 20-create-app-test-db.sh │ ├── ergonode-common-functions.sh │ └── postgres-healthcheck.sh └── rabbitmq │ ├── docker-ergonode-entrypoint.sh │ ├── rabbitmq-healthcheck.sh │ └── rabbitmq.conf.template ├── data └── .gitkeep ├── docker-compose.deploy.yml ├── docker-compose.postgres.yml ├── docker-compose.production.yml ├── docker-compose.test.yml └── docker-compose.yml /.dockerignore: -------------------------------------------------------------------------------- 1 | ./data 2 | ./backend/.git 3 | ./fronted/.git 4 | ./frontend/node_modules/ 5 | ./frontend/.nuxt 6 | ./frontend/.env 7 | ./frontend/dist 8 | ./backend/config/jwt/ 9 | ./backend/var/ 10 | ./backend/vendor/ 11 | ./backend/build/ 12 | ./backend/bin/* 13 | !./backend/bin/.gitignore 14 | !./backend/bin/console 15 | -------------------------------------------------------------------------------- /.env.dist: -------------------------------------------------------------------------------- 1 | ###> Docker Compose Configuration ### 2 | COMPOSE_PROJECT_NAME=ergonode 3 | CONTAINER_REGISTRY_BASE=ergonode 4 | ####< Docker Compose Configuration ### 5 | 6 | ###> PostgreSQL Configuration ### 7 | POSTGRES_PASSWORD=123 8 | POSTGRES_USER=postgres 9 | EXPOSED_POSTGRES_PORT=5432 10 | POSTGRES_DB=postgres 11 | ####< PostgreSQL Configuration ### 12 | 13 | ###> App DB Configuration ### 14 | APP_USER=ergonode 15 | APP_USER_PASSWORD=123 16 | APP_DB=ergonode 17 | APP_TEST_DB=ergonode_test 18 | ####< App DB Configuration ### 19 | 20 | ###> Xdebug Configuration ### 21 | # Default xdebug config for php target php_final_with_xdebug 22 | # This ip can be get by using shell command: 23 | # ifconfig | grep -A1 docker0 | grep inet 24 | # on Mac OS X and Windows `host.docker.internal` can be set for autoresolving 25 | # if you have firewall you need enable listening on tcp port 9000 26 | # for ufw firewall you can use command like 27 | # sudo ufw allow 9000/tcp 28 | # XDEBUG_CONFIG=remote_enable=1 remote_host=host.docker.internal remote_connect_back=0 29 | 30 | # Default ide config for ./bin/console command 31 | # and phpstorm should be localhost or symfony.dev 32 | PHP_IDE_CONFIG=serverName=localhost 33 | ####< Xdebug Configuration ### 34 | 35 | 36 | ###> Nginx Configuration ### 37 | EXPOSED_NGINX_PORT=8000 38 | ####< Nginx Configuration ### 39 | 40 | ###> PHP Configuration ### 41 | PHP_FINAL_TARGET=php_final 42 | ###< PHP Configuration ### 43 | 44 | ###> Node Configuration ### 45 | EXPOSED_NODE_PORT=80 46 | ###< Node Configuration ### 47 | 48 | ###> Docs Configuration ### 49 | EXPOSED_DOCS_PORT=8002 50 | ###< Docs Configuration ### 51 | 52 | ###> Backend overrides ### 53 | APP_URL=http://nginx 54 | ###< Backend overrides ### 55 | 56 | ###> Rabbitmq Configuration ### 57 | EXPOSED_RABBITMQ_PORT=5672 58 | EXPOSED_RABBITMQ_WEB_PORT=15672 59 | RABBITMQ_DEFAULT_USER=ergonode 60 | RABBITMQ_DEFAULT_PASS=ergonode 61 | ###< Rabbitmq Configuration ### 62 | 63 | ###> Mailhog Configuration ### 64 | EXPOSED_MAILHOG_SMTP_PORT=1025 65 | EXPOSED_MAILHOG_WEB_PORT=8025 66 | ###< Mailhog Configuration ### 67 | 68 | ###> Worker ### 69 | WORKER_SLEEP=10 70 | IMPORT_WORKER_SLEEP=30 71 | EXPORT_WORKER_SLEEP=30 72 | WORKER_MEMORY_LIMIT=128M 73 | IMPORT_WORKER_MEMORY_LIMIT=512M 74 | EXPORT_WORKER_MEMORY_LIMIT=512M 75 | WORKER_TIME_LIMIT=3600 76 | ###< Worker ### 77 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | 4 | 5 | Issue # 6 | ## Type of change 7 | 8 | 9 | 10 | - [ ] Bug fix (non-breaking change which fixes an issue) 11 | - [ ] New feature (non-breaking change which adds functionality) 12 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 13 | - [ ] This change requires a documentation update 14 | 15 | # How Has This Been Tested? 16 | 17 | 18 | 19 | 20 | 21 | # Checklist: 22 | - [ ] I have read the contribution requirements and fulfill them. 23 | - [ ] My code follows the style guidelines of this project 24 | - [ ] I have performed a self-review of my own code 25 | - [ ] I have commented my code, particularly in hard-to-understand areas 26 | - [ ] I have made corresponding changes to the documentation 27 | - [ ] My changes generate no new warnings 28 | - [ ] I have added tests that prove my fix is effective or that my feature works 29 | - [ ] New and existing unit tests pass locally with my changes 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | 3 | .env 4 | 5 | /data/* 6 | !/data/.gitkeep 7 | /backend/ 8 | /frontend/ 9 | /docs/ 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # the different stages of this Dockerfile are meant to be built into separate images 2 | # https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage 3 | # https://docs.docker.com/compose/compose-file/#target 4 | # https://docs.docker.com/compose/environment-variables/ 5 | 6 | # https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact 7 | 8 | FROM php:7.4-fpm-alpine as php 9 | 10 | ENV COMPOSER_ALLOW_SUPERUSER 1 11 | ENV COMPOSER_HOME /tmp 12 | ENV COMPOSER_MEMORY_LIMIT -1 13 | ARG NEWRELIC_URL=https://download.newrelic.com/php_agent/archive/9.14.0.290/newrelic-php5-9.14.0.290-linux-musl.tar.gz 14 | ARG NEWRELIC_SHA256SUM=9842f06c0834e02b2bb31e6349893532384c836a6cddccb57e827b7670e487a8 15 | 16 | COPY --from=composer /usr/bin/composer /usr/bin/composer 17 | 18 | # required packages and PHP extensionns 19 | RUN set -eux ; \ 20 | # Non dev packages 21 | apk add --no-cache git \ 22 | zip \ 23 | unzip \ 24 | curl \ 25 | rabbitmq-c \ 26 | libpq \ 27 | icu-libs \ 28 | graphviz \ 29 | acl \ 30 | fcgi \ 31 | bash \ 32 | libcurl \ 33 | gettext \ 34 | gnu-libiconv \ 35 | libpng \ 36 | libjpeg \ 37 | freetype \ 38 | libwebp \ 39 | imagemagick \ 40 | libxpm \ 41 | libzip \ 42 | busybox-suid ; \ 43 | # dev packages 44 | apk add --no-cache --virtual .fetch-deps \ 45 | icu-dev \ 46 | postgresql-dev \ 47 | rabbitmq-c-dev \ 48 | autoconf \ 49 | musl-dev \ 50 | gcc \ 51 | g++ \ 52 | make \ 53 | pkgconf \ 54 | file \ 55 | curl-dev \ 56 | libpng-dev \ 57 | jpeg-dev \ 58 | freetype-dev \ 59 | libwebp-dev \ 60 | libzip-dev \ 61 | imagemagick-dev \ 62 | libxpm-dev ; \ 63 | docker-php-ext-configure gd \ 64 | --with-webp \ 65 | --with-jpeg \ 66 | --with-xpm \ 67 | --with-freetype ; \ 68 | docker-php-ext-install -j$(nproc) \ 69 | pdo \ 70 | pdo_pgsql \ 71 | intl \ 72 | pcntl \ 73 | gd \ 74 | exif \ 75 | zip \ 76 | opcache ; \ 77 | pecl install amqp ; \ 78 | pecl install xdebug; \ 79 | pecl install imagick ; \ 80 | docker-php-ext-enable amqp ; \ 81 | docker-php-ext-enable xdebug ; \ 82 | docker-php-ext-enable imagick ; \ 83 | # newrelic 84 | mkdir -p /tmp/newrelic ; \ 85 | cd /tmp/newrelic ; \ 86 | curl -L "${NEWRELIC_URL}" -o newrelic.tar.gz ; \ 87 | sha256sum newrelic.tar.gz | grep "${NEWRELIC_SHA256SUM}" ; \ 88 | tar -xf newrelic.tar.gz ; \ 89 | NR_INSTALL_USE_CP_NOT_LN=1 NR_INSTALL_SILENT=1 ./newrelic-php5-*/newrelic-install install ; \ 90 | rm -rf /tmp/newrelic ; \ 91 | php --version ; \ 92 | rm -rf /tmp/* ; \ 93 | update-ca-certificates 94 | # newrelic 95 | 96 | ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php 97 | 98 | COPY ./config/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint 99 | COPY ./config/php/php-fpm.d/zzz-01-healthcheck.conf /usr/local/etc/php-fpm.d/zzz-01-healthcheck.conf 100 | COPY ./config/php/php-fpm-healthcheck.sh /usr/local/bin/php-fpm-healthcheck 101 | COPY ./config/php/php-ini-directives.ini.template /usr/local/etc/php/php-ini-directives.ini.template 102 | 103 | # install Symfony Flex globally to speed up download of Composer packages (parallelized prefetching) \ 104 | RUN set -eux ; \ 105 | chmod +x /usr/local/bin/docker-entrypoint; \ 106 | chmod 755 /usr/local/bin/php-fpm-healthcheck ; \ 107 | composer --ansi --version --no-interaction; \ 108 | composer global require "symfony/flex" --prefer-dist --no-progress --no-suggest --classmap-authoritative; \ 109 | composer clear-cache; 110 | 111 | HEALTHCHECK --start-period=5m CMD php-fpm-healthcheck 112 | ENTRYPOINT ["docker-entrypoint"] 113 | CMD ["php-fpm"] 114 | 115 | WORKDIR /srv/app 116 | 117 | COPY backend/composer.json \ 118 | backend/composer.lock \ 119 | backend/symfony.lock \ 120 | backend/.env \ 121 | backend/.env.test \ 122 | backend/phpunit.xml.dist \ 123 | backend/phpstan.neon.dist \ 124 | backend/phpcs.xml.dist \ 125 | backend/behat.yml.dist \ 126 | backend/build.xml \ 127 | ./ 128 | 129 | RUN set -eux; \ 130 | composer install --prefer-dist --no-autoloader --no-scripts --no-progress --no-suggest; \ 131 | mkdir -p config/jwt var/cache var/log import export public/multimedia public/thumbnail public/avatar; \ 132 | composer clear-cache 133 | 134 | COPY backend/bin bin/ 135 | COPY backend/config config/ 136 | COPY backend/module module/ 137 | COPY backend/public public/ 138 | COPY backend/src src/ 139 | COPY backend/templates templates/ 140 | COPY backend/translations translations/ 141 | 142 | 143 | #clean up 144 | RUN set -eux; \ 145 | chmod +x bin/console; \ 146 | composer dump-autoload --optimize; \ 147 | composer dump-env prod; \ 148 | php -d memory_limit=-1 bin/console cache:clear --env=prod --no-debug ; \ 149 | php -d memory_limit=-1 bin/console cache:clear --env=dev; \ 150 | bin/console assets:install 151 | 152 | FROM php as php_production 153 | # do not use .env in production 154 | RUN set -eux; \ 155 | pecl uninstall xdebug ; \ 156 | rm -f /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \ 157 | # remove unnecessary dev packages 158 | apk del --no-network .fetch-deps ; \ 159 | php --version ; \ 160 | rm -f .env \ 161 | .env.test \ 162 | *.dist \ 163 | *.md \ 164 | config/jwt/*.pem \ 165 | tests \ 166 | features 167 | 168 | #copy app version if exists 169 | COPY backend/.env backend/app.versio[n] ./ 170 | 171 | FROM nginx:1.17-alpine AS nginx 172 | 173 | RUN set -eux; \ 174 | apk add --no-cache \ 175 | curl \ 176 | bash ; \ 177 | rm -rf /tmp/* 178 | 179 | COPY ./config/nginx/conf.d/http-directives.conf.template /etc/nginx/conf.d/http-directives.conf.template 180 | COPY ./config/nginx/conf.d/symfony-development.conf.template /etc/nginx/conf.d/symfony-development.conf.template 181 | COPY ./config/nginx/conf.d/symfony-production.conf.template /etc/nginx/conf.d/symfony-production.conf.template 182 | COPY ./config/nginx/nginx.conf /etc/nginx/nginx.conf 183 | COPY ./config/nginx/docker-entrypoint.sh /usr/local/bin/docker-entrypoint 184 | COPY --from=php /srv/app/public /srv/app/public 185 | 186 | RUN chmod +x /usr/local/bin/docker-entrypoint 187 | 188 | HEALTHCHECK --start-period=5m CMD curl --fail http://localhost/healthcheck.json || exit 1 189 | 190 | ENV NGINX_HTTP_DIRECTIVES="client_max_body_size 250m;" 191 | 192 | ENTRYPOINT ["docker-entrypoint"] 193 | CMD ["nginx", "-g", "daemon off;"] 194 | 195 | FROM node:12.6-alpine as node 196 | 197 | COPY config/node/docker-entrypoint.sh /usr/local/bin/docker-entrypoint 198 | RUN set -eux; \ 199 | chmod +x /usr/local/bin/docker-entrypoint ; \ 200 | apk add --no-cache \ 201 | curl \ 202 | bash \ 203 | git 204 | 205 | 206 | ENTRYPOINT ["docker-entrypoint"] 207 | 208 | FROM node as nuxtjs 209 | 210 | WORKDIR /srv/app 211 | 212 | HEALTHCHECK --start-period=5m CMD curl --fail http://localhost || exit 1 213 | 214 | ENV HOST=0.0.0.0 215 | ENV PORT=80 216 | 217 | WORKDIR /srv/app 218 | 219 | COPY frontend /srv/app/ 220 | 221 | RUN set -eux; \ 222 | npm install ; \ 223 | npm run modules:all ; \ 224 | NODE_ENV=production API_BASE_URL=http://localhost:8000/api/v1/ npm run build ; \ 225 | #clean up 226 | npm cache clean -f ; \ 227 | rm -f .env 228 | 229 | CMD ["npm", "run", "dev"] 230 | 231 | FROM nuxtjs as nuxtjs_production 232 | 233 | WORKDIR /srv/app 234 | 235 | #copy app version if exists 236 | COPY frontend/.env.dist frontend/app.versio[n] ./ 237 | 238 | CMD ["npm", "run", "start"] 239 | 240 | FROM node as docsify 241 | 242 | RUN set -eux; \ 243 | npm install docsify-cli -g ; \ 244 | npm cache clean -f 245 | 246 | HEALTHCHECK --start-period=5m CMD curl --fail http://localhost:3000 || exit 1 247 | 248 | CMD ["docsify", "serve" ,"docs"] 249 | 250 | FROM postgres:10-alpine as postgres 251 | 252 | COPY ./config/postgres/docker-entrypoint-initdb.d /docker-entrypoint-initdb.d 253 | COPY ./config/postgres/postgres-healthcheck.sh /usr/local/bin/postgres-healthcheck.sh 254 | COPY ./config/postgres/ergonode-common-functions.sh /usr/local/bin/ergonode-common-functions.sh 255 | 256 | RUN chmod +x /usr/local/bin/postgres-healthcheck.sh 257 | 258 | HEALTHCHECK --start-period=5m CMD bash -c /usr/local/bin/postgres-healthcheck.sh 259 | 260 | FROM rabbitmq:3.8-management-alpine as rabbitmq-management 261 | 262 | COPY config/rabbitmq/rabbitmq-healthcheck.sh /usr/local/bin/rabbitmq-healthcheck.sh 263 | COPY config/rabbitmq/rabbitmq.conf.template /etc/rabbitmq/rabbitmq.conf.template 264 | COPY config/rabbitmq/docker-ergonode-entrypoint.sh /usr/local/bin/docker-ergonode-entrypoint 265 | 266 | RUN set -eux; \ 267 | chmod +x /usr/local/bin/rabbitmq-healthcheck.sh ; \ 268 | chmod +x /usr/local/bin/docker-ergonode-entrypoint ; \ 269 | rabbitmq-plugins enable --offline rabbitmq_peer_discovery_consul ; \ 270 | apk add --no-cache gettext 271 | 272 | 273 | HEALTHCHECK --start-period=2m CMD bash -c /usr/local/bin/rabbitmq-healthcheck.sh 274 | 275 | 276 | ENTRYPOINT ["docker-ergonode-entrypoint"] 277 | CMD ["rabbitmq-server"] 278 | 279 | FROM haproxy:2.1-alpine as haproxy 280 | RUN set -eux ; \ 281 | apk add --no-cache curl 282 | 283 | COPY config/haproxy/haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg 284 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ergonode Docker 2 | 3 | ## Ergonode Docker uses the following services 4 | 5 | - PostgreSQL 10 6 | - PHP 7.4 7 | - NGINX 1.17 8 | - Docsify 4 9 | - Nodejs 12.6 10 | - RabbitMQ 3.8 11 | 12 | ## Development use 13 | 14 | ### Installation 15 | 16 | At first you must install Docker and Docker Compose (https://docs.docker.com/compose). 17 | 18 | Next, you must clone frontend, backend and docs repositories to ergonode directory: 19 | 20 | ```shell script 21 | git clone git@github.com:ergonode/docker.git ergonode 22 | cd ergonode 23 | git clone git@github.com:ergonode/frontend.git 24 | git clone git@github.com:ergonode/backend.git 25 | git clone git@github.com:ergonode/docs.git 26 | ``` 27 | 28 | If you want to test ergonode in multiple directories you need to create the `.env` file and set 29 | `COMPOSE_PROJECT_NAME` env var to some unique value. 30 | 31 | If you want change any environment variable you can optionally change this in the `.env` file. 32 | And all environment variables used by our docker you can find in the `docker-compose.yml` files. 33 | 34 | Now you can start docker by simple command 35 | 36 | ```shell script 37 | docker-compose up 38 | ``` 39 | 40 | ### Backend setup 41 | 42 | List of changes that must be made in `ergonode/backend` configuration. 43 | 44 | #### Messenger DSN 45 | 46 | Messenger DSN addresses must be changed to `amqp://ergonode:ergonode@rabbit:5672` in your `.env.local` file. 47 | 48 | For example: 49 | ``` 50 | MESSENGER_TRANSPORT_DSN=amqp://ergonode:ergonode@rabbitmq:5672/%2f/messages 51 | ``` 52 | 53 | #### Mailer DSN 54 | 55 | Mailer DSN address must be changed to `smtp://mailhog:1025` in your `.env.local` file. 56 | 57 | ### Database filling 58 | 59 | Now you can fill database with basic data by using command 60 | ```shell script 61 | docker-compose exec php bin/phing database:fixture 62 | ``` 63 | 64 | Or fill database with development data with command 65 | ```shell script 66 | docker-compose exec php bin/phing database:fixture:dev 67 | ``` 68 | 69 | ### Shell side usage 70 | 71 | To run all tests execute 72 | ```shell script 73 | docker-compose exec php bin/phing test 74 | ``` 75 | 76 | To run symfony console 77 | ```shell script 78 | docker-compose exec php bin/console 79 | ``` 80 | 81 | To add new users you can use command 82 | ```shell script 83 | docker-compose exec php bin/console ergonode:user:create [] 84 | ``` 85 | 86 | If you want to enter some container 87 | 88 | ```shell script 89 | docker-compose exec php bash 90 | docker-compose exec postgres bash 91 | docker-compose exec nuxtjs bash 92 | ``` 93 | 94 | ### Browser side usage 95 | 96 | If you want to view frontend panel just type address from below into your browser 97 | 98 | ``` 99 | http://localhost 100 | ``` 101 | 102 | And to test app you can login as `test@ergonode.com` with password `abcd1234` 103 | 104 | If you want to view backend API doc just type address from below into your browser 105 | 106 | ``` 107 | http://localhost:8000/api/doc 108 | ``` 109 | 110 | If you want to review messages on RabbitMQ, type address from below into your browser 111 | 112 | ``` 113 | http://localhost:15672 114 | ``` 115 | 116 | If you want to see documentation, type address from below into your browser 117 | 118 | ``` 119 | http://localhost:8002 120 | ``` 121 | 122 | ## FAQ 123 | 124 | ##### I have error 413 – Request Entity Too Large 125 | You need increase in the nginx `client_max_body_size` and in php `upload_max_size`. 126 | 127 | ##### How to increase the nginx client_max_body_size and in php upload max size? 128 | In the .env file please set `NGINX_HTTP_DIRECTIVES` to `client_max_body_size 250m;` or higher value 129 | `NGINX_HTTP_DIRECTIVES="client_max_body_size 250m;`. 130 | Also you can set `PHP_INI_DIRECTIVES` to `upload_max_filesize=250M; post_max_size = 250M;` 131 | 132 | ##### How to increase php memory limit? 133 | In the `.env` file please set `PHP_INI_DIRECTIVES` to `memory_limit=1024M;` or higher value 134 | ``` 135 | PHP_INI_DIRECTIVES="memory_limit=1024M;" 136 | ``` 137 | 138 | ##### What data are stored? 139 | For now only database in `data` folder 140 | 141 | ##### Where can i change PHP settings? 142 | In the environment variable `PHP_INI_DIRECTIVES` each setting must be delimited by `;` 143 | 144 | ##### Where can i change nginx http settings? 145 | In the environment variable `NGINX_HTTP_DIRECTIVES` each setting must be delimited by `;` 146 | 147 | ##### What if I have better idea? 148 | No problem ! Just tell us about your idea and we will discuse it. Bring lot of beers! 149 | -------------------------------------------------------------------------------- /README.production-test.md: -------------------------------------------------------------------------------- 1 | # Ergonode production docker testing on swarm installed on your localhost 2 | 3 | 4 | ## Preparing the local environment for testing 5 | 6 | ### Enable Swarm mode 7 | 8 | 1. You Must enable swarm mode with command `docker swarm init`: 9 | ``` 10 | $ docker swarm init 11 | Swarm initialized: current node (i4imqmykpz6a6o9amevr491v4) is now a manager. 12 | 13 | To add a worker to this swarm, run the following command: 14 | 15 | docker swarm join --token SWMTKN-1-5gw46owitfxgvgsbdb19a3cz0ox5ulu07tf7ga1zrto6ouuxrc-a2ulaio3v9rnqqbtxwff2tunj 192.168.99.200:2377 16 | 17 | To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. 18 | 19 | ``` 20 | In some cases it will be necessary to execute command `docker swarm init --advertise-addr ` 21 | 22 | More documentation about enabling swarm mode you can find in https://docs.docker.com/engine/swarm/swarm-mode/ 23 | 24 | 25 | ### Set up a Docker registry🔗 26 | 27 | For testing you need setup local registry. 28 | 29 | 1. Start the registry as a service on your swarm: 30 | 31 | ``` 32 | $ docker service create --name registry --publish published=5000,target=5000 registry:2 33 | 5vfwyy0etx9pvb1tcns1qtrl8 34 | overall progress: 1 out of 1 tasks 35 | 1/1: running [==================================================>] 36 | verify: Service converged 37 | ``` 38 | 2. Check its status with `docker service ls`: 39 | 40 | ``` 41 | $ docker service ls 42 | ID NAME MODE REPLICAS IMAGE PORTS 43 | 5vfwyy0etx9p registry replicated 1/1 registry:2 *:5000->5000/tcp 44 | ``` 45 | 3. Check that it’s working with `curl`: 46 | ``` 47 | $ curl http://localhost:5000/v2/ 48 | 49 | {} 50 | ``` 51 | 52 | ### Build your production code 53 | 54 | 1. You Must copy or clone your **production** backend and frontend app to the docker directory. 55 | 56 | 2. Directory structure 57 | 58 | ``` 59 | docker/ 60 | ├── frontend 61 | ├── backend 62 | ``` 63 | 3. Set your **build** environment variables. You can use for this the .env file. 64 | 65 | ```bash 66 | COMPOSE_PROJECT_NAME=ergonode 67 | CONTAINER_REGISTRY_BASE=localhost:5000/ergonode 68 | ``` 69 | 70 | 4. Build with command 71 | ```bash 72 | docker-compose -f docker-compose.deploy.yml build 73 | ``` 74 | 75 | or faster build with enabled BuildKit 76 | ``` 77 | COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f docker-compose.deploy.yml build 78 | ``` 79 | 80 | ### Push images to local registry 81 | 82 | 1. To push your images to your registry you need execute command. 83 | 84 | ```bash 85 | $ docker-compose -f docker-compose.deploy.yml push 86 | Pushing php (localhost:5000/ergonode/php:latest)... 87 | The push refers to repository [localhost:5000/ergonode/php] 88 | 9dcb7c3cba06: Pushed 89 | 317220a89f7a: Pushed 90 | 8869b7f8d14b: Pushed 91 | 0b5d19df65c0: Pushed 92 | 67aa39707573: Pushed 93 | 8f0e5fed38ca: Pushed 94 | 9868b4b7e471: Pushed 95 | 3e5a91435251: Pushed 96 | de4d41a476fa: Pushed 97 | cf44941de815: Pushed 98 | bb9023598f8e: Pushed 99 | 80b84485e3db: Pushed 100 | 09910eb25821: Pushed 101 | 93bcee3daaff: Pushed 102 | c1f1b3bb785a: Pushed 103 | 1769ec9d9fbb: Pushed 104 | 2be2bea30da4: Pushed 105 | 35c5254fa70a: Pushed 106 | 98075e80af84: Pushed 107 | e02653067cbc: Pushed 108 | 6f376367414e: Pushed 109 | 546d72961a9b: Pushed 110 | a284cca01749: Pushed 111 | 0f17bf26d50f: Pushed 112 | a08a6a32d21a: Pushed 113 | 9ca12a39140e: Pushed 114 | 0078526f623d: Pushed 115 | ba661e61e5ca: Pushed 116 | ee40c7334a95: Pushed 117 | beee9f30bc1f: Pushed 118 | latest: digest: sha256:571240eceee46a9ddec431c3a05181e286382925948030585562d03c61b8e4ac size: 6593 119 | Pushing nuxtjs (localhost:5000/ergonode/nuxtjs:latest)... 120 | The push refers to repository [localhost:5000/ergonode/nuxtjs] 121 | d4bf0d1f3bae: Pushed 122 | 5f70bf18a086: Pushed 123 | 4511ef4fad3d: Pushed 124 | 111e3208ee56: Pushed 125 | fe5324d0691a: Pushed 126 | f2569cae1768: Pushed 127 | 352920ec1073: Pushed 128 | 662f8f5a2b7a: Pushed 129 | 00210cd15c5c: Pushed 130 | ffa1cdbe8bf7: Pushed 131 | f1b5933fe4b5: Pushed 132 | latest: digest: sha256:a624e2ff6f8fd1684a377a82c0e6258174684479f5da37fb2d6686997367bff0 size: 2827 133 | Pushing nginx (localhost:5000/ergonode/nginx:latest)... 134 | The push refers to repository [localhost:5000/ergonode/nginx] 135 | 15f7b07e2eb1: Pushed 136 | c4a41daeabbf: Pushed 137 | 6a7bac1cc4a5: Pushed 138 | 0f91bfd1b7b4: Pushed 139 | bc4f27e27c4c: Pushed 140 | 03e7b7ac5f4c: Pushed 141 | ca38b6f1110c: Pushed 142 | 6f23cf4d16de: Pushed 143 | 531743b7098c: Pushed 144 | latest: digest: sha256:96cb5a1245ac7792df763bebe1c261272a4b4e4c7f09d2fd5d066eef20899202 size: 2405 145 | Pushing postgres (localhost:5000/ergonode/postgres:latest)... 146 | The push refers to repository [localhost:5000/ergonode/postgres] 147 | ad721fbf05ac: Pushed 148 | 20b113d053ff: Pushed 149 | a283fe349755: Pushed 150 | 004c5c491659: Pushed 151 | 2084a1a5fdaa: Pushed 152 | 36589f5f7745: Pushed 153 | 554b8a481572: Pushed 154 | ad31bd535054: Pushed 155 | 2d9f8a4bb985: Pushed 156 | c1fe1c22cb47: Pushed 157 | 34ba88304670: Pushed 158 | a55a08db54f9: Pushed 159 | beee9f30bc1f: Mounted from ergonode/php 160 | latest: digest: sha256:51d61dc5992c093fbb69a960376bc20b327fddf807b7876b56e6652c61c2198a size: 3020 161 | Pushing haproxy (localhost:5000/ergonode/haproxy:latest)... 162 | The push refers to repository [localhost:5000/ergonode/haproxy] 163 | 1dd6602aeaba: Pushed 164 | 1d7bfabed83a: Pushed 165 | 26ab55d789a8: Pushed 166 | 065b7480de97: Pushed 167 | beee9f30bc1f: Mounted from ergonode/postgres 168 | latest: digest: sha256:be0c4ef6d6ff88ae660f1e4def955fe70166bb9e57d224b1dda54a0d9cc5549d size: 1363 169 | Pushing rabbitmq (localhost:5000/ergonode/rabbitmq:latest)... 170 | The push refers to repository [localhost:5000/ergonode/rabbitmq] 171 | 84a43432a8f4: Pushed 172 | 14424cfa9842: Pushed 173 | 757705f5325b: Pushed 174 | 0929bd357320: Pushed 175 | 77a02e0abffa: Pushed 176 | ef81076db681: Pushed 177 | 3a77603d9a2e: Pushed 178 | 55285c124aa2: Pushed 179 | 5f445fdd2cbe: Pushed 180 | b533ec746365: Pushed 181 | 3af4411af099: Pushed 182 | ea443b32be83: Pushed 183 | beee9f30bc1f: Mounted from ergonode/haproxy 184 | latest: digest: sha256:81e6b3204ac1688a2476b91227d4a9dad61f835b5794a59b38a2e950f735d5ce size: 3038 185 | ``` 186 | ### Deploy the stack to the swarm 187 | 188 | 189 | 1. You need set all environment required variables described in `docker-compose.production.yml` and in `docker-compose.postgres.yml`. 190 | 2. And also you need create secrets required in `docker-compose.production.yml` and in `docker-compose.postgres.yml`. 191 | 192 | For each secret please enter your secret and press CTRL+D 193 | ``` 194 | $ docker secret create ergonode-postgres-passwd - 195 | ``` 196 | ``` 197 | $ docker secret create ergonode-user-passwd - 198 | ``` 199 | 200 | 3. For environmental variables, you can create a file `.env`. 201 | 202 | 4. Create the your stack with `docker stack deploy:` 203 | ``` 204 | $ env $(cat .env | grep ^[a-zA-Z] | xargs) docker stack deploy --compose-file docker-compose.production.yml --compose-file docker-compose.postgres.yml ergonode 205 | 206 | Creating network ergonode_ergonode 207 | Creating service ergonode_php-messenger-export 208 | Creating service ergonode_rabbitmq-02 209 | Creating service ergonode_php-messenger-core 210 | Creating service ergonode_php 211 | Creating service ergonode_nginx 212 | Creating service ergonode_php-messenger-import 213 | Creating service ergonode_postgres 214 | Creating service ergonode_rabbitmq-01 215 | Creating service ergonode_consul 216 | Creating service ergonode_nuxtjs 217 | Creating service ergonode_php-messenger-segment 218 | Creating service ergonode_rabbitmq-03 219 | Creating service ergonode_haproxy 220 | ``` 221 | 222 | 5. Check that it’s running with `docker stack services ergonode`: 223 | 224 | ```bash 225 | $ docker stack services ergonode 226 | ID NAME MODE REPLICAS IMAGE PORTS 227 | 69uby4hcw9ar ergonode_php-messenger-segment replicated 1/1 localhost:5000/ergonode/php:latest 228 | 8qtlwf3u3wli ergonode_rabbitmq-01 global 1/1 localhost:5000/ergonode/rabbitmq:latest 229 | bvel8mli4ymd ergonode_rabbitmq-03 global 1/1 localhost:5000/ergonode/rabbitmq:latest 230 | cxtlqpulnjjl ergonode_php-messenger-core replicated 1/1 localhost:5000/ergonode/php:latest 231 | g0daudkr5v3c ergonode_php-messenger-export replicated 1/1 localhost:5000/ergonode/php:latest 232 | h9uc5g0kqffy ergonode_postgres global 1/1 localhost:5000/ergonode/postgres:latest 233 | i0u876bxsyul ergonode_nuxtjs replicated 1/1 localhost:5000/ergonode/nuxtjs:latest 234 | jvz19jpgzzb9 ergonode_nginx replicated 1/1 localhost:5000/ergonode/nginx:latest *:80->80/tcp 235 | ls2wvroa777r ergonode_php-messenger-import replicated 1/1 localhost:5000/ergonode/php:latest 236 | n3ukz3z6tm30 ergonode_consul replicated 1/1 consul:1.7 237 | of4toxprxoaf ergonode_rabbitmq-02 global 1/1 localhost:5000/ergonode/rabbitmq:latest 238 | rlnxa9vsuedh ergonode_php replicated 1/1 localhost:5000/ergonode/php:latest 239 | skcutkkb5fza ergonode_haproxy global 1/1 localhost:5000/ergonode/haproxy:latest *:15672->15672/tcp 240 | ``` 241 | This might take some time if you have a multi-node swarm, as images need to be pulled. 242 | It may take some time if you have a multi-node, because the images have need to be pulled by swarm nodes. 243 | 244 | And you can test your application on port 80 (by default this is set in environment variable $EXPOSED_NGINX_PORT) at http://your-swarm-node-ip. 245 | 246 | 6. To check your service logs you can do this with `docker service logs ergonode_service_name` 247 | ```bash 248 | $ docker service logs -f ergonode_nginx 249 | ergonode_nginx.1.z8ohiml3lj9l@swarm | 127.0.0.1 - - [25/Feb/2020:09:59:49 +0000] "GET /api/doc HTTP/1.1" 200 98347 "-" "curl/7.66.0" "-" 250 | ``` 251 | 7. To troubleshoot why some services does not up . You can find your service container with command: 252 | ```bash 253 | $ docker ps 254 | ``` 255 | 256 | This example display container id for php service 257 | 258 | ```bash 259 | $ docker ps -f name=ergonode_php.1 260 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 261 | a81d054a6473 localhost:5000/ergonode/php:latest "docker-entrypoint p…" 10 minutes ago Up 10 minutes (healthy) 9000/tcp ergonode_php.1.fd63lm163x7wudnob7xrju91h 262 | ``` 263 | 264 | And to display logs you can execute 265 | ``` 266 | $ docker logs a81d054a6473 267 | Linking /usr/local/etc/php/php.ini-production > /usr/local/etc/php/php.ini 268 | Verified OK 269 | Setting file permissions... 270 | Waiting for db to be ready... 271 | 272 | Doctrine Database Migrations 273 | 274 | 275 | No migrations to execute. 276 | app initialization finished 277 | [01-Apr-2020 18:30:05] NOTICE: fpm is running, pid 1 278 | [01-Apr-2020 18:30:05] NOTICE: ready to handle connections 279 | ``` 280 | 281 | 8. If you want to bring down your stack then you can execute `docker stack rm:` 282 | ```bash 283 | $ docker stack rm ergonode 284 | 285 | Removing service ergonode_consul 286 | Removing service ergonode_haproxy 287 | Removing service ergonode_nginx 288 | Removing service ergonode_nuxtjs 289 | Removing service ergonode_php 290 | Removing service ergonode_php-messenger-core 291 | Removing service ergonode_php-messenger-export 292 | Removing service ergonode_php-messenger-import 293 | Removing service ergonode_php-messenger-segment 294 | Removing service ergonode_postgres 295 | Removing service ergonode_rabbitmq-01 296 | Removing service ergonode_rabbitmq-02 297 | Removing service ergonode_rabbitmq-03 298 | Removing network ergonode_ergonode 299 | ``` 300 | 301 | And you can optionally prune ergonode volumes 302 | 303 | ``` 304 | $ docker volume prune --filter label=com.docker.stack.namespace=ergonode 305 | WARNING! This will remove all local volumes not used by at least one container. 306 | Are you sure you want to continue? [y/N] y 307 | Deleted Volumes: 308 | ergonode_multimedia 309 | ergonode_avatar 310 | ergonode_import 311 | ergonode_jwt 312 | ergonode_ergonode-postgres-data 313 | ergonode_rabbitmq-01 314 | ergonode_rabbitmq-02 315 | ergonode_rabbitmq-03 316 | 317 | Total reclaimed space: 1.086GB 318 | ``` 319 | -------------------------------------------------------------------------------- /README.production.md: -------------------------------------------------------------------------------- 1 | # Ergonode production docker 2 | 3 | 4 | ## Build 5 | 6 | 1. You Must copy or clone your **production** backend and frontend app to the docker directory. 7 | 8 | 2. Directory structure 9 | 10 | ``` 11 | docker/ 12 | ├── frontend 13 | ├── backend 14 | ``` 15 | 16 | 3. Set your **build** environment variables. You can use for this the .env file. 17 | 18 | ```bash 19 | COMPOSE_PROJECT_NAME=your-app-name 20 | CONTAINER_REGISTRY_BASE=your-registry-url/your-app-name 21 | ``` 22 | 23 | And optionally your IMAGE tag, by default this is already set to latest. 24 | 25 | ```bash 26 | IMAGE_TAG=latest 27 | ``` 28 | 4. Build with command 29 | ```bash 30 | docker-compose -f docker-compose.deploy.yml build 31 | ``` 32 | 33 | or faster build with enabled BuildKit 34 | ``` 35 | COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f docker-compose.deploy.yml build 36 | ``` 37 | 38 | ## Test you images 39 | 40 | 1. For testing your backend code must have must have correctly configured test tools. 41 | If you have correctly set up your testing tools you can execute the commands: 42 | 43 | 44 | ```bash 45 | #!/bin/bash 46 | 47 | set -eo pipefail 48 | 49 | function finish { 50 | docker-compose -f docker-compose.test.yml rm --stop --force 51 | } 52 | trap finish EXIT 53 | docker-compose -f docker-compose.test.yml up -d 54 | until docker-compose -f docker-compose.test.yml run --rm php bin/console doctrine:query:sql "SELECT 1" > /dev/null 2>&1; do 55 | sleep 1 56 | done 57 | 58 | docker-compose -f docker-compose.test.yml run -e "PHP_INI_DIRECTIVES=memory_limit=-1" --rm php bin/phing test 59 | docker-compose -f docker-compose.test.yml run --rm nuxtjs npm run test 60 | ``` 61 | 62 | 2. To test your images on local machine you can use command 63 | 64 | ``` 65 | docker-compose -f docker-compose.production.yml -f docker-compose.postgres.yml up -d 66 | ``` 67 | 3. And test your app on port 80 (by default this is set in environment variable $EXPOSED_NGINX_PORT) at http://localhost 68 | 69 | # Push images to registry 70 | 71 | 1. To push your images to your registry you need execute commands. 72 | 73 | 74 | ```bash 75 | docker login your-registry-url 76 | docker-compose -f docker-compose.deploy.yml push 77 | ``` 78 | 79 | ## Deploy the stack to the swarm 80 | 81 | 82 | 1. You need login to your swarm server by ssh and following command execute on your docker swarm server. 83 | 84 | 2. You need set all environment required variables described in `docker-compose.production.yml` and optionally in `docker-compose.postgres.yml`. 85 | 86 | 3. For environmental variables, you can create a file `.env`. 87 | 88 | 4. Example `.env` file: 89 | 90 | ```bash 91 | COMPOSE_PROJECT_NAME=your-app-name 92 | CONTAINER_REGISTRY_BASE=your-registry-url/your-app-name 93 | 94 | ... 95 | ``` 96 | 5. Login to your registry (if your registry require this for pulling docker images) 97 | 98 | ```bash 99 | docker login your-registry-url 100 | ``` 101 | 102 | 6. Create the your stack with `docker stack deploy:` 103 | ``` 104 | $ env $(cat .env | grep ^[a-zA-Z] | xargs) docker stack deploy --compose-file docker-compose.production.yml --compose-file docker-compose.postgres.yml ergonode 105 | 106 | Creating network ergonode_ergonode 107 | Creating service ergonode_php-messenger-export 108 | Creating service ergonode_rabbitmq-02 109 | Creating service ergonode_php-messenger-core 110 | Creating service ergonode_php 111 | Creating service ergonode_nginx 112 | Creating service ergonode_php-messenger-import 113 | Creating service ergonode_postgres 114 | Creating service ergonode_rabbitmq-01 115 | Creating service ergonode_consul 116 | Creating service ergonode_nuxtjs 117 | Creating service ergonode_php-messenger-segment 118 | Creating service ergonode_rabbitmq-03 119 | Creating service ergonode_haproxy 120 | ``` 121 | 122 | If You have managed PostgreSQL by your provider you can skip option `--compose-file docker-compose.postgres.yml` 123 | 124 | 7. Check that it’s running with `docker stack services ergonode`: 125 | ```bash 126 | $ docker stack services ergonode 127 | ID NAME MODE REPLICAS IMAGE PORTS 128 | 4uwzc0p9hetl ergonode_nginx replicated 1/1 docker.io/ergonode/nginx:latest *:80->80/tcp 129 | q1me75mm90pw ergonode_nuxtjs replicated 1/1 docker.io/ergonode/nuxtjs:latest 130 | rlgcj8dyj54z ergonode_postgres replicated 1/1 docker.io/ergonode/postgres:latest 131 | s4hlonu65i8g ergonode_php replicated 1/1 docker.io/ergonode/php:latest 132 | ``` 133 | This might take some time if you have a multi-node swarm, as images need to be pulled. 134 | It may take some time if you have a multi-node, because the images have need to be pulled by swarm nodes. 135 | 136 | And you can test your application on port 80 (by default this is set in environment variable $EXPOSED_NGINX_PORT) at http://your-swarm-node-ip. 137 | 138 | 9. To check your service logs you can do this with `docker service logs ergonode_service_name` 139 | ```bash 140 | $ docker service logs -f ergonode_nginx 141 | ergonode_nginx.1.z8ohiml3lj9l@swarm | 127.0.0.1 - - [25/Feb/2020:09:59:49 +0000] "GET /api/doc HTTP/1.1" 200 98347 "-" "curl/7.66.0" "-" 142 | ``` 143 | 144 | 10. If you want to bring down your stack then you can execute `docker stack rm:` 145 | ```bash 146 | $ docker stack rm ergonode 147 | 148 | Removing service ergonode_nginx 149 | Removing service ergonode_nuxtjs 150 | Removing service ergonode_php 151 | Removing service ergonode_postgres 152 | Removing network ergonode_ergonode 153 | ``` 154 | -------------------------------------------------------------------------------- /UPGRADING.md: -------------------------------------------------------------------------------- 1 | # Upgrading Notes 2 | 3 | This document captures breaking changes between versions. 4 | 5 | # Upgrading Notes (0.6.x to 7) 6 | 7 | * Move frontend, backend, docs directories to the docker directory (main directory of this project). 8 | * Manually remove `frontend/node_modules` and `docs/node_modules` directories. 9 | * Since version 7.0, the `.env` file for development is optional, you do not need to create it. 10 | -------------------------------------------------------------------------------- /config/haproxy/haproxy.cfg: -------------------------------------------------------------------------------- 1 | global 2 | log 127.0.0.1 local0 3 | log 127.0.0.1 local1 notice 4 | maxconn 4096 5 | 6 | defaults 7 | log global 8 | option tcplog 9 | option dontlognull 10 | timeout connect 6s 11 | timeout client 60s 12 | timeout server 60s 13 | 14 | listen stats 15 | bind *:1936 16 | mode http 17 | stats enable 18 | stats hide-version 19 | stats realm Haproxy\ Statistics 20 | stats uri / 21 | 22 | listen rabbitmq 23 | bind *:5672 24 | mode tcp 25 | server rabbitmq-01 rabbitmq-01:5672 check 26 | server rabbitmq-02 rabbitmq-02:5672 check 27 | server rabbitmq-03 rabbitmq-03:5672 check 28 | 29 | listen rabbitmq-ui 30 | bind *:15672 31 | mode http 32 | server rabbitmq-01 rabbitmq-01:15672 check 33 | server rabbitmq-02 rabbitmq-02:15672 check 34 | server rabbitmq-03 rabbitmq-03:15672 check -------------------------------------------------------------------------------- /config/nginx/conf.d/http-directives.conf.template: -------------------------------------------------------------------------------- 1 | ${NGINX_HTTP_DIRECTIVES}; 2 | 3 | -------------------------------------------------------------------------------- /config/nginx/conf.d/symfony-development.conf.template: -------------------------------------------------------------------------------- 1 | upstream php-upstream { 2 | server ${PHP_HOST}:9000; 3 | } 4 | 5 | upstream nuxtjs-upstream { 6 | server ${NUXTJS_HOST}:80; 7 | } 8 | 9 | server { 10 | server_name symfony; 11 | root /srv/app/public; 12 | 13 | location / { 14 | try_files ${DOLLAR}uri /index.php${DOLLAR}is_args${DOLLAR}args; 15 | # kill cache 16 | 17 | add_header Last-Modified ${DOLLAR}date_gmt; 18 | add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; 19 | if_modified_since off; 20 | expires off; 21 | etag off; 22 | } 23 | 24 | location ~ ^/index\.php(/|$) { 25 | fastcgi_pass php-upstream; 26 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 27 | include fastcgi_params; 28 | # When you are using symlinks to link the document root to the 29 | # current version of your application, you should pass the real 30 | # application path instead of the path to the symlink to PHP 31 | # FPM. 32 | # Otherwise, PHP's OPcache may not properly detect changes to 33 | # your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126 34 | # for more information). 35 | 36 | fastcgi_param SCRIPT_FILENAME ${DOLLAR}realpath_root${DOLLAR}fastcgi_script_name; 37 | fastcgi_param DOCUMENT_ROOT ${DOLLAR}realpath_root; 38 | # Prevents URIs that include the front controller. This will 404: 39 | # http://domain.tld/index.php/some-path 40 | # Remove the internal directive to allow URIs like this 41 | internal; 42 | } 43 | 44 | # return 404 for all other php files not matching the front controller 45 | # this prevents access to other php files you don't want to be accessible. 46 | location ~ \.php$ { 47 | return 404; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /config/nginx/conf.d/symfony-production.conf.template: -------------------------------------------------------------------------------- 1 | upstream php-upstream { 2 | server ${PHP_HOST}:9000; 3 | } 4 | 5 | upstream nuxtjs-upstream { 6 | server ${NUXTJS_HOST}:80; 7 | } 8 | 9 | server { 10 | server_name symfony; 11 | root /srv/app/public; 12 | 13 | location ~* ^/(api|bundles) { 14 | try_files ${DOLLAR}uri /index.php${DOLLAR}is_args${DOLLAR}args; 15 | } 16 | 17 | location / { 18 | try_files ${DOLLAR}uri @nuxtjs; 19 | } 20 | 21 | location @nuxtjs { 22 | proxy_pass http://nuxtjs-upstream; 23 | proxy_set_header Host ${DOLLAR}host; 24 | proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for; 25 | } 26 | 27 | location ~ ^/index\.php(/|$) { 28 | fastcgi_pass php-upstream; 29 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 30 | include fastcgi_params; 31 | # When you are using symlinks to link the document root to the 32 | # current version of your application, you should pass the real 33 | # application path instead of the path to the symlink to PHP 34 | # FPM. 35 | # Otherwise, PHP's OPcache may not properly detect changes to 36 | # your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126 37 | # for more information). 38 | 39 | fastcgi_param SCRIPT_FILENAME ${DOLLAR}realpath_root${DOLLAR}fastcgi_script_name; 40 | fastcgi_param DOCUMENT_ROOT ${DOLLAR}realpath_root; 41 | # Prevents URIs that include the front controller. This will 404: 42 | # http://domain.tld/index.php/some-path 43 | # Remove the internal directive to allow URIs like this 44 | internal; 45 | } 46 | 47 | # return 404 for all other php files not matching the front controller 48 | # this prevents access to other php files you don't want to be accessible. 49 | location ~ \.php$ { 50 | return 404; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /config/nginx/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # first arg is `-f` or `--some-option` 6 | if [ "${1#-}" != "$1" ]; then 7 | set -- nginx "$@" 8 | fi 9 | 10 | if [ "$1" = 'nginx' ] ; then 11 | 12 | DOLLAR="\$" envsubst < /etc/nginx/conf.d/http-directives.conf.template | sed "s~;\s*~;\n~g" | sed "s~^\s*;~~g" > /etc/nginx/conf.d/default.conf 13 | if [ "$APP_ENV" == 'prod' ]; then 14 | DOLLAR="\$" envsubst < /etc/nginx/conf.d/symfony-production.conf.template >> /etc/nginx/conf.d/default.conf 15 | else 16 | DOLLAR="\$" envsubst < /etc/nginx/conf.d/symfony-development.conf.template >> /etc/nginx/conf.d/default.conf 17 | fi 18 | 19 | >&2 echo "nginx initialization finished" 20 | function finish { 21 | jobs=$(jobs -p) 22 | if [[ -n ${jobs} ]] ; then 23 | kill $(jobs -p) 24 | fi 25 | } 26 | trap finish EXIT 27 | 28 | startTime=$SECONDS 29 | until "$@" ; do 30 | exitCode=$? 31 | sleep 5 32 | elapsedTime=$(($SECONDS - $startTime)) 33 | if (( $elapsedTime > ${START_PERIOD:-300} )); then 34 | exit ${exitCode} 35 | fi 36 | done 37 | else 38 | exec "$@" 39 | fi 40 | -------------------------------------------------------------------------------- /config/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | user nginx; 3 | worker_processes auto; 4 | 5 | error_log /var/log/nginx/error.log warn; 6 | pid /var/run/nginx.pid; 7 | 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | 14 | http { 15 | include /etc/nginx/mime.types; 16 | default_type application/octet-stream; 17 | 18 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 19 | '$status $body_bytes_sent "$http_referer" ' 20 | '"$http_user_agent" "$http_x_forwarded_for"'; 21 | 22 | access_log /var/log/nginx/access.log main; 23 | 24 | sendfile on; 25 | #tcp_nopush on; 26 | 27 | keepalive_timeout 65; 28 | 29 | server_tokens off; 30 | gzip on; 31 | 32 | include /etc/nginx/conf.d/*.conf; 33 | } 34 | -------------------------------------------------------------------------------- /config/node/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" = 'npm' ] ; then 4 | if [ "$NODE_ENV" != 'production' ]; then 5 | npm install 6 | if [[ ! -f ".env" ]] ; then 7 | cp .env.dist .env 8 | fi 9 | npm run modules:all 10 | fi 11 | 12 | if [ "$1" = 'npm' ] && [ "$2" = 'run' ] && [ "$3" = 'start' ]; then 13 | 14 | if [ -n "${API_BASE_URL}" ] && [ -d ".nuxt" ]; then 15 | >&2 echo "Setting API_BASE_URL to ${API_BASE_URL}" 16 | find ".nuxt" -type f -exec sed -i "s~http://localhost:8000/api/v1/~${API_BASE_URL}~g" {} + 17 | else 18 | npm run build 19 | fi 20 | fi 21 | 22 | echo -e "\e[30;48;5;82mergonode frontend is available at http://localhost:${EXPOSED_NODE_PORT} \e[0m" 23 | fi 24 | 25 | exec "$@" -------------------------------------------------------------------------------- /config/php/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | function disableXdebug() { 6 | if [ -f "/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini" ] ; then 7 | mv /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini /usr/local/etc/docker-php-ext-xdebug.ini 8 | fi 9 | } 10 | 11 | function enableXdebug() { 12 | if [ -f "/usr/local/etc/docker-php-ext-xdebug.ini" ] ; then 13 | mv /usr/local/etc/docker-php-ext-xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini 14 | fi 15 | } 16 | 17 | if [[ "${NEWRELIC_ENABLE:-0}" -eq 0 ]] && [[ -f /usr/local/etc/php/conf.d/newrelic.ini ]] ; then 18 | rm /usr/local/etc/php/conf.d/newrelic.ini 19 | fi 20 | 21 | function jwtKeysAreCorrect() { 22 | local privatePath=$1 23 | local publicPath=$2 24 | local passArg=$3 25 | 26 | echo 1234 > /tmp/to-sign.txt 27 | openssl dgst -sha256 -sign "${privatePath}" -passin "${passArg}" -out /tmp/sign.sha256 /tmp/to-sign.txt 2>/dev/null 28 | openssl dgst -sha256 -verify "${publicPath}" -signature /tmp/sign.sha256 /tmp/to-sign.txt 2>/dev/null 29 | } 30 | 31 | function genereJwtKeys() { 32 | local privatePath=$1 33 | local publicPath=$2 34 | local passArg=$3 35 | 36 | openssl genrsa -aes256 -passout "${passArg}" -out "${privatePath}" 4096 37 | openssl rsa -pubout -in "${privatePath}" -passin "${passArg}" -out "${publicPath}" 38 | } 39 | 40 | function fixPermissionForJwtKeys() { 41 | local privatePath=$1 42 | local publicPath=$2 43 | 44 | chown root:www-data "${privatePath}" 45 | chmod 640 "${privatePath}" 46 | chmod 640 "${publicPath}" 47 | } 48 | 49 | 50 | function genereJwtKeysIfInvalid() { 51 | local privatePath=$1 52 | local publicPath=$2 53 | local passArg=$3 54 | 55 | if ! jwtKeysAreCorrect "${privatePath}" "${publicPath}" "${passArg}"; then 56 | >&2 echo "Generating jwt keys..." 57 | genereJwtKeys "${privatePath}" "${publicPath}" "${passArg}" 58 | fi 59 | 60 | fixPermissionForJwtKeys "${privatePath}" "${publicPath}" 61 | } 62 | 63 | function waitUntil() { 64 | until "$@" > /dev/null 2>&1 ; do 65 | sleep 1 66 | done 67 | } 68 | 69 | function createApplicationDirs() 70 | { 71 | mkdir -p var/cache var/log public/multimedia public/thumbnail public/avatar import export 72 | >&2 echo "Setting file permissions..." 73 | if setfacl -m u:www-data:rwX -m u:"$(whoami)":rwX var ; then 74 | setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var 75 | setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var 76 | setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX public/multimedia 77 | setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX public/multimedia 78 | setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX public/thumbnail 79 | setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX public/thumbnail 80 | setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX public/avatar 81 | setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX public/avatar 82 | setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX import 83 | setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX import 84 | setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX export 85 | setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX export 86 | else 87 | chown -R www-data var 88 | chown -R www-data public/multimedia 89 | chown -R www-data public/thumbnail 90 | chown -R www-data public/avatar 91 | chown -R www-data import 92 | chown -R www-data export 93 | fi 94 | } 95 | 96 | function createAmqpVhost() { 97 | local scheme=$(echo $1 | php -r "echo @parse_url(stream_get_contents(STDIN))['scheme'];") 98 | 99 | if [[ "${scheme}" != 'amqp' ]] ; then 100 | return 0 101 | fi 102 | 103 | local host=$(echo $1 | php -r "echo @parse_url(stream_get_contents(STDIN))['host'];") 104 | #local port=$(echo $1 | php -r "echo @parse_url(stream_get_contents(STDIN))['port'];") 105 | local port=15672 106 | local user=$(echo $1 | php -r "echo @parse_url(stream_get_contents(STDIN))['user'];") 107 | local pass=$(echo $1 | php -r "echo @parse_url(stream_get_contents(STDIN))['pass'];") 108 | local path=$(echo $1 | php -r "echo @parse_url(stream_get_contents(STDIN))['path'];") 109 | local vhost=$(echo $1 | php -r "echo (@explode('/', @parse_url(stream_get_contents(STDIN))['path']))[1];") 110 | 111 | local url="http://${host}:${port}/api/vhosts/${vhost}" 112 | local userPass="${user}:${pass}" 113 | curl -u "${userPass}" --fail "${url}" || curl --silent --show-error -u "${userPass}" --fail -X PUT "${url}" 114 | } 115 | 116 | # first arg is `-f` or `--some-option` 117 | if [ "${1#-}" != "$1" ]; then 118 | set -- php-fpm "$@" 119 | fi 120 | 121 | 122 | envsubst < /usr/local/etc/php/php-ini-directives.ini.template | sed "s~;\s*~\n~g" > /usr/local/etc/php/conf.d/php-ini-directives.ini 123 | 124 | if [ "$1" = 'php-fpm' ] || [[ "$1" =~ (vendor/)?bin/.* ]] || [ "$1" = 'composer' ]; then 125 | 126 | PHP_INI_RECOMMENDED="$PHP_INI_DIR/php.ini-production" 127 | if [ "$APP_ENV" != 'prod' ]; then 128 | PHP_INI_RECOMMENDED="$PHP_INI_DIR/php.ini-development" 129 | fi 130 | echo "Linking ${PHP_INI_RECOMMENDED} > ${PHP_INI_DIR}/php.ini" 131 | ln -sf "$PHP_INI_RECOMMENDED" "$PHP_INI_DIR/php.ini" 132 | 133 | disableXdebug 134 | genereJwtKeysIfInvalid "${JWT_PRIVATE_KEY_PATH}" "${JWT_PUBLIC_KEY_PATH}" env:JWT_PASSPHRASE 135 | fi 136 | 137 | if [[ "$1" =~ bin/console ]] && [[ "$2" = 'messenger:consume' ]]; then 138 | 139 | createAmqpVhost "${MESSENGER_TRANSPORT_IMPORT_DSN}" 140 | createAmqpVhost "${MESSENGER_TRANSPORT_EXPORT_DSN}" 141 | createAmqpVhost "${MESSENGER_TRANSPORT_NOTIFICATION_DSN}" 142 | 143 | bin/console messenger:setup-transports --no-interaction import 144 | bin/console messenger:setup-transports --no-interaction export 145 | bin/console messenger:setup-transports --no-interaction notification 146 | 147 | >&2 echo "messenger initialization finished" 148 | fi 149 | 150 | if [ "$1" = 'php-fpm' ] ; then 151 | createApplicationDirs 152 | 153 | if [ "$APP_ENV" != 'prod' ]; then 154 | composer install --prefer-dist --no-progress --no-suggest --no-interaction 155 | fi 156 | 157 | >&2 echo "Waiting for db to be ready..." 158 | waitUntil bin/console doctrine:query:sql "SELECT 1" 159 | 160 | if [ "$APP_ENV" != 'prod' ]; then 161 | bin/phing build 162 | fi 163 | 164 | bin/console ergonode:migrations:migrate --no-interaction --allow-no-migration 165 | 166 | if [ "$APP_ENV" != 'prod' ]; then 167 | enableXdebug 168 | echo -e "\e[30;48;5;82mergonode api is available at http://localhost:${EXPOSED_NGINX_PORT} \e[0m" 169 | fi 170 | 171 | >&2 echo "app initialization finished" 172 | fi 173 | 174 | if [ "$1" = 'crond' ] ; then 175 | createApplicationDirs 176 | 177 | function finish { 178 | jobs=$(jobs -p) 179 | if [[ -n ${jobs} ]] ; then 180 | kill $(jobs -p) 181 | fi 182 | } 183 | trap finish EXIT 184 | 185 | # each enty for CRONTAB must be delimited by ; example: 186 | # * * * * * /srv/app/bin/console channel:export:schedule >> /srv/app/var/log/crond.log ; * * * * * /srv/app/bin/console some:other:cmd >> /srv/app/var/log/crond.log 187 | 188 | echo "${CRONTAB:-* * * * * /srv/app/bin/console channel:export:schedule >> /srv/app/var/log/crond.log}" | sed "s~;\s*~\n~g" > /tmp/cron.install 189 | su -s /bin/bash www-data -c 'cat /tmp/cron.install | crontab -' 190 | rm -f /tmp/cron.install 191 | >&2 echo "installed crontab" 192 | su -s /bin/bash www-data -c 'crontab -l' 193 | su -s /bin/bash www-data -c "touch /srv/app/var/log/crond.log" 194 | crond -f & 195 | tail -f /srv/app/var/log/crond.log 196 | 197 | else 198 | exec docker-php-entrypoint "$@" 199 | fi 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /config/php/php-fpm-healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim: set filetype=sh : 3 | 4 | # Author: https://github.com/renatomefi 5 | # The original code lives in https://github.com/renatomefi/php-fpm-healthcheck 6 | # 7 | # A POSIX compliant shell script to healthcheck PHP fpm status, can be used only for pinging the status page 8 | # or check for specific metrics 9 | # 10 | # i.e.: ./php-fpm-healthcheck --verbose --active-processes=6 11 | # The script will fail in case the 'active processes' is bigger than 6. 12 | # 13 | # You can combine multiple options as well, the first one to fail will fail the healthcheck 14 | # i.e.: ./php-fpm-healthcheck --listen-queue-len=10 --active-processes=6 15 | # 16 | # Ping mode (exit 0 if php-fpm returned data): ./php-fpm-healthcheck 17 | # 18 | # Ping mode with data (outputs php-fpm status text): ./php-fpm-healthcheck -v 19 | # 20 | # Exit status codes: 21 | # 2,9,111 - Couldn't connect to PHP fpm, is it running? 22 | # 8 - Couldn't reach PHP fpm status page, have you configured it with `pm.status_path = /status`? 23 | # 1 - A healthcheck condition has failed 24 | # 3 - Invalid option given 25 | # 4 - One or more required softwares are missing 26 | # 27 | # Available options: 28 | # -v|--verbose 29 | # 30 | # Metric options, fails in case the CURRENT VALUE is bigger than the GIVEN VALUE 31 | # --accepted-conn=n 32 | # --listen-queue=n 33 | # --max-listen-queue=n 34 | # --idle-processes=n 35 | # --active-processes=n 36 | # --total-processes=n 37 | # --max-active-processes=n 38 | # --max-children-reached=n 39 | # --slow-requests=n 40 | # 41 | 42 | set -eu 43 | 44 | OPTIND=1 # Reset getopt in case it has been used previously in the shell 45 | 46 | # FastCGI variables 47 | export REQUEST_METHOD="GET" 48 | export SCRIPT_NAME="/status" 49 | export SCRIPT_FILENAME="/status" 50 | FCGI_CONNECT_DEFAULT="localhost:9000" 51 | 52 | # Required software 53 | FCGI_CMD_PATH=$(command -v cgi-fcgi) || { >&2 echo "Make sure fcgi is installed (i.e. apk add --no-cache fcgi). Aborting."; exit 4; } 54 | command -v sed 1> /dev/null || { >&2 echo "Make sure sed is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; } 55 | command -v tail 1> /dev/null || { >&2 echo "Make sure tail is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; } 56 | command -v grep 1> /dev/null || { >&2 echo "Make sure grep is installed (i.e. apk add --no-cache grep). Aborting."; exit 4; } 57 | 58 | # Get status from fastcgi connection 59 | # $1 - cgi-fcgi connect argument 60 | get_fpm_status() { 61 | if test "$VERBOSE" = 1; then printf "Trying to connect to php-fpm via: %s\\n" "$1"; fi; 62 | 63 | # Since I cannot use pipefail I'll just split these in two commands 64 | FPM_STATUS=$(env -i REQUEST_METHOD="$REQUEST_METHOD" SCRIPT_NAME="$SCRIPT_NAME" SCRIPT_FILENAME="$SCRIPT_FILENAME" "$FCGI_CMD_PATH" -bind -connect "$1" 2> /dev/null) 65 | FPM_STATUS=$(echo "$FPM_STATUS" | tail +5) 66 | 67 | if test "$VERBOSE" = 1; then printf "php-fpm status output:\\n%s\\n" "$FPM_STATUS"; fi; 68 | 69 | if test "$FPM_STATUS" = "File not found."; then 70 | >&2 printf "php-fpm status page non reachable\\n"; 71 | exit 8; 72 | fi; 73 | } 74 | 75 | # $1 - fpm option 76 | # $2 - expected value threshold 77 | check_fpm_health_by() { 78 | OPTION=$(echo "$1" | sed 's/--//g; s/-/ /g;') 79 | VALUE_EXPECTED="$2"; 80 | VALUE_ACTUAL=$(echo "$FPM_STATUS" | grep "^$OPTION:" | cut -d: -f2 | sed 's/ //g') 81 | 82 | if test "$VERBOSE" = 1; then printf "'%s' value '%s' and expected is less than '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED"; fi; 83 | 84 | if test "$VALUE_ACTUAL" -gt "$VALUE_EXPECTED"; then 85 | >&2 printf "'%s' value '%s' is greater than expected '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED"; 86 | exit 1; 87 | fi; 88 | } 89 | 90 | PARAM_AMOUNT=0 91 | 92 | # $1 - fpm option 93 | # $2 - expected value threshold 94 | check_later() { 95 | # The POSIX sh way to check if it's an integer, also the output is supressed since it's polution 96 | if ! test "$2" -eq "$2" 2> /dev/null; then 97 | >&2 printf "'%s' option value must be an integer, '%s' given\\n" "$1" "$2"; exit 3; 98 | fi 99 | 100 | PARAM_AMOUNT=$(( PARAM_AMOUNT + 1 )) 101 | 102 | eval "PARAM_TO_CHECK$PARAM_AMOUNT=$1" 103 | eval "VALUE_TO_CHECK$PARAM_AMOUNT=$2" 104 | } 105 | 106 | # From the PARAM_TO_CHECK/VALUE_TO_CHECK magic variables, do all the checks 107 | check_fpm_health() { 108 | j=1 109 | while [ $j -le $PARAM_AMOUNT ]; do 110 | eval "CURRENT_PARAM=\$PARAM_TO_CHECK$j" 111 | eval "CURRENT_VALUE=\$VALUE_TO_CHECK$j" 112 | check_fpm_health_by "$CURRENT_PARAM" "$CURRENT_VALUE" 113 | j=$(( j + 1 )) 114 | done 115 | } 116 | 117 | if ! GETOPT=$(getopt -o v --long verbose,accepted-conn:,listen-queue:,max-listen-queue:,listen-queue-len:,idle-processes:,active-processes:,total-processes:,max-active-processes:,max-children-reached:,slow-requests: -n 'php-fpm-healthcheck' -- "$@"); then 118 | >&2 echo "Invalid options, terminating." ; exit 3 119 | fi; 120 | 121 | eval set -- "$GETOPT" 122 | 123 | FCGI_CONNECT="${FCGI_CONNECT:-$FCGI_CONNECT_DEFAULT}" 124 | 125 | VERBOSE=0 126 | 127 | while test "$1"; do 128 | case "$1" in 129 | -v|--verbose ) VERBOSE=1; shift ;; 130 | --) shift ; break ;; 131 | * ) check_later "$1" "$2"; shift 2 ;; 132 | esac 133 | done 134 | 135 | FPM_STATUS=false 136 | 137 | get_fpm_status "$FCGI_CONNECT" 138 | check_fpm_health -------------------------------------------------------------------------------- /config/php/php-fpm.d/zzz-01-healthcheck.conf: -------------------------------------------------------------------------------- 1 | [www] 2 | 3 | ; healthcheck 4 | pm.status_path = /status 5 | ping.path = /ping 6 | -------------------------------------------------------------------------------- /config/php/php-ini-directives.ini.template: -------------------------------------------------------------------------------- 1 | ${PHP_INI_DIRECTIVES} 2 | -------------------------------------------------------------------------------- /config/postgres/docker-entrypoint-initdb.d/10-create-app-user.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | . /usr/local/bin/ergonode-common-functions.sh 6 | 7 | #escape string with double quotes 8 | app_password=${app_password/\'/\'\'} 9 | 10 | 11 | psql -v ON_ERROR_STOP=1 \ 12 | --dbname "$db" \ 13 | --username="$user" <<-EOSQL 14 | CREATE ROLE ${app_user} LOGIN PASSWORD '${app_password}' CREATEDB; 15 | EOSQL 16 | -------------------------------------------------------------------------------- /config/postgres/docker-entrypoint-initdb.d/10-create-required-extensions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | . /usr/local/bin/ergonode-common-functions.sh 6 | 7 | psql -v ON_ERROR_STOP=1 \ 8 | --dbname "template1" \ 9 | --username="$user" <<-EOSQL 10 | CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; 11 | CREATE EXTENSION IF NOT EXISTS "ltree"; 12 | EOSQL 13 | -------------------------------------------------------------------------------- /config/postgres/docker-entrypoint-initdb.d/20-create-app-db.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | . /usr/local/bin/ergonode-common-functions.sh 6 | 7 | psql -v ON_ERROR_STOP=1 \ 8 | --dbname "$db" \ 9 | --username="$user" <<-EOSQL 10 | CREATE DATABASE ${app_db} OWNER ${app_user}; 11 | EOSQL 12 | -------------------------------------------------------------------------------- /config/postgres/docker-entrypoint-initdb.d/20-create-app-test-db.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | . /usr/local/bin/ergonode-common-functions.sh 6 | 7 | if [[ -z "${app_test_db}" ]] ; then 8 | exit 0 9 | fi 10 | 11 | psql -v ON_ERROR_STOP=1 \ 12 | --dbname "$db" \ 13 | --username="$user" <<-EOSQL 14 | CREATE DATABASE ${app_test_db} OWNER ${app_user}; 15 | EOSQL 16 | -------------------------------------------------------------------------------- /config/postgres/ergonode-common-functions.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_user="${APP_USER:-$(test -f "${APP_USER_FILE}" && cat ${APP_USER_FILE} || echo "ergonode")}" 4 | app_password="${APP_USER_PASSWORD:-$(test -f "${APP_USER_PASSWORD_FILE}" && cat ${APP_USER_PASSWORD_FILE})}" 5 | app_db="${APP_DB:-$(test -f "${APP_DB_FILE}" && cat ${APP_DB_FILE} || echo "ergonode")}" 6 | app_test_db="${APP_DB_TEST:-$(test -f "${APP_TEST_DB_FILE}" && cat ${APP_TEST_DB_FILE} || echo "")}" 7 | 8 | user="${POSTGRES_USER:-$(test -f "${POSTGRES_USER_FILE}" && cat ${POSTGRES_USER_FILE} || echo "postgres")}" 9 | db="${POSTGRES_DB:-$(test -f "${POSTGRES_DB_FILE}" && cat ${POSTGRES_DB_FILE} || echo $user)}" 10 | password="${POSTGRES_PASSWORD:-$(test -f "${POSTGRES_PASSWORD_FILE}" && cat ${POSTGRES_PASSWORD_FILE})}" 11 | 12 | host="$(hostname -i || echo '127.0.0.1')" -------------------------------------------------------------------------------- /config/postgres/postgres-healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | . /usr/local/bin/ergonode-common-functions.sh 6 | 7 | export PGPASSWORD="${password}" 8 | 9 | psql \ 10 | --host="$host" \ 11 | --username="$user" \ 12 | --dbname="$db" \ 13 | --quiet --no-align --tuples-only \ 14 | --command "SELECT 1" 15 | -------------------------------------------------------------------------------- /config/rabbitmq/docker-ergonode-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | set -e 5 | 6 | function waitUntil() { 7 | if ! "$@" ; then 8 | sleep 1 9 | waitUntil "$@" ; 10 | fi 11 | } 12 | 13 | envsubst < /etc/rabbitmq/rabbitmq.conf.template >> /etc/rabbitmq/rabbitmq.conf 14 | 15 | if [[ ! -z "${CONSUL_ACL_TOKEN}" ]] ; 16 | then 17 | echo "cluster_formation.consul.acl_token = ${CONSUL_ACL_TOKEN}" >> /etc/rabbitmq/rabbitmq.conf 18 | fi 19 | 20 | 21 | if [[ ! -z "${RABBITMQ_ERLANG_COOKIE}" ]] ; 22 | then 23 | echo "${RABBITMQ_ERLANG_COOKIE}" > "${RABBITMQ_DATA_DIR}/.erlang.cookie" 24 | fi 25 | 26 | >&2 echo "Waiting for consul..." 27 | waitUntil ping -c 1 "${CONSUL_HOST}" 28 | 29 | if [[ ! -z "${WAIT_FOR}" ]] && [[ ! -d "${RABBITMQ_DATA_DIR}/mnesia" ]]; 30 | then 31 | >&2 echo "Waiting for ${WAIT_FOR}..." 32 | waitUntil ping -c 1 "${WAIT_FOR}" 33 | fi 34 | 35 | exec docker-entrypoint.sh rabbitmq-server 36 | -------------------------------------------------------------------------------- /config/rabbitmq/rabbitmq-healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # The original code lives in https://github.com/docker-library/healthcheck/blob/master/rabbitmq/docker-healthcheck 4 | 5 | set -eo pipefail 6 | 7 | # A RabbitMQ node is considered healthy if all the below are true: 8 | # * the rabbit app finished booting & it's running 9 | # * there are no alarms 10 | # * there is at least 1 active listener 11 | 12 | rabbitmqctl eval ' 13 | { true, rabbit_app_booted_and_running } = { rabbit:is_booted(node()), rabbit_app_booted_and_running }, 14 | { [], no_alarms } = { rabbit:alarms(), no_alarms }, 15 | [] /= rabbit_networking:active_listeners(), 16 | rabbitmq_node_is_healthy. 17 | ' || exit 1 -------------------------------------------------------------------------------- /config/rabbitmq/rabbitmq.conf.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | cluster_formation.peer_discovery_backend = rabbit_peer_discovery_consul 4 | 5 | cluster_formation.consul.host = ${CONSUL_HOST} 6 | 7 | cluster_formation.consul.svc = rabbitmq 8 | cluster_formation.consul.svc_addr_auto = true 9 | cluster_formation.consul.svc_addr_use_nodename = true 10 | cluster_formation.consul.use_longname = true 11 | -------------------------------------------------------------------------------- /data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ergonode/docker/3bb868a8f624721c5a53d65b46fe6ae9106c8bad/data/.gitkeep -------------------------------------------------------------------------------- /docker-compose.deploy.yml: -------------------------------------------------------------------------------- 1 | # example docker-compose for push/build for production release 2 | # this file only require CONTAINER_REGISTRY_BASE and optional IMAGE_TAG environment variable. 3 | version: "3.7" 4 | x-cache-from: 5 | - &ergonode-cache-from 6 | cache_from: 7 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/nginx:latest 8 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/php:latest 9 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/nuxtjs:latest 10 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/docsify:latest 11 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/rabbitmq:latest 12 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/haproxy:latest 13 | services: 14 | php: 15 | build: 16 | context: "./" 17 | target: php_production 18 | <<: *ergonode-cache-from 19 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/php:${IMAGE_TAG:-latest} 20 | nuxtjs: 21 | build: 22 | context: "./" 23 | target: nuxtjs_production 24 | <<: *ergonode-cache-from 25 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/nuxtjs:${IMAGE_TAG:-latest} 26 | nginx: 27 | build: 28 | context: "./" 29 | target: nginx 30 | <<: *ergonode-cache-from 31 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/nginx:${IMAGE_TAG:-latest} 32 | postgres: 33 | build: 34 | context: "./" 35 | target: postgres 36 | <<: *ergonode-cache-from 37 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/postgres:${IMAGE_TAG:-latest} 38 | haproxy: 39 | build: 40 | context: "./" 41 | target: haproxy 42 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/haproxy:${IMAGE_TAG:-latest} 43 | rabbitmq: 44 | build: 45 | context: "./" 46 | target: rabbitmq-management 47 | <<: *ergonode-cache-from 48 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/rabbitmq:${IMAGE_TAG:-latest} -------------------------------------------------------------------------------- /docker-compose.postgres.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | x-networks: 3 | - &ergonode-networks 4 | networks: 5 | ergonode: 6 | x-deploy: 7 | - &ergonode-deploy 8 | deploy: 9 | mode: global 10 | update_config: 11 | failure_action: rollback 12 | order: start-first 13 | services: 14 | postgres: 15 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/postgres:${IMAGE_TAG:-latest} 16 | volumes: 17 | - "ergonode-postgres-data:/var/lib/postgresql/data" 18 | environment: 19 | POSTGRES_USER: ${POSTGRES_USER:-postgres} 20 | POSTGRES_PASSWORD_FILE: /run/secrets/ergonode-postgres-passwd 21 | POSTGRES_DB: ${POSTGRES_DB:-postgres} 22 | APP_USER: ${APP_USER:-ergonode} 23 | APP_USER_PASSWORD_FILE: /run/secrets/ergonode-user-passwd 24 | APP_DB: ${APP_DB:-ergonode} 25 | secrets: 26 | - ergonode-postgres-passwd 27 | - ergonode-user-passwd 28 | <<: *ergonode-networks 29 | <<: *ergonode-deploy 30 | volumes: 31 | ergonode-postgres-data: 32 | networks: 33 | ergonode: 34 | attachable: true 35 | secrets: 36 | ergonode-postgres-passwd: 37 | external: true 38 | ergonode-user-passwd: 39 | external: true 40 | -------------------------------------------------------------------------------- /docker-compose.production.yml: -------------------------------------------------------------------------------- 1 | # example docker-compose for running images in production environment 2 | # All mandatory environment variables are required 3 | version: "3.7" 4 | x-rabbitmq-environment: 5 | - &rabbitmq-environment 6 | RABBITMQ_ERLANG_COOKIE: ${RABBITMQ_ERLANG_COOKIE:?Missing mandatory value for RABBITMQ_ERLANG_COOKIE} 7 | RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER:-ergonode} 8 | RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS:?Missing mandatory value for RABBITMQ_DEFAULT_PASS} 9 | CONSUL_HOST: ${CONSUL_HOST:-consul} 10 | # CONSUL_ACL_TOKEN: CONSUL_ACL_TOKEN 11 | x-rabbitmq: 12 | - &rabbitmq 13 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/rabbitmq:${IMAGE_TAG:-latest} 14 | networks: 15 | ergonode: 16 | aliases: 17 | - rabbitmq 18 | deploy: 19 | mode: global 20 | update_config: 21 | failure_action: rollback 22 | order: stop-first 23 | depends_on: 24 | - consul 25 | x-networks: 26 | - &ergonode-networks 27 | networks: 28 | ergonode: 29 | x-deploy: 30 | - &ergonode-deploy 31 | deploy: 32 | update_config: 33 | failure_action: rollback 34 | order: start-first 35 | x-php-environment: 36 | - &php-environment 37 | APP_ENV: ${APP_ENV:-prod} 38 | APP_SECRET: ${APP_SECRET:?Missing mandatory value for APP_SECRET} 39 | DATABASE_URL: ${DATABASE_URL:?Missing mandatory value for DATABASE_URL} 40 | JWT_PRIVATE_KEY_PATH: ${JWT_PRIVATE_KEY_PATH:-config/jwt/private.pem} 41 | JWT_PUBLIC_KEY_PATH: ${JWT_PUBLIC_KEY_PATH:-config/jwt/public.pem} 42 | JWT_PASSPHRASE: ${JWT_PASSPHRASE:?Missing mandatory value for JWT_PASSPHRASE} 43 | JWT_TOKEN_TTL: ${JWT_TOKEN_TTL:-3600} 44 | CORS_ALLOW_ORIGIN: ${CORS_ALLOW_ORIGIN:?Missing mandatory value for CORS_ALLOW_ORIGIN} 45 | APP_HOST: ${APP_HOST:?Missing mandatory value for APP_HOST} 46 | APP_SCHEME: ${APP_SCHEME:-https} 47 | APP_URL: ${APP_URL:?Missing mandatory value for APP_URL} 48 | TRUSTED_HOSTS: ${TRUSTED_HOSTS:-^localhost|example\.com$} 49 | TRUSTED_PROXIES: ${TRUSTED_PROXIES} 50 | MESSENGER_TRANSPORT_EXPORT_DSN: ${MESSENGER_TRANSPORT_EXPORT_DSN:-amqp://ergonode:ergonode@rabbit:5672/%2f/export} 51 | MESSENGER_TRANSPORT_IMPORT_DSN: ${MESSENGER_TRANSPORT_IMPORT_DSN:-amqp://ergonode:ergonode@rabbit:5672/%2f/import} 52 | MESSENGER_TRANSPORT_NOTIFICATION_DSN: ${MESSENGER_TRANSPORT_NOTIFICATION_DSN:-amqp://ergonode:ergonode@rabbit:5672/%2f/notification} 53 | # each enty for CRONTAB must be delimited by ; example: 54 | # * * * * * /srv/app/bin/console channel:export:schedule >> /srv/app/var/log/crond.log ; * * * * * /srv/app/bin/console some:other:cmd >> /srv/app/var/log/crond.log 55 | CRONTAB: ${CRONTAB:-* * * * * /srv/app/bin/console channel:export:schedule >> /srv/app/var/log/crond.log} 56 | x-php-volumes: 57 | - &php-volumes 58 | volumes: 59 | - "multimedia:/srv/app/public/multimedia" 60 | - "avatar:/srv/app/public/avatar" 61 | - "import:/srv/app/import" 62 | - "export:/srv/app/export" 63 | - "jwt:/srv/app/config/jwt" 64 | x-php-messenger: 65 | - &php-messenger 66 | working_dir: /srv/app 67 | image: ${CONTAINER_REGISTRY_BASE:-ergonode}/php:${IMAGE_TAG:-latest} 68 | <<: *php-volumes 69 | environment: 70 | <<: *php-environment 71 | depends_on: 72 | - postgres 73 | - haproxy 74 | command: bin/console messenger:consume --memory-limit=256M --time-limit=3600 -vv import export segment 75 | restart: always 76 | healthcheck: 77 | disable: true 78 | deploy: 79 | replicas: 1 80 | update_config: 81 | failure_action: rollback 82 | order: start-first 83 | <<: *ergonode-networks 84 | services: 85 | php: 86 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/php:${IMAGE_TAG:-latest} 87 | environment: 88 | <<: *php-environment 89 | <<: *php-volumes 90 | <<: *ergonode-networks 91 | <<: *ergonode-deploy 92 | crond: 93 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/php:${IMAGE_TAG:-latest} 94 | environment: 95 | <<: *php-environment 96 | <<: *php-volumes 97 | <<: *ergonode-networks 98 | command: ["crond"] 99 | deploy: 100 | replicas: 1 101 | update_config: 102 | failure_action: rollback 103 | order: start-first 104 | php-messenger-import: 105 | <<: *php-messenger 106 | command: bin/console messenger:consume --memory-limit=128M --time-limit=3600 -vv import 107 | deploy: 108 | replicas: 1 109 | update_config: 110 | failure_action: rollback 111 | order: start-first 112 | php-messenger-export: 113 | <<: *php-messenger 114 | command: bin/console messenger:consume --memory-limit=128M --time-limit=3600 -vv export 115 | deploy: 116 | replicas: 1 117 | update_config: 118 | failure_action: rollback 119 | order: start-first 120 | php-messenger-segment: 121 | <<: *php-messenger 122 | command: bin/console messenger:consume --memory-limit=128M --time-limit=3600 -vv segment 123 | deploy: 124 | replicas: 1 125 | update_config: 126 | failure_action: rollback 127 | order: start-first 128 | php-messenger-completeness: 129 | <<: *php-messenger 130 | command: bin/console messenger:consume --memory-limit=128M --time-limit=3600 -vv completeness 131 | deploy: 132 | replicas: 1 133 | update_config: 134 | failure_action: rollback 135 | order: start-first 136 | php-messenger-notification: 137 | <<: *php-messenger 138 | command: bin/console messenger:consume --memory-limit=128M --time-limit=3600 -vv notification 139 | deploy: 140 | replicas: 1 141 | update_config: 142 | failure_action: rollback 143 | order: start-first 144 | php-messenger-batch_action: 145 | <<: *php-messenger 146 | command: bin/console messenger:consume --memory-limit=128M --time-limit=3600 -vv batch_action 147 | deploy: 148 | replicas: 1 149 | update_config: 150 | failure_action: rollback 151 | order: start-first 152 | nuxtjs: 153 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/nuxtjs:${IMAGE_TAG:-latest} 154 | environment: 155 | NODE_ENV: ${NODE_ENV:-production} 156 | API_BASE_URL: ${API_BASE_URL:?Missing mandatory value for API_BASE_URL} 157 | <<: *ergonode-networks 158 | <<: *ergonode-deploy 159 | nginx: 160 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/nginx:${IMAGE_TAG:-latest} 161 | environment: 162 | APP_ENV: ${APP_ENV:-prod} 163 | PHP_HOST: ${PHP_HOST:-php} 164 | NUXTJS_HOST: ${PHP_HOST:-nuxtjs} 165 | DOLLAR: "$$" 166 | volumes: 167 | - "multimedia:/srv/app/public/multimedia" 168 | - "avatar:/srv/app/public/avatar" 169 | ports: 170 | - "${EXPOSED_NGINX_PORT:-80}:80" 171 | <<: *ergonode-networks 172 | <<: *ergonode-deploy 173 | depends_on: 174 | - php 175 | - nuxtjs 176 | consul: 177 | image: consul:1.7 178 | networks: 179 | ergonode: 180 | healthcheck: 181 | test: ["CMD", "sh", "-c", "curl --fail http://localhost:8500 || exit 1"] 182 | haproxy: 183 | image: ${CONTAINER_REGISTRY_BASE:?Missing mandatory value for CONTAINER_REGISTRY_BASE}/haproxy:${IMAGE_TAG:-latest} 184 | deploy: 185 | mode: global 186 | ports: 187 | - "${EXPOSED_RABBITMQ_PORT:-15672}:15672" 188 | networks: 189 | ergonode: 190 | aliases: 191 | - rabbit 192 | rabbitmq-01: 193 | <<: *rabbitmq 194 | hostname: rabbitmq-01 195 | volumes: 196 | - rabbitmq-01:/var/lib/rabbitmq 197 | environment: 198 | <<: *rabbitmq-environment 199 | rabbitmq-02: 200 | <<: *rabbitmq 201 | hostname: rabbitmq-02 202 | volumes: 203 | - rabbitmq-02:/var/lib/rabbitmq 204 | environment: 205 | <<: *rabbitmq-environment 206 | WAIT_FOR: rabbitmq-01 207 | rabbitmq-03: 208 | <<: *rabbitmq 209 | hostname: rabbitmq-03 210 | volumes: 211 | - rabbitmq-03:/var/lib/rabbitmq 212 | environment: 213 | <<: *rabbitmq-environment 214 | WAIT_FOR: rabbitmq-02 215 | volumes: 216 | multimedia: 217 | avatar: 218 | import: 219 | export: 220 | jwt: 221 | rabbitmq-01: 222 | rabbitmq-02: 223 | rabbitmq-03: 224 | networks: 225 | ergonode: 226 | attachable: true 227 | -------------------------------------------------------------------------------- /docker-compose.test.yml: -------------------------------------------------------------------------------- 1 | #example docker-compose for running tests 2 | version: "3.7" 3 | services: 4 | php: 5 | image: ${CONTAINER_REGISTRY_BASE}/php:${IMAGE_TAG:-latest} 6 | environment: 7 | APP_ENV: prod 8 | JWT_PRIVATE_KEY_PATH: config/jwt/private.pem 9 | JWT_PUBLIC_KEY_PATH: config/jwt/public.pem 10 | JWT_PASSPHRASE: 1234 11 | APP_URL: http://localhost:8001 12 | volumes: 13 | - "./backend/var/log:/srv/app/var/log" 14 | - "./backend/composer.json:/srv/app/composer.json:ro" 15 | - "./backend/composer.lock:/srv/app/composer.lock:ro" 16 | - "./backend/symfony.lock:/srv/app/symfony.lock:ro" 17 | - "./backend/.env:/srv/app/.env:ro" 18 | - "./backend/.env.test:/srv/app/.env.test:ro" 19 | - "./backend/phpunit.xml.dist:/srv/app/phpunit.xml.dist:ro" 20 | - "./backend/phpstan.neon.dist:/srv/app/phpstan.neon.dist:ro" 21 | - "./backend/phpcs.xml.dist:/srv/app/phpcs.xml.dist:ro" 22 | - "./backend/behat.yml.dist:/srv/app/behat.yml.dist:ro" 23 | - "./backend/depfile.yml:/srv/app/depfile.yml:ro" 24 | - "./backend/.travis.yml:/srv/app/.travis.yml:ro" 25 | - "./backend/build.xml:/srv/app/build.xml:ro" 26 | - "./backend/tests:/srv/app/tests:ro" 27 | - "./backend/features:/srv/app/features:ro" 28 | postgres: 29 | image: ${CONTAINER_REGISTRY_BASE}/postgres:${IMAGE_TAG:-latest} 30 | environment: 31 | POSTGRES_USER: postgres 32 | POSTGRES_PASSWORD: 123 33 | POSTGRES_DB: postgres 34 | APP_USER: ergonode 35 | APP_USER_PASSWORD: 123 36 | APP_DB: ergonode 37 | APP_TEST_DB: ergonode_test 38 | nuxtjs: 39 | image: ${CONTAINER_REGISTRY_BASE}/nuxtjs:${IMAGE_TAG:-latest} 40 | command: exit 0 41 | 42 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | #docker-compose for development 2 | version: "3.7" 3 | x-rabbitmq-environment: 4 | - &rabbitmq-environment 5 | RABBITMQ_ERLANG_COOKIE: ${RABBITMQ_ERLANG_COOKIE:-cookie} 6 | RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER:-ergonode} 7 | RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS:-ergonode} 8 | CONSUL_HOST: ${CONSUL_HOST:-consul} 9 | # CONSUL_ACL_TOKEN: CONSUL_ACL_TOKEN 10 | x-rabbitmq: 11 | - &rabbitmq 12 | build: 13 | context: "./" 14 | target: rabbitmq-management 15 | image: ${CONTAINER_REGISTRY_BASE:-ergonode}/rabbitmq:${IMAGE_TAG:-latest} 16 | depends_on: 17 | - consul 18 | x-cache-from: 19 | - &ergonode-cache-from 20 | cache_from: 21 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/nginx:latest 22 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/php:latest 23 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/nuxtjs:latest 24 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/docsify:latest 25 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/rabbitmq:latest 26 | - ${CONTAINER_REGISTRY_BASE:-ergonode}/haproxy:latest 27 | x-php-environment: 28 | - &php-environment 29 | XDEBUG_CONFIG: ${XDEBUG_CONFIG:-remote_enable=1 remote_connect_back=1} 30 | PHP_IDE_CONFIG: ${PHP_IDE_CONFIG:-serverName=localhost} 31 | APP_URL: ${APP_URL:-http://nginx} 32 | JWT_PRIVATE_KEY_PATH: ${JWT_PRIVATE_KEY_PATH:-config/jwt/private.pem} 33 | JWT_PUBLIC_KEY_PATH: ${JWT_PUBLIC_KEY_PATH:-config/jwt/public.pem} 34 | JWT_PASSPHRASE: ${JWT_PASSPHRASE:-1234} 35 | PHP_INI_DIRECTIVES: ${PHP_INI_DIRECTIVES:-upload_max_filesize=250M; post_max_size = 250M; memory_limit=256M} 36 | MESSENGER_TRANSPORT_EXPORT_DSN: ${MESSENGER_TRANSPORT_EXPORT_DSN:-amqp://ergonode:ergonode@rabbitmq:5672/%2f/export} 37 | MESSENGER_TRANSPORT_IMPORT_DSN: ${MESSENGER_TRANSPORT_IMPORT_DSN:-amqp://ergonode:ergonode@rabbitmq:5672/%2f/import} 38 | MESSENGER_TRANSPORT_NOTIFICATION_DSN: ${MESSENGER_TRANSPORT_NOTIFICATION_DSN:-amqp://ergonode:ergonode@rabbitmq:5672/%2f/notification} 39 | # Newrelic to set newrelic settings please use PHP_INI_DIRECTIVES env var 40 | # newrelic.license = "REPLACE_WITH_REAL_KEY" ; newrelic.appname = "Some App" ; newrelic.daemon.app_connect_timeout=15s ; 41 | # more info about new relic configuration https://docs.newrelic.com/docs/agents/php-agent/configuration/php-agent-configuration 42 | NEWRELIC_ENABLE: ${NEWRELIC_ENABLE:-0} 43 | x-php-messenger: 44 | - &php-messenger 45 | working_dir: /srv/app 46 | image: ${CONTAINER_REGISTRY_BASE:-ergonode}/php:${IMAGE_TAG:-latest} 47 | volumes: 48 | - ./backend:/srv/app 49 | environment: 50 | <<: *php-environment 51 | depends_on: 52 | - consul 53 | - postgres 54 | - rabbitmq 55 | command: bin/console messenger:consume --sleep=10 --memory-limit=128M --time-limit=3600 -vv import export segment 56 | healthcheck: 57 | disable: true 58 | restart: on-failure 59 | services: 60 | postgres: 61 | build: 62 | context: "./" 63 | target: postgres 64 | <<: *ergonode-cache-from 65 | image: ${CONTAINER_REGISTRY_BASE:-ergonode}/postgres:${IMAGE_TAG:-latest} 66 | volumes: 67 | - "./data/.postgres:/var/lib/postgresql/data:delegated" 68 | environment: 69 | POSTGRES_USER: ${POSTGRES_USER:-postgres} 70 | POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-123} 71 | POSTGRES_DB: ${POSTGRES_DB:-postgres} 72 | APP_USER: ${APP_USER:-ergonode} 73 | APP_USER_PASSWORD: ${APP_USER_PASSWORD:-123} 74 | APP_DB: ${APP_DB:-ergonode} 75 | APP_TEST_DB: ${APP_TEST_DB:-ergonode_test} 76 | ports: 77 | - "${EXPOSED_POSTGRES_PORT:-5432}:5432" 78 | php: 79 | build: 80 | context: "./" 81 | target: php 82 | <<: *ergonode-cache-from 83 | working_dir: /srv/app 84 | image: ${CONTAINER_REGISTRY_BASE:-ergonode}/php:${IMAGE_TAG:-latest} 85 | volumes: 86 | - ./backend:/srv/app:delegated 87 | environment: 88 | <<: *php-environment 89 | depends_on: 90 | - postgres 91 | - mailhog 92 | crond: 93 | build: 94 | context: "./" 95 | target: php 96 | <<: *ergonode-cache-from 97 | working_dir: /srv/app 98 | image: ${CONTAINER_REGISTRY_BASE:-ergonode}/php:${IMAGE_TAG:-latest} 99 | volumes: 100 | - ./backend:/srv/app:delegated 101 | environment: 102 | <<: *php-environment 103 | command: ["crond"] 104 | rabbitmq: 105 | <<: *rabbitmq 106 | hostname: rabbitmq 107 | environment: 108 | <<: *rabbitmq-environment 109 | ports: 110 | - "${EXPOSED_RABBITMQ_PORT:-5672}:5672" 111 | - "${EXPOSED_RABBITMQ_WEB_PORT:-15672}:15672" 112 | healthcheck: 113 | test: ["CMD", "rabbitmq-diagnostics", "-q", "status"] 114 | interval: 30s 115 | timeout: 10s 116 | retries: 5 117 | php-messenger-import: 118 | <<: *php-messenger 119 | command: bin/console messenger:consume --sleep=${IMPORT_WORKER_SLEEP:-1} --memory-limit=${IMPORT_WORKER_MEMORY_LIMIT:-128M} --time-limit=${WORKER_TIME_LIMIT:-3600} -vv import 120 | php-messenger-export: 121 | <<: *php-messenger 122 | command: bin/console messenger:consume --sleep=${EXPORT_WORKER_SLEEP:-1} --memory-limit=${EXPORT_WORKER_MEMORY_LIMIT:-128M} --time-limit=${WORKER_TIME_LIMIT:-3600} -vv export 123 | php-messenger-segment: 124 | <<: *php-messenger 125 | command: bin/console messenger:consume --sleep=${WORKER_SLEEP:-1} --memory-limit=${WORKER_MEMORY_LIMIT:-128M} --time-limit=${WORKER_TIME_LIMIT:-3600} -vv segment 126 | php-messenger-completeness: 127 | <<: *php-messenger 128 | command: bin/console messenger:consume --sleep=${WORKER_SLEEP:-1} --memory-limit=${WORKER_MEMORY_LIMIT:-128M} --time-limit=${WORKER_TIME_LIMIT:-3600} -vv completeness 129 | php-messenger-notification: 130 | <<: *php-messenger 131 | command: bin/console messenger:consume --sleep=${WORKER_SLEEP:-1} --memory-limit=${WORKER_MEMORY_LIMIT:-128M} --time-limit=${WORKER_TIME_LIMIT:-3600} -vv notification 132 | php-messenger-batch_action: 133 | <<: *php-messenger 134 | command: bin/console messenger:consume --sleep=${WORKER_SLEEP:-1} --memory-limit=${WORKER_MEMORY_LIMIT:-128M} --time-limit=${WORKER_TIME_LIMIT:-3600} -vv batch_action 135 | nginx: 136 | build: 137 | context: ./ 138 | target: nginx 139 | <<: *ergonode-cache-from 140 | image: ${CONTAINER_REGISTRY_BASE:-ergonode}/nginx:${IMAGE_TAG:-latest} 141 | volumes: 142 | - ./backend:/srv/app 143 | working_dir: /srv/app 144 | environment: 145 | PHP_HOST: ${PHP_HOST:-php} 146 | NUXTJS_HOST: ${PHP_HOST:-nuxtjs} 147 | NGINX_HTTP_DIRECTIVES: ${NGINX_HTTP_DIRECTIVES:-client_max_body_size 250m;} 148 | ports: 149 | - "${EXPOSED_NGINX_PORT:-8000}:80" 150 | depends_on: 151 | - php 152 | nuxtjs: 153 | build: 154 | context: "./" 155 | target: nuxtjs 156 | <<: *ergonode-cache-from 157 | image: ${CONTAINER_REGISTRY_BASE:-ergonode}/nuxtjs:${IMAGE_TAG:-latest} 158 | working_dir: /srv/app 159 | volumes: 160 | - "./frontend:/srv/app" 161 | ports: 162 | - "${EXPOSED_NODE_PORT:-80}:80" 163 | environment: 164 | EXPOSED_NODE_PORT: ${EXPOSED_NODE_PORT:-80} 165 | API_BASE_URL: ${API_BASE_URL:-http://localhost:8000/api/v1/} 166 | docsify: 167 | build: 168 | context: "./" 169 | target: docsify 170 | <<: *ergonode-cache-from 171 | image: ${CONTAINER_REGISTRY_BASE:-ergonode}/docs:${IMAGE_TAG:-latest} 172 | working_dir: /srv/app 173 | volumes: 174 | - "./docs:/srv/app" 175 | ports: 176 | - "${EXPOSED_DOCS_PORT:-8002}:3000" 177 | mailhog: 178 | image: mailhog/mailhog 179 | ports: 180 | - "${EXPOSED_MAILHOG_SMTP_PORT:-1025}:1025" 181 | - "${EXPOSED_MAILHOG_WEB_PORT:-8025}:8025" 182 | consul: 183 | image: consul:1.7 184 | healthcheck: 185 | test: ["CMD", "sh", "-c", "curl --fail http://localhost:8500 || exit 1"] 186 | networks: 187 | default: 188 | --------------------------------------------------------------------------------