Skip to content

Commit

Permalink
ci: Build image for production in pipeline (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
olemathias authored Sep 12, 2024
1 parent b8b052f commit e21e62f
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 28 deletions.
49 changes: 49 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: build-image
on:
push:
branches:
- 'main'

jobs:
ci:
uses: ./.github/workflows/ci.yaml
build-image:
name: build image
runs-on: ubuntu-latest
needs: [ci] # require tests to pass before build runs
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to the Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build backend image for amd64
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64
build-args: |
APP_ENV=production
push: true
tags: |
ghcr.io/${{ github.repository }}/wagtail-backend:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build nginx image for amd64
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64
build-args: |
APP_ENV=nginx-production
push: true
tags: |
ghcr.io/${{ github.repository }}/nginx-static:latest
cache-from: type=gha
cache-to: type=gha,mode=max
16 changes: 10 additions & 6 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@ name: ci

on:
push:
branches:
- '*'
- '!main'
workflow_call:

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Run pre-commit tests
uses: pre-commit/[email protected].0
uses: pre-commit/[email protected].1
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Dependencies
Expand All @@ -30,14 +34,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set .env from .env.example
run: mv .env.example .env
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build image for amd64 and arm64
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
47 changes: 27 additions & 20 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Defining environment
ARG APP_ENV=dev

# Use an official Python runtime based on Debian 12 "bookworm" as a parent image.
# Supported python3 versions: https://docs.wagtail.org/en/stable/releases/upgrading.html#compatible-django-python-versions
FROM python:3.12-slim-bookworm
FROM python:3.12-slim-bookworm AS base

# Add user that will be used in the container.
RUN useradd wagtail

# Port used by this container to serve HTTP.
EXPOSE 8000

# Set environment variables.
# 1. Force Python stdout and stderr streams to be unbuffered.
# 2. Set PORT variable that is used by Gunicorn. This should match "EXPOSE"
# command.
# Set default environment variables.
ENV PYTHONUNBUFFERED=1 \
PORT=8000

Expand All @@ -22,10 +22,11 @@ RUN apt-get update --yes --quiet && apt-get install --yes --quiet --no-install-r
libjpeg62-turbo-dev \
zlib1g-dev \
libwebp-dev \
netcat-openbsd \
&& rm -rf /var/lib/apt/lists/*

# Install the application server.
RUN pip install "gunicorn==20.0.4"
RUN pip install "gunicorn==23.0.0"

# Install the project requirements.
COPY requirements.txt /
Expand All @@ -34,9 +35,7 @@ RUN pip install -r /requirements.txt
# Use /app folder as a directory where the source code is stored.
WORKDIR /app

# Set this directory to be owned by the "wagtail" user. This Wagtail project
# uses SQLite, the folder needs to be owned by the user that
# will be writing to the database file.
# Set this directory to be owned by the "wagtail" user.
RUN chown wagtail:wagtail /app

# Copy the source code of the project into the container.
Expand All @@ -45,16 +44,24 @@ COPY --chown=wagtail:wagtail . .
# Use user "wagtail" to run the build commands below and the server itself.
USER wagtail

# Collect static files.
# Building the Production image
FROM base AS production-image
RUN echo "Building production image"
ENV DJANGO_SETTINGS_MODULE=tgno.settings.production
RUN python manage.py collectstatic --noinput --clear
ENTRYPOINT ["/app/entrypoint.prod.sh"]
CMD ["gunicorn", "tgno.wsgi:application"]

# Building the nginx production image
FROM nginx:1.27-alpine AS nginx-production-image
RUN echo "Building nginx-production image"
COPY --from=production-image /app/static /usr/share/nginx/html/static

# Building the Dev image
FROM base AS dev-image
RUN echo "Building dev image"
ENV DJANGO_SETTINGS_MODULE=tgno.settings.dev
RUN python manage.py collectstatic --noinput --clear
CMD ["python", "manage.py", "0.0.0.0:8000"]

# Runtime command that executes when "docker run" is called, it does the
# following:
# 1. Migrate the database.
# 2. Start the application server.
# WARNING:
# Migrating database at the same time as starting the server IS NOT THE BEST
# PRACTICE. The database should be migrated manually or using the release
# phase facilities of your hosting platform. This is used only so the
# Wagtail instance can be started with a simple "docker run" command.
CMD set -xe; python manage.py migrate --noinput; gunicorn tgno.wsgi:application
FROM ${APP_ENV}-image
9 changes: 9 additions & 0 deletions entrypoint.prod.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh

while ! nc -z $POSTGRES_HOST $POSTGRES_PORT; do
sleep 0.5
echo "Waiting for PostgreSQL ($POSTGRES_HOST:$POSTGRES_PORT)"
done

python manage.py migrate --no-input
exec "$@"
4 changes: 2 additions & 2 deletions tgno/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,6 @@

# Base URL to use when referring to full URLs within the Wagtail admin backend -
# e.g. in notification emails. Don't include '/admin' or a trailing slash
WAGTAILADMIN_BASE_URL = "http://example.com"
WAGTAILADMIN_BASE_URL = env("WAGTAILADMIN_BASE_URL", "http://example.com")

WAGTAILAPI_BASE_URL = "http://example.com"
WAGTAILAPI_BASE_URL = env("WAGTAILAPI_BASE_URL", "http://example.com")
2 changes: 2 additions & 0 deletions tgno/settings/dev.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from os import getenv as env

from .base import *

# SECURITY WARNING: don't run with debug turned on in production!
Expand Down
22 changes: 22 additions & 0 deletions tgno/settings/production.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
from os import getenv as env

from .base import *

DEBUG = False
SECRET_KEY = env("SECRET_KEY")
ALLOWED_HOSTS = env("ALLOWED_HOSTS", "localhost").split(",")
CSRF_TRUSTED_ORIGINS = env("CSRF_TRUSTED_ORIGINS", "http://localhost").split(",")
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"

LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {
"class": "logging.StreamHandler",
},
},
"loggers": {
"django": {
"handlers": ["console"],
"level": env("DJANGO_LOG_LEVEL", "INFO"),
},
},
}

try:
from .local import *
Expand Down

0 comments on commit e21e62f

Please sign in to comment.