Skip to content

Commit

Permalink
Merge branch 'main' into wagtailcharts-test
Browse files Browse the repository at this point in the history
  • Loading branch information
anselmbradford authored Dec 18, 2024
2 parents ce9f110 + 846bd92 commit 1c1c1c0
Show file tree
Hide file tree
Showing 236 changed files with 3,591 additions and 2,170 deletions.
2 changes: 0 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
.github/
.tox/
cfgov/agreements/static/agreements/js/chosen.jquery.js
cfgov/agreements/static/agreements/js/jquery-3.5.1.min.js
cfgov/alerts/tests/json/
cfgov/data_research/data/
cfgov/retirement_api/data/
Expand Down
257 changes: 119 additions & 138 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,192 +1,173 @@
FROM python:3.8-alpine as base
FROM python:3.8-alpine as python

# Hard labels
LABEL maintainer="[email protected]"

# Create a non-root user
ARG USERNAME=cfgov
ARG USER_UID=1000
RUN addgroup --gid ${USER_UID} ${USERNAME} && \
adduser \
--uid ${USER_UID} \
--ingroup ${USERNAME} \
--disabled-password \
${USERNAME}

# Ensure that the environment uses UTF-8 encoding by default
ENV LANG en_US.UTF-8
ENV ENV /etc/profile
ENV PIP_NO_CACHE_DIR true
# Stops Python default buffering to stdout, improving logging to the console.
ENV PYTHONUNBUFFERED 1
ENV APP_HOME /src/consumerfinance.gov

WORKDIR ${APP_HOME}

# Install and update common OS packages, pip, setuptools, wheel, and awscli
RUN apk update --no-cache && apk upgrade --no-cache
RUN pip install --upgrade pip setuptools wheel awscli

# Add `$HOME/.local/bin` to PATH
RUN echo 'export PATH=$HOME/.local/bin:$PATH' >> /etc/profile

#######################################################################
# Intermediate layer to build only prod deps
FROM base as cfgov-python-builder
# Disable pip cache dir
ENV PIP_NO_CACHE_DIR 1

# .build-deps are required to build and test the application (pip, tox,
# matplotlib, numpy, etc.)
# TODO: When we update from the python:3.8 image, see which of these we can
# remove because binary packages might be available to us again.
RUN apk add --no-cache --virtual .build-deps gcc gettext git libffi-dev musl-dev postgresql-dev musl-dev linux-headers g++ make freetype
# Allow pip install as root.
ENV PIP_ROOT_USER_ACTION ignore

# Install python requirements
COPY requirements requirements
RUN mkdir /build && pip install --prefix=/build -r requirements/deployment.txt
# Stops Python default buffering to stdout, improving logging to the console
ENV PYTHONUNBUFFERED 1

#######################################################################
# cfgov-dev is used for local development, as well as a base for frontend.
FROM cfgov-python-builder AS cfgov-dev
# Set the APP_HOME, our working directory
ENV APP_HOME /src/consumerfinance.gov

ENV CFGOV_PATH ${APP_HOME}
ENV CFGOV_CURRENT ${APP_HOME}
# Add our top-level Python path to the PYTHONPATH
ENV PYTHONPATH ${APP_HOME}/cfgov

# Django Settings
ENV DJANGO_SETTINGS_MODULE cfgov.settings.local
ENV ALLOWED_HOSTS '["*"]'

# .backend-deps and .frontend-deps are required to run the application
RUN apk add --no-cache --virtual .backend-deps bash curl postgresql

