#docker #nginx #ecs #efs #page-speed
Idea
We had two options for our blogging
- Subscribe to ghost.org plan
- Host our own on aws
As we want to host our blog on a subdirectory https://finflux.co/blog, the first option was costly for us and hence we opted for the second option.
Our main website https://finflux.co is written in php + html5 + css and served using Nginx. So we finalised on following stack to cohost website and ghost using docker containers
- Nginx (pagespeed/nginx-pagespeed:latest)
- php-fpm (bitnami/php-fpm:latest)
- ghost (ghost:3-alpine)
- mysql as ghost backend
- Pagespeed – for faster web experience
To run locally
We modified Nginx server config to go to ghost blog On local, we want two things to happen. On http://localhost website should serve and on http://localhost/blog, the ghost blog should trigger. We did changes to docker-compose and .
docker-compose.yml
version: '2'networks: app-tier: driver: bridge services: phpfpm: image: 'bitnami/php-fpm:latest' networks: - app-tier volumes: - web-content:/app nginx: image: 'pagespeed/nginx-pagespeed:latest' depends_on: - phpfpm - ghost networks: - app-tier ports: - '80:8080' volumes: - ./server.conf:/etc/nginx/conf.d/yourapp.conf - ./website/:/app ghost: image: ghost:3-alpine restart: always networks: - app-tier ports: - 8082:2368 environment: # see https://docs.ghost.org/docs/config#section-running-ghost-with-config-env-variables database__client: mysql database__connection__host: host.docker.internal database__connection__user: root database__connection__password: xxxxxx database__connection__database: ghost url: http://localhost/blog volumes: web-content:
nginx server.conf
server { listen 0.0.0.0:8080; root /app; error_page 404 /notfound.html; location / { # try_files $uri $uri/index.php; index index.php; } location ~ \.php$ { root /app; fastcgi_pass phpfpm:9000; fastcgi_index index.php; # include the fastcgi_param setting include fastcgi.conf; } pagespeed on; pagespeed FileCachePath /var/cache/ngx_pagespeed; # Ensure requests for pagespeed optimized resources go to the pagespeed handler # and no extraneous headers get set. location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { add_header "" ""; } location ~ "^/pagespeed_static/" { } location ~ "^/ngx_pagespeed_beacon$" { }}
To run on Production
On production, we did following additional steps
- ECS to run docker containers
- ECR image of Finflux website
- Used SSM to store database password
- AWS logs for logging
- AWS efs(Elastic File Storage) – Ghost persistent storage
- SES as ghost email service
Dockerfile
FROM pagespeed/nginx-pagespeed:latestLABEL maintainer="dev@finflux.co"COPY ./website/ /appCOPY ./server.conf /etc/nginx/conf.d/yourapp.confEXPOSE 8080CMD ["nginx", "-g", "daemon off;"]
docker-compose.yml
version: '3'services: phpfpm: image: 'bitnami/php-fpm:latest' volumes: - web-content:/app logging: driver: awslogs options: awslogs-group: logging-group awslogs-region: ap-south-1 awslogs-stream-prefix: website-phpfpm nginx: image: 'xyz.dkr.ecr.ap-south-1.amazonaws.com/finflux-website:${IMG_TAG}' links: - phpfpm - ghost depends_on: - phpfpm - ghost ports: - '80:8080' volumes: - web-content:/app logging: driver: awslogs options: awslogs-group: logging-group awslogs-region: ap-south-1 awslogs-stream-prefix: website-nginx ghost: image: ghost:3-alpine ports: - 8080:2368 volumes: - ghost-efs:/var/lib/ghost/content environment: # see https://docs.ghost.org/docs/config#section-running-ghost-with-config-env-variables TZ: "${TIME_ZONE}" database__client: mysql database__connection__host: ${DB_HOST} database__connection__user: ${DB_USER} database__connection__database: ${DB_NAME} mail__transport: SMTP mail__options__port: 587 mail__options__host: ${SMTP_HOST} mail__options__auth__user: ${SMTP_USER} mail__options__auth__pass: ${SMTP_PASS} mail__from: ${SMTP_EMAIL} url: ${GHOST_URL} logging: driver: awslogs options: awslogs-group: logging-group awslogs-region: ap-south-1 awslogs-stream-prefix: website-ghost volumes: web-content: ghost-efs:
ecs-params.yml
version: 1task_definition: task_role_arn: "arn:aws:iam::xyz:role/ECS-TASK-EXECUTION-ROLE" task_execution_role: "arn:aws:iam::xyz:role/ECS-TASK-EXECUTION-ROLE" services: ghost: mem_reservation: 1024MB secrets: - value_from: "arn:aws:ssm:ap-south-1:xyz:parameter/website.dbpassword" name: "database__connection__password" nginx: mem_reservation: 512MB phpfpm: mem_reservation: 256MB efs_volumes: - name: ghost-efs filesystem_id: <efs-volumeId> root_directory: /website