Skip to content

Commit

Permalink
Merge pull request #1707 from Crown-Commercial-Service/GMBP-231-add-n…
Browse files Browse the repository at this point in the history
…ative-build

Add build for native AWS container image support
  • Loading branch information
cmurton-bg committed Nov 8, 2023
2 parents d191a6e + 59e55c5 commit c985da3
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@ bootstrap:
-@[ -z "$$TERM" ] || tput setaf 2 # green
@>&2 echo dmdevtools has been installed globally, run developer tasks with '`invoke`'
-@[ -z "$$TERM" ] || tput setaf 9 # default

.PHONY: build
build:
docker build -t digitalmarketplace-aws-supplier-frontend-http --build-arg DM_APP_NAME=supplier-frontend -f docker-aws/Dockerfile.http .
docker build -t digitalmarketplace-aws-supplier-frontend-wsgi -f docker-aws/Dockerfile.wsgi .
7 changes: 7 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import re

from flask import Flask, request, redirect, session
Expand Down Expand Up @@ -40,15 +41,21 @@ def create_app(config_name):
from .main import main as main_blueprint
from .status import status as status_blueprint
from dmutils.external import external as external_blueprint
from .healthcheck import healthcheck as healthcheck_blueprint

application.register_blueprint(metrics_blueprint, url_prefix='/suppliers')
application.register_blueprint(main_blueprint, url_prefix='/suppliers')
application.register_blueprint(status_blueprint, url_prefix='/suppliers')
application.register_blueprint(healthcheck_blueprint, url_prefix='/healthcheck')

# Must be registered last so that any routes declared in the app are registered first (i.e. take precedence over
# the external NotImplemented routes in the dm-utils external blueprint).
application.register_blueprint(external_blueprint)

# In native AWS we need to stipulate the absolute login URL as per:
# https://flask-login.readthedocs.io/en/latest/#flask_login.LoginManager.login_view
if login_view := os.getenv("DM_LOGIN_URL"):
login_manager.login_view = login_view
login_manager.login_message = None # don't flash message to user
main_blueprint.config = application.config.copy()

Expand Down
11 changes: 11 additions & 0 deletions app/healthcheck/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Add an unauthenticated /healthcheck route for ECS Task & ALB Target
# Group health checks. Simply indicates that the app is "up".
from flask import Blueprint, jsonify

healthcheck = Blueprint('healthcheck', __name__, url_prefix='/healthcheck')


@healthcheck.route('/')
@healthcheck.route('')
def healthcheck_root():
return jsonify(status='ok'), 200
13 changes: 13 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,18 @@ class Development(Config):
DM_DNB_API_PASSWORD = 'not_a_real_password' # pragma: allowlist secret


class NativeAWS(Config):
DEBUG = False
DM_APP_NAME = 'supplier-frontend'
DM_HTTP_PROTO = 'https'
# DM_LOGIN_URL will be read from env vars - used to avoid incorrect host/port
# redirect from Flask-Login package
DM_LOGIN_URL = None
# SESSION_COOKIE_DOMAIN will be read from env vars - set to subdomain to
# allow session share between "www.' and "admin."
SESSION_COOKIE_DOMAIN = None


class Live(Config):
"""Base config for deployed environments"""
DEBUG = False
Expand Down Expand Up @@ -196,6 +208,7 @@ class Production(Live):

configs = {
'development': Development,
'native-aws': NativeAWS,
'preview': Preview,
'staging': Staging,
'production': Production,
Expand Down
5 changes: 5 additions & 0 deletions docker-aws/Dockerfile.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Base builds are defined in https://github.com/Crown-Commercial-Service/ccs-digitalmarketplace-aws-docker-base
FROM digitalmarketplace/dmp-http-buildstatic:1.0.0 as buildstatic

FROM digitalmarketplace/dmp-http-frontend:1.0.0
COPY --from=buildstatic ${APP_DIR}/app/static ${APP_DIR}/static
8 changes: 8 additions & 0 deletions docker-aws/Dockerfile.wsgi
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Base builds are defined in https://github.com/Crown-Commercial-Service/ccs-digitalmarketplace-aws-docker-base
FROM digitalmarketplace/dmp-http-buildstatic:1.0.0 as buildstatic

FROM digitalmarketplace/dmp-wsgi:1.0.0
COPY --from=buildstatic ${APP_DIR}/node_modules/digitalmarketplace-govuk-frontend ${APP_DIR}/node_modules/digitalmarketplace-govuk-frontend
COPY --from=buildstatic ${APP_DIR}/node_modules/govuk-frontend ${APP_DIR}/node_modules/govuk-frontend
COPY --from=buildstatic ${APP_DIR}/app/content ${APP_DIR}/app/content
COPY --from=buildstatic ${APP_DIR}/app/static ${APP_DIR}/app/static
13 changes: 13 additions & 0 deletions docker-aws/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# docker-aws

Changes to the Docker build process for the 2023 AWS native migration.

## Explanation

The DMP1.5 (and 1.0) task architecture is as follows: a Supervisord task which runs Nginx, uWSGI and awslogs. Some points about this:

We do not require an awslogs router task anymore, rather just to write the logs to stdout / stderr and let Docker and the ECS-included awslogs driver route these naturally to CloudWatch Logs

Supervisord is a poor task manager for an ECS task because it maintains the perception of a healthy container even when a sub-process (e.g. uWSGI) has died (zombie tasks are pretty common in this case)

We must therefore arrive at an alternative architecture for the ECS Tasks and a change of Docker build process to support this. Please see ticket and code changes for [GMBP-195](https://crowncommercialservice.atlassian.net/browse/GMBP-195) for a more detailed explanation.

0 comments on commit c985da3

Please sign in to comment.