# Install python requirements
COPY requirements requirements
RUN cp -Rfp /build/* /usr/local && rm -Rf /build && pip install -r requirements/local.txt
# Set the working directory
WORKDIR ${APP_HOME}

# Copy the application requirements, needed to build the Python environment
# below
# Note: by specifying specific files we enable this layer to be cached if
# these files do not change.
COPY requirements ./requirements

# Build the Python environment
RUN \
apk update --no-cache && apk upgrade --no-cache && \
apk add --no-cache --virtual .build-deps \
gcc \
gettext \
git \
libffi-dev \
musl-dev \
postgresql-dev \
&& \
apk add --no-cache --virtual .backend-deps \
bash \
curl \
postgresql \
&& \
pip install --upgrade pip setuptools wheel && \
pip install -r requirements/deployment_container.txt && \
apk del .build-deps

# The application will run on port 8000
EXPOSE 8000

ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["python", "./cfgov/manage.py", "runserver", "0.0.0.0:8000"]

#######################################################################
# Build frontend assets using a Node base image
FROM node:20-alpine as cfgov-node-builder
FROM node:20-alpine as node-builder

ENV APP_HOME /src/consumerfinance.gov
WORKDIR ${APP_HOME}

# Install and update common OS packages and frontend dependencies
RUN apk update --no-cache && \
apk upgrade --no-cache && \
apk add --no-cache --virtual .frontend-deps jpeg-dev yarn zlib-dev
RUN apk update --no-cache && apk upgrade --no-cache && \
apk add --no-cache --virtual .frontend-deps \
jpeg-dev \
yarn \
zlib-dev

# Target a production frontend build
ARG FRONTEND_TARGET=production

# See .dockerignore for details on which files are included
COPY . .
# Copy the files needed for building the frontend
# Note: by specifying specific files we enable this layer to be cached if
# these files do not change.
COPY frontend.sh .
COPY package.json .
COPY yarn.lock .
COPY cfgov/unprocessed ./cfgov/unprocessed
COPY config ./config/
COPY esbuild ./esbuild/
COPY scripts ./scripts/
COPY npm-packages-offline-cache ./npm-packages-offline-cache/

# Build the front-end
RUN ./frontend.sh ${FRONTEND_TARGET} && \
yarn cache clean && \
rm -rf node_modules npm-packages-offline-cache cfgov/unprocessed
rm -rf \
frontend.sh \
package.json \
yarn.lock \
cfgov/unprocessed \
config \
esbuild \
scripts \
npm-packages-offline-cache \
node_modules

#######################################################################
# Intermediate layer to collect the frontend for the production-like image
FROM cfgov-python-builder as cfgov-frontend-builder

ENV STATIC_PATH ${APP_HOME}/cfgov/static/
ENV PYTHONPATH ${APP_HOME}/cfgov
# Dev runs with Django runserver with cfgov.settings.local
FROM python AS dev

# Django Settings
ENV DJANGO_SETTINGS_MODULE cfgov.settings.production
ENV DJANGO_STATIC_ROOT ${STATIC_PATH}
ENV DJANGO_SETTINGS_MODULE cfgov.settings.local
ENV ALLOWED_HOSTS '["*"]'

# Install Python dependencie
RUN cp -Rfp /build/* /usr/local && rm -Rf /build

# See .dockerignore for details on which files are included
COPY --from=cfgov-node-builder ${APP_HOME} ${APP_HOME}
# Install dev/local Python requirements
RUN pip install -r requirements/local.txt

# Run Django's collectstatic to collect assets from the frontend build.
#
# Our Django settings file requires a SECRET_KEY, but we don't want to
# bake our key into the Docker image. We need to provide one in order to
# be able to run collectstatic, even though the key value isn't actually
# used in any way during staticfiles collection. We provide a random
# secret key here for this step only.
RUN SECRET_KEY=only-for-collectstatic cfgov/manage.py collectstatic
# Copy the necessary files and directories into the dev container
# Note: by specifying specific files we enable this layer to be cached if
# these files do not change.
COPY cfgov ./cfgov/
COPY static.in ./static.in/
COPY docker-entrypoint.sh ./docker-entrypoint.sh
COPY --from=node-builder ${APP_HOME} ${APP_HOME}

#######################################################################
# Build mod_wsgi against target Python version
FROM base as cfgov-mod-wsgi
WORKDIR /tmp
RUN apk add --no-cache --virtual .build-deps apache2-dev gcc make musl-dev
RUN wget https://github.com/GrahamDumpleton/mod_wsgi/archive/refs/tags/4.9.0.tar.gz -O mod_wsgi.tar.gz
RUN echo -n "0a6f380af854b85a3151e54a3c33b520c4a6e21a99bcad7ae5ddfbfe31a74b50 mod_wsgi.tar.gz" | sha256sum -c
RUN tar xvf mod_wsgi.tar.gz
RUN cd mod_wsgi* && ./configure && make install
RUN ls /usr/lib/apache2/mod_wsgi.so # Ensure it compiled and is where expected
RUN apk del .build-deps
RUN rm -Rf /tmp/mod_wsgi*
# Run our initial data entrypoint script
ENTRYPOINT ["./docker-entrypoint.sh"]

#######################################################################
# Production-like Apache-based image
FROM base as cfgov-prod
# Give our user ownership over the app directory
RUN chown -R ${USERNAME}:${USERNAME} ${APP_HOME}

ENV HTTPD_ROOT /etc/apache2
# Run the application with the user we created
USER $USERNAME

# Apache HTTPD settings
ENV APACHE_SERVER_ROOT ${APP_HOME}/cfgov/apache
ENV APACHE_PROCESS_COUNT 4
ENV ACCESS_LOG /dev/stdout
ENV ERROR_LOG /dev/stderr
ENV STATIC_PATH ${APP_HOME}/cfgov/static/
ENV LIMIT_REQUEST_BODY 0
# Run Django's runserver
CMD python ./cfgov/manage.py runserver 0.0.0.0:8000

# mod_wsgi settings
ENV CFGOV_PATH ${APP_HOME}
ENV CFGOV_CURRENT ${APP_HOME}
ENV PYTHONPATH ${APP_HOME}/cfgov
#######################################################################
# Production runs with Django via Gunicorn with cfgov.settings.production
FROM python AS prod

# Django Settings
ENV DJANGO_SETTINGS_MODULE cfgov.settings.production
ENV STATIC_PATH ${APP_HOME}/cfgov/static/
ENV DJANGO_STATIC_ROOT ${STATIC_PATH}
ENV ALLOWED_HOSTS '["*"]'

# Install Apache server and curl (container healthcheck),
# and converts all Docker Secrets into environment variables.
RUN apk add --no-cache apache2 curl && \
echo '[ -d /var/run/secrets ] && for s in $(find /var/run/secrets -type f -name "*" -maxdepth 1) ; do export $s=$(cat $s); done && cd -' > /etc/profile.d/secrets_env.sh

# Link mime.types for RHEL Compatability in apache config.
# TODO: Remove this link once RHEL is replaced
RUN ln -s /etc/apache2/mime.types /etc/mime.types
# Copy the application code over
COPY cfgov ./cfgov/
COPY static.in ./static.in/

# Copy mod_wsgi.so from mod_wsgi image
COPY --from=cfgov-mod-wsgi /usr/lib/apache2/mod_wsgi.so /usr/lib/apache2/mod_wsgi.so
# Copy our static build over from node-builder
COPY --from=node-builder ${APP_HOME} ${APP_HOME}

# Copy installed production requirements from the cfgov-python-builder layer
COPY --from=cfgov-python-builder /build /usr/local

# Setup .local dir for apache user and set permissions on code and .local
RUN mkdir -p /var/www/.local && chown -R apache:apache ${APP_HOME} /var/www/.local

# Copy the cfgov directory form the build image
COPY --from=cfgov-frontend-builder --chown=apache:apache ${CFGOV_PATH}/cfgov ${CFGOV_PATH}/cfgov
COPY --from=cfgov-frontend-builder --chown=apache:apache ${CFGOV_PATH}/docker-entrypoint.sh ${CFGOV_PATH}/refresh-data.sh ${CFGOV_PATH}/initial-data.sh ${CFGOV_PATH}/dump-data.sh ${CFGOV_PATH}/
COPY --from=cfgov-frontend-builder --chown=apache:apache ${CFGOV_PATH}/static.in ${CFGOV_PATH}/static.in

RUN ln -s /usr/lib/apache2 cfgov/apache/modules
RUN chown -R apache:apache /usr/share/apache2 /var/run/apache2 /var/log/apache2

# Cleanup *.key files
RUN for i in $(find /usr/local/lib/python3* -type f -name "*.key*"); do rm "$i"; done
RUN for i in $(find /var/www/.local/lib/python3* -type f -name "*.key*"); do rm "$i"; done

# .backend-deps are required to run the application
RUN apk add --no-cache --virtual .backend-deps bash postgresql-client

# Swap to apache user
USER apache
# Run Django's collectstatic to collect assets from the frontend build.
#
# Our Django settings file requires a SECRET_KEY, but we don't want to
# bake our key into the Docker image. We need to provide one in order to
# be able to run collectstatic, even though the key value isn't actually
# used in any way during staticfiles collection. We provide a random
# secret key here for this step only.
RUN SECRET_KEY=only-for-collectstatic cfgov/manage.py collectstatic --noinput

# Create additional structure
# cfgov/f/ - Wagtail file uploads
RUN mkdir -p cfgov/f
# Give our user ownership over the app directory
RUN chown -R ${USERNAME}:${USERNAME} ${APP_HOME}

# Healthcheck retry set high since database loads take a while
HEALTHCHECK --start-period=300s --interval=30s --retries=30 \
CMD curl -sf -A docker-healthcheck -o /dev/null http://localhost:8000/ht/
# Run the application with the user we created
USER $USERNAME

CMD ["httpd", "-d", "/src/consumerfinance.gov/cfgov/apache", "-f", "/src/consumerfinance.gov/cfgov/apache/conf/httpd.conf", "-D", "FOREGROUND"]
# Run Gunicorn
CMD gunicorn cfgov.wsgi:application -b :8000
17 changes: 17 additions & 0 deletions cfgov/agreements/jinja2/agreements/_json.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{# ==========================================================================

Includes issuers as a global JS object

issuers: List of credit card agreement issuers.

========================================================================== #}
<script>
window.cfpbIssuers = [
{%- for issuer in issuers -%}
{
value:"{{issuer.slug}}",
label:"{{issuer.name}}"
}{{ "," if not loop.last else "" }}
{%- endfor -%}
]
</script>
15 changes: 0 additions & 15 deletions cfgov/agreements/jinja2/agreements/_select.html

This file was deleted.

18 changes: 2 additions & 16 deletions cfgov/agreements/jinja2/agreements/base_agreements.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
{% extends "v1/layouts/layout-2-1.html" %}

{% block css %}
{{ super() }}
<link rel="stylesheet" href="{{ static( 'agreements/css/chosen.css' ) }}" />
{% endblock %}

{% block javascript scoped %}
{{ super() }}
<script src="{{ static( 'agreements/js/jquery-3.5.1.min.js' ) }}"></script>
<script src="{{ static( 'agreements/js/chosen.jquery.js' ) }}"></script>
<script>
$(document).ready(function () {
$("#issuer_select").chosen();
$("#issuer_select").chosen().change( function(e){
window.location = '/credit-cards/agreements/issuer/' + jQuery(this).val() + '/';
});
});
</script>
{{ super() }}
<script src="{{ static( 'apps/agreements/Agreements.js' ) }}"></script>
{% endblock %}
Loading

0 comments on commit 1c1c1c0

Please sign in to comment.