Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add build for native AWS container image support #1707

Merged
merged 3 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.