├── .gitignore ├── README.md ├── bin ├── _resources │ └── app_task.json ├── build └── deploy ├── composer.json ├── composer.lock ├── docker-compose.yml ├── docker ├── nginx │ ├── Dockerfile │ └── etc │ │ └── nginx │ │ └── nginx.conf └── phpfpm │ └── Dockerfile ├── infrastructure ├── example │ └── example.tf ├── modules │ └── app │ │ ├── alb.tf │ │ ├── autoscaling.tf │ │ ├── ecr.tf │ │ ├── iam.tf │ │ ├── logs.tf │ │ ├── outputs.tf │ │ ├── securitygroups.tf │ │ ├── vars.tf │ │ └── vpc.tf └── prod │ └── main.tf └── web └── index.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/* 2 | /build/* 3 | .terraform 4 | *.tfstate* 5 | *.swp 6 | *.dmg 7 | *.gz 8 | *.iso 9 | *.jar 10 | *.rar 11 | *.tar 12 | *.zip 13 | *.7z 14 | *.com 15 | *.class 16 | *.dll 17 | *.exe 18 | *.app 19 | *.o 20 | *.so 21 | .DS_Store* 22 | ehthumbs.db 23 | Icon? 24 | Thumbs.db 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS Container Service & PHP Example 2 | 3 | For a talk I give that's a basic intro to ECS, Terraform, and Docker. This 4 | particular flavor uses PHP as an example. 5 | 6 | ## Directory Structure 7 | 8 | - `web`: The web root directory 9 | - `docker`: Dockerfiles and configuration 10 | - `infra`: Terraform (and Ansible in a real project) modules, roles, 11 | and configuration. 12 | -------------------------------------------------------------------------------- /bin/_resources/app_task.json: -------------------------------------------------------------------------------- 1 | { 2 | "family": "ecsterraformphp-{ENV}", 3 | "networkMode": "bridge", 4 | "taskRoleArn": "{ROLE_ARN}", 5 | "containerDefinitions": [ 6 | { 7 | "name": "fpm", 8 | "image": "{FPM_REPO}:{VERSION}", 9 | "cpu": 128, 10 | "memory": 128, 11 | "essential": true, 12 | "hostname": "fpm", 13 | "logConfiguration": { 14 | "logDriver": "awslogs", 15 | "options": { 16 | "awslogs-group": "{LOG_GROUP}", 17 | "awslogs-region": "us-east-1", 18 | "awslogs-stream-prefix": "ecsterraformphp" 19 | } 20 | } 21 | }, 22 | { 23 | "name": "nginx", 24 | "image": "{NGINX_REPO}:{VERSION}", 25 | "cpu": 64, 26 | "memory": 64, 27 | "portMappings": [ 28 | { 29 | "containerPort": 80 30 | } 31 | ], 32 | "essential": true, 33 | "hostname": "nginx", 34 | "logConfiguration": { 35 | "logDriver": "awslogs", 36 | "options": { 37 | "awslogs-group": "{LOG_GROUP}", 38 | "awslogs-region": "us-east-1", 39 | "awslogs-stream-prefix": "ecsterraformphp" 40 | } 41 | }, 42 | "links": ["fpm:phpfpm"] 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /bin/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | root="$(git rev-parse --show-toplevel)" 6 | 7 | pushd "$root" 8 | 9 | rm -rf build 10 | mkdir build 11 | cp composer.* build/ 12 | cp -R web build/ 13 | cp docker/phpfpm/Dockerfile build/phpfpm.dock 14 | cp docker/nginx/Dockerfile build/nginx.dock 15 | cp -R docker/nginx/etc build/ 16 | pushd "$root/build" 17 | composer install --no-dev --classmap-authoritative 18 | popd 19 | 20 | docker build -t ecs-terraform-php-fpm -f build/phpfpm.dock build/ 21 | docker build -t ecs-terraform-php-nginx -f build/nginx.dock build/ 22 | 23 | popd 24 | -------------------------------------------------------------------------------- /bin/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ "$#" != 2 ]; then 6 | echo "Usage: $0 {environment} {version}" >&2 7 | exit 1 8 | fi 9 | 10 | env="$1" 11 | version="$2" 12 | root="$(git rev-parse --show-toplevel)" 13 | 14 | # build 15 | . "$root/bin/build" 16 | 17 | pushd "$root" 18 | 19 | pushd "infrastructure/$env" 20 | fpm="$(terraform output docker_repo_fpm)" 21 | nginx="$(terraform output docker_repo_nginx)" 22 | role="$(terraform output task_role)" 23 | logs="$(terraform output log_group)" 24 | popd 25 | 26 | docker tag ecs-terraform-php-fpm "$fpm:$version" 27 | docker tag ecs-terraform-php-nginx "$nginx:$version" 28 | eval "$(aws ecr get-login)" 29 | docker push "$fpm:$version" 30 | docker push "$nginx:$version" 31 | 32 | def="$(sed "s/{ENV}/$env/g; \ 33 | s/{VERSION}/$version/g; \ 34 | s~{ROLE_ARN}~$role~g; \ 35 | s~{FPM_REPO}~$fpm~g; \ 36 | s~{NGINX_REPO}~$nginx~g; \ 37 | s~{LOG_GROUP}~$logs~g" \ 38 | "bin/_resources/app_task.json" 39 | )" 40 | 41 | aws --region us-east-1 \ 42 | ecs \ 43 | register-task-definition \ 44 | --cli-input-json "$def" 45 | 46 | popd 47 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chrisguitarguy/ecs-terraform-example", 3 | "description": "A small example app for docker & terraform", 4 | "keywords": [], 5 | "license": "MIT", 6 | "require": { 7 | "silex/silex": "~2.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "25ba6b4d710e5fea107a8a862c07a203", 8 | "packages": [ 9 | { 10 | "name": "pimple/pimple", 11 | "version": "v3.0.2", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/silexphp/Pimple.git", 15 | "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a", 20 | "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.0" 25 | }, 26 | "type": "library", 27 | "extra": { 28 | "branch-alias": { 29 | "dev-master": "3.0.x-dev" 30 | } 31 | }, 32 | "autoload": { 33 | "psr-0": { 34 | "Pimple": "src/" 35 | } 36 | }, 37 | "notification-url": "https://packagist.org/downloads/", 38 | "license": [ 39 | "MIT" 40 | ], 41 | "authors": [ 42 | { 43 | "name": "Fabien Potencier", 44 | "email": "fabien@symfony.com" 45 | } 46 | ], 47 | "description": "Pimple, a simple Dependency Injection Container", 48 | "homepage": "http://pimple.sensiolabs.org", 49 | "keywords": [ 50 | "container", 51 | "dependency injection" 52 | ], 53 | "time": "2015-09-11T15:10:35+00:00" 54 | }, 55 | { 56 | "name": "psr/log", 57 | "version": "1.0.2", 58 | "source": { 59 | "type": "git", 60 | "url": "https://github.com/php-fig/log.git", 61 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 62 | }, 63 | "dist": { 64 | "type": "zip", 65 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 66 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 67 | "shasum": "" 68 | }, 69 | "require": { 70 | "php": ">=5.3.0" 71 | }, 72 | "type": "library", 73 | "extra": { 74 | "branch-alias": { 75 | "dev-master": "1.0.x-dev" 76 | } 77 | }, 78 | "autoload": { 79 | "psr-4": { 80 | "Psr\\Log\\": "Psr/Log/" 81 | } 82 | }, 83 | "notification-url": "https://packagist.org/downloads/", 84 | "license": [ 85 | "MIT" 86 | ], 87 | "authors": [ 88 | { 89 | "name": "PHP-FIG", 90 | "homepage": "http://www.php-fig.org/" 91 | } 92 | ], 93 | "description": "Common interface for logging libraries", 94 | "homepage": "https://github.com/php-fig/log", 95 | "keywords": [ 96 | "log", 97 | "psr", 98 | "psr-3" 99 | ], 100 | "time": "2016-10-10T12:19:37+00:00" 101 | }, 102 | { 103 | "name": "silex/silex", 104 | "version": "v2.0.4", 105 | "source": { 106 | "type": "git", 107 | "url": "https://github.com/silexphp/Silex.git", 108 | "reference": "49ca08d853731d1635374e5019c8696cfd53c161" 109 | }, 110 | "dist": { 111 | "type": "zip", 112 | "url": "https://api.github.com/repos/silexphp/Silex/zipball/49ca08d853731d1635374e5019c8696cfd53c161", 113 | "reference": "49ca08d853731d1635374e5019c8696cfd53c161", 114 | "shasum": "" 115 | }, 116 | "require": { 117 | "php": ">=5.5.9", 118 | "pimple/pimple": "~3.0", 119 | "symfony/event-dispatcher": "~2.8|^3.0", 120 | "symfony/http-foundation": "~2.8|^3.0", 121 | "symfony/http-kernel": "~2.8|^3.0", 122 | "symfony/routing": "~2.8|^3.0" 123 | }, 124 | "replace": { 125 | "silex/api": "self.version", 126 | "silex/providers": "self.version" 127 | }, 128 | "require-dev": { 129 | "doctrine/dbal": "~2.2", 130 | "monolog/monolog": "^1.4.1", 131 | "swiftmailer/swiftmailer": "~5", 132 | "symfony/asset": "~2.8|^3.0", 133 | "symfony/browser-kit": "~2.8|^3.0", 134 | "symfony/config": "~2.8|^3.0", 135 | "symfony/css-selector": "~2.8|^3.0", 136 | "symfony/debug": "~2.8|^3.0", 137 | "symfony/doctrine-bridge": "~2.8|^3.0", 138 | "symfony/dom-crawler": "~2.8|^3.0", 139 | "symfony/expression-language": "~2.8|^3.0", 140 | "symfony/finder": "~2.8|^3.0", 141 | "symfony/form": "~2.8|^3.0", 142 | "symfony/intl": "~2.8|^3.0", 143 | "symfony/monolog-bridge": "~2.8|^3.0", 144 | "symfony/options-resolver": "~2.8|^3.0", 145 | "symfony/phpunit-bridge": "~2.8|^3.0", 146 | "symfony/process": "~2.8|^3.0", 147 | "symfony/security": "~2.8|^3.0", 148 | "symfony/serializer": "~2.8|^3.0", 149 | "symfony/translation": "~2.8|^3.0", 150 | "symfony/twig-bridge": "~2.8|^3.0", 151 | "symfony/validator": "~2.8|^3.0", 152 | "symfony/var-dumper": "~2.8|^3.0", 153 | "twig/twig": "~1.27|~2.0" 154 | }, 155 | "type": "library", 156 | "extra": { 157 | "branch-alias": { 158 | "dev-master": "2.0.x-dev" 159 | } 160 | }, 161 | "autoload": { 162 | "psr-4": { 163 | "Silex\\": "src/Silex" 164 | } 165 | }, 166 | "notification-url": "https://packagist.org/downloads/", 167 | "license": [ 168 | "MIT" 169 | ], 170 | "authors": [ 171 | { 172 | "name": "Fabien Potencier", 173 | "email": "fabien@symfony.com" 174 | }, 175 | { 176 | "name": "Igor Wiedler", 177 | "email": "igor@wiedler.ch" 178 | } 179 | ], 180 | "description": "The PHP micro-framework based on the Symfony Components", 181 | "homepage": "http://silex.sensiolabs.org", 182 | "keywords": [ 183 | "microframework" 184 | ], 185 | "time": "2016-11-06T18:09:06+00:00" 186 | }, 187 | { 188 | "name": "symfony/debug", 189 | "version": "v3.2.7", 190 | "source": { 191 | "type": "git", 192 | "url": "https://github.com/symfony/debug.git", 193 | "reference": "56f613406446a4a0a031475cfd0a01751de22659" 194 | }, 195 | "dist": { 196 | "type": "zip", 197 | "url": "https://api.github.com/repos/symfony/debug/zipball/56f613406446a4a0a031475cfd0a01751de22659", 198 | "reference": "56f613406446a4a0a031475cfd0a01751de22659", 199 | "shasum": "" 200 | }, 201 | "require": { 202 | "php": ">=5.5.9", 203 | "psr/log": "~1.0" 204 | }, 205 | "conflict": { 206 | "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" 207 | }, 208 | "require-dev": { 209 | "symfony/class-loader": "~2.8|~3.0", 210 | "symfony/http-kernel": "~2.8|~3.0" 211 | }, 212 | "type": "library", 213 | "extra": { 214 | "branch-alias": { 215 | "dev-master": "3.2-dev" 216 | } 217 | }, 218 | "autoload": { 219 | "psr-4": { 220 | "Symfony\\Component\\Debug\\": "" 221 | }, 222 | "exclude-from-classmap": [ 223 | "/Tests/" 224 | ] 225 | }, 226 | "notification-url": "https://packagist.org/downloads/", 227 | "license": [ 228 | "MIT" 229 | ], 230 | "authors": [ 231 | { 232 | "name": "Fabien Potencier", 233 | "email": "fabien@symfony.com" 234 | }, 235 | { 236 | "name": "Symfony Community", 237 | "homepage": "https://symfony.com/contributors" 238 | } 239 | ], 240 | "description": "Symfony Debug Component", 241 | "homepage": "https://symfony.com", 242 | "time": "2017-03-28T21:38:24+00:00" 243 | }, 244 | { 245 | "name": "symfony/event-dispatcher", 246 | "version": "v3.2.7", 247 | "source": { 248 | "type": "git", 249 | "url": "https://github.com/symfony/event-dispatcher.git", 250 | "reference": "154bb1ef7b0e42ccc792bd53edbce18ed73440ca" 251 | }, 252 | "dist": { 253 | "type": "zip", 254 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/154bb1ef7b0e42ccc792bd53edbce18ed73440ca", 255 | "reference": "154bb1ef7b0e42ccc792bd53edbce18ed73440ca", 256 | "shasum": "" 257 | }, 258 | "require": { 259 | "php": ">=5.5.9" 260 | }, 261 | "require-dev": { 262 | "psr/log": "~1.0", 263 | "symfony/config": "~2.8|~3.0", 264 | "symfony/dependency-injection": "~2.8|~3.0", 265 | "symfony/expression-language": "~2.8|~3.0", 266 | "symfony/stopwatch": "~2.8|~3.0" 267 | }, 268 | "suggest": { 269 | "symfony/dependency-injection": "", 270 | "symfony/http-kernel": "" 271 | }, 272 | "type": "library", 273 | "extra": { 274 | "branch-alias": { 275 | "dev-master": "3.2-dev" 276 | } 277 | }, 278 | "autoload": { 279 | "psr-4": { 280 | "Symfony\\Component\\EventDispatcher\\": "" 281 | }, 282 | "exclude-from-classmap": [ 283 | "/Tests/" 284 | ] 285 | }, 286 | "notification-url": "https://packagist.org/downloads/", 287 | "license": [ 288 | "MIT" 289 | ], 290 | "authors": [ 291 | { 292 | "name": "Fabien Potencier", 293 | "email": "fabien@symfony.com" 294 | }, 295 | { 296 | "name": "Symfony Community", 297 | "homepage": "https://symfony.com/contributors" 298 | } 299 | ], 300 | "description": "Symfony EventDispatcher Component", 301 | "homepage": "https://symfony.com", 302 | "time": "2017-04-04T07:26:27+00:00" 303 | }, 304 | { 305 | "name": "symfony/http-foundation", 306 | "version": "v3.2.7", 307 | "source": { 308 | "type": "git", 309 | "url": "https://github.com/symfony/http-foundation.git", 310 | "reference": "cb0b6418f588952c9290b3df4ca650f1b7ab570a" 311 | }, 312 | "dist": { 313 | "type": "zip", 314 | "url": "https://api.github.com/repos/symfony/http-foundation/zipball/cb0b6418f588952c9290b3df4ca650f1b7ab570a", 315 | "reference": "cb0b6418f588952c9290b3df4ca650f1b7ab570a", 316 | "shasum": "" 317 | }, 318 | "require": { 319 | "php": ">=5.5.9", 320 | "symfony/polyfill-mbstring": "~1.1" 321 | }, 322 | "require-dev": { 323 | "symfony/expression-language": "~2.8|~3.0" 324 | }, 325 | "type": "library", 326 | "extra": { 327 | "branch-alias": { 328 | "dev-master": "3.2-dev" 329 | } 330 | }, 331 | "autoload": { 332 | "psr-4": { 333 | "Symfony\\Component\\HttpFoundation\\": "" 334 | }, 335 | "exclude-from-classmap": [ 336 | "/Tests/" 337 | ] 338 | }, 339 | "notification-url": "https://packagist.org/downloads/", 340 | "license": [ 341 | "MIT" 342 | ], 343 | "authors": [ 344 | { 345 | "name": "Fabien Potencier", 346 | "email": "fabien@symfony.com" 347 | }, 348 | { 349 | "name": "Symfony Community", 350 | "homepage": "https://symfony.com/contributors" 351 | } 352 | ], 353 | "description": "Symfony HttpFoundation Component", 354 | "homepage": "https://symfony.com", 355 | "time": "2017-04-04T15:30:56+00:00" 356 | }, 357 | { 358 | "name": "symfony/http-kernel", 359 | "version": "v3.2.7", 360 | "source": { 361 | "type": "git", 362 | "url": "https://github.com/symfony/http-kernel.git", 363 | "reference": "8285ab5faf1306b1a5ebcf287fe91c231a6de88e" 364 | }, 365 | "dist": { 366 | "type": "zip", 367 | "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8285ab5faf1306b1a5ebcf287fe91c231a6de88e", 368 | "reference": "8285ab5faf1306b1a5ebcf287fe91c231a6de88e", 369 | "shasum": "" 370 | }, 371 | "require": { 372 | "php": ">=5.5.9", 373 | "psr/log": "~1.0", 374 | "symfony/debug": "~2.8|~3.0", 375 | "symfony/event-dispatcher": "~2.8|~3.0", 376 | "symfony/http-foundation": "~2.8.13|~3.1.6|~3.2" 377 | }, 378 | "conflict": { 379 | "symfony/config": "<2.8" 380 | }, 381 | "require-dev": { 382 | "symfony/browser-kit": "~2.8|~3.0", 383 | "symfony/class-loader": "~2.8|~3.0", 384 | "symfony/config": "~2.8|~3.0", 385 | "symfony/console": "~2.8|~3.0", 386 | "symfony/css-selector": "~2.8|~3.0", 387 | "symfony/dependency-injection": "~2.8|~3.0", 388 | "symfony/dom-crawler": "~2.8|~3.0", 389 | "symfony/expression-language": "~2.8|~3.0", 390 | "symfony/finder": "~2.8|~3.0", 391 | "symfony/process": "~2.8|~3.0", 392 | "symfony/routing": "~2.8|~3.0", 393 | "symfony/stopwatch": "~2.8|~3.0", 394 | "symfony/templating": "~2.8|~3.0", 395 | "symfony/translation": "~2.8|~3.0", 396 | "symfony/var-dumper": "~3.2" 397 | }, 398 | "suggest": { 399 | "symfony/browser-kit": "", 400 | "symfony/class-loader": "", 401 | "symfony/config": "", 402 | "symfony/console": "", 403 | "symfony/dependency-injection": "", 404 | "symfony/finder": "", 405 | "symfony/var-dumper": "" 406 | }, 407 | "type": "library", 408 | "extra": { 409 | "branch-alias": { 410 | "dev-master": "3.2-dev" 411 | } 412 | }, 413 | "autoload": { 414 | "psr-4": { 415 | "Symfony\\Component\\HttpKernel\\": "" 416 | }, 417 | "exclude-from-classmap": [ 418 | "/Tests/" 419 | ] 420 | }, 421 | "notification-url": "https://packagist.org/downloads/", 422 | "license": [ 423 | "MIT" 424 | ], 425 | "authors": [ 426 | { 427 | "name": "Fabien Potencier", 428 | "email": "fabien@symfony.com" 429 | }, 430 | { 431 | "name": "Symfony Community", 432 | "homepage": "https://symfony.com/contributors" 433 | } 434 | ], 435 | "description": "Symfony HttpKernel Component", 436 | "homepage": "https://symfony.com", 437 | "time": "2017-04-05T12:52:03+00:00" 438 | }, 439 | { 440 | "name": "symfony/polyfill-mbstring", 441 | "version": "v1.3.0", 442 | "source": { 443 | "type": "git", 444 | "url": "https://github.com/symfony/polyfill-mbstring.git", 445 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" 446 | }, 447 | "dist": { 448 | "type": "zip", 449 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", 450 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", 451 | "shasum": "" 452 | }, 453 | "require": { 454 | "php": ">=5.3.3" 455 | }, 456 | "suggest": { 457 | "ext-mbstring": "For best performance" 458 | }, 459 | "type": "library", 460 | "extra": { 461 | "branch-alias": { 462 | "dev-master": "1.3-dev" 463 | } 464 | }, 465 | "autoload": { 466 | "psr-4": { 467 | "Symfony\\Polyfill\\Mbstring\\": "" 468 | }, 469 | "files": [ 470 | "bootstrap.php" 471 | ] 472 | }, 473 | "notification-url": "https://packagist.org/downloads/", 474 | "license": [ 475 | "MIT" 476 | ], 477 | "authors": [ 478 | { 479 | "name": "Nicolas Grekas", 480 | "email": "p@tchwork.com" 481 | }, 482 | { 483 | "name": "Symfony Community", 484 | "homepage": "https://symfony.com/contributors" 485 | } 486 | ], 487 | "description": "Symfony polyfill for the Mbstring extension", 488 | "homepage": "https://symfony.com", 489 | "keywords": [ 490 | "compatibility", 491 | "mbstring", 492 | "polyfill", 493 | "portable", 494 | "shim" 495 | ], 496 | "time": "2016-11-14T01:06:16+00:00" 497 | }, 498 | { 499 | "name": "symfony/routing", 500 | "version": "v3.2.7", 501 | "source": { 502 | "type": "git", 503 | "url": "https://github.com/symfony/routing.git", 504 | "reference": "d6605f9a5767bc5bc4895e1c762ba93964608aee" 505 | }, 506 | "dist": { 507 | "type": "zip", 508 | "url": "https://api.github.com/repos/symfony/routing/zipball/d6605f9a5767bc5bc4895e1c762ba93964608aee", 509 | "reference": "d6605f9a5767bc5bc4895e1c762ba93964608aee", 510 | "shasum": "" 511 | }, 512 | "require": { 513 | "php": ">=5.5.9" 514 | }, 515 | "conflict": { 516 | "symfony/config": "<2.8" 517 | }, 518 | "require-dev": { 519 | "doctrine/annotations": "~1.0", 520 | "doctrine/common": "~2.2", 521 | "psr/log": "~1.0", 522 | "symfony/config": "~2.8|~3.0", 523 | "symfony/expression-language": "~2.8|~3.0", 524 | "symfony/http-foundation": "~2.8|~3.0", 525 | "symfony/yaml": "~2.8|~3.0" 526 | }, 527 | "suggest": { 528 | "doctrine/annotations": "For using the annotation loader", 529 | "symfony/config": "For using the all-in-one router or any loader", 530 | "symfony/dependency-injection": "For loading routes from a service", 531 | "symfony/expression-language": "For using expression matching", 532 | "symfony/http-foundation": "For using a Symfony Request object", 533 | "symfony/yaml": "For using the YAML loader" 534 | }, 535 | "type": "library", 536 | "extra": { 537 | "branch-alias": { 538 | "dev-master": "3.2-dev" 539 | } 540 | }, 541 | "autoload": { 542 | "psr-4": { 543 | "Symfony\\Component\\Routing\\": "" 544 | }, 545 | "exclude-from-classmap": [ 546 | "/Tests/" 547 | ] 548 | }, 549 | "notification-url": "https://packagist.org/downloads/", 550 | "license": [ 551 | "MIT" 552 | ], 553 | "authors": [ 554 | { 555 | "name": "Fabien Potencier", 556 | "email": "fabien@symfony.com" 557 | }, 558 | { 559 | "name": "Symfony Community", 560 | "homepage": "https://symfony.com/contributors" 561 | } 562 | ], 563 | "description": "Symfony Routing Component", 564 | "homepage": "https://symfony.com", 565 | "keywords": [ 566 | "router", 567 | "routing", 568 | "uri", 569 | "url" 570 | ], 571 | "time": "2017-03-02T15:58:09+00:00" 572 | } 573 | ], 574 | "packages-dev": [], 575 | "aliases": [], 576 | "minimum-stability": "stable", 577 | "stability-flags": [], 578 | "prefer-stable": false, 579 | "prefer-lowest": false, 580 | "platform": [], 581 | "platform-dev": [] 582 | } 583 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | phpfpm: 5 | image: php:7.1-fpm-alpine 6 | volumes: 7 | - .:/app 8 | nginx: 9 | image: nginx:1.11-alpine 10 | volumes: 11 | - ./docker/nginx/etc/nginx/nginx.conf:/etc/nginx/nginx.conf 12 | - ./web:/app/web 13 | ports: 14 | - "9090:80" 15 | -------------------------------------------------------------------------------- /docker/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:1.11-alpine 2 | 3 | COPY etc/nginx/nginx.conf /etc/nginx/nginx.conf 4 | COPY web /app/web 5 | -------------------------------------------------------------------------------- /docker/nginx/etc/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes 1; 3 | 4 | error_log /var/log/nginx/error.log warn; 5 | pid /var/run/nginx.pid; 6 | 7 | 8 | events { 9 | worker_connections 1024; 10 | } 11 | 12 | 13 | http { 14 | include /etc/nginx/mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 18 | '$status $body_bytes_sent "$http_referer" ' 19 | '"$http_user_agent" "$http_x_forwarded_for"'; 20 | 21 | access_log /var/log/nginx/access.log main; 22 | 23 | sendfile on; 24 | 25 | keepalive_timeout 65; 26 | 27 | # Assumes you have a hostname that's resolvable as `phpfpm` listening 28 | # on port 9000 29 | upstream phpfpm { 30 | server phpfpm:9000; 31 | } 32 | 33 | server { 34 | listen 80 default_server; 35 | server_name _; 36 | 37 | # mimic the directory structure of our PHP FPM container 38 | root /app/web; 39 | index index.php index.html; 40 | try_files $uri $uri/ /index.php?$args; 41 | 42 | # this is so our container load balancer, can ping this for a health check 43 | location = /health { 44 | return 200 'OK'; 45 | add_header Content-Type text/plain; 46 | } 47 | 48 | location ~ ^(?