Skip to content
Draft
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
9 changes: 4 additions & 5 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Build and Push Docker Image
name: Build and Push Container Image

on:
"on":
workflow_call:
inputs:
registry:
Expand Down Expand Up @@ -47,7 +47,6 @@ jobs:
images: ${{ inputs.registry }}/${{ github.repository }}-${{ inputs.image_name }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Build and push Docker image
Expand All @@ -71,11 +70,11 @@ jobs:
package-name: messages-${{ inputs.image_name }}
package-type: 'container'
min-versions-to-keep: 0
delete-only-untagged-versions: 'true'
delete-only-untagged-versions: true
- name: Container images retention
uses: actions/delete-package-versions@v5
with:
package-name: messages-${{ inputs.image_name }}
package-type: 'container'
min-versions-to-keep: 30
ignore-versions: '^latest|main|(\\d+\\.\\d+(\\.\\d+)?)$'
ignore-versions: 'latest|main|(\\d+\\.\\d+(\\.\\d+)?)'
72 changes: 72 additions & 0 deletions .github/workflows/messages-ghcr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Build and publish OCI images

"on":
push:
branches:
- main

jobs:

docker-publish-mta-in:
uses: ./.github/workflows/docker-publish.yml
permissions:
contents: read
packages: write
attestations: write
id-token: write
secrets: inherit
with:
image_name: "mta-in"
context: "src/mta-in"
target: runtime-prod

docker-publish-mta-out:
uses: ./.github/workflows/docker-publish.yml
permissions:
contents: read
packages: write
attestations: write
id-token: write
secrets: inherit
with:
image_name: "mta-out"
context: "src/mta-out"
target: runtime-prod

docker-publish-socks-proxy:
uses: ./.github/workflows/docker-publish.yml
permissions:
contents: read
packages: write
attestations: write
id-token: write
secrets: inherit
with:
image_name: "socks-proxy"
context: "src/socks-proxy"

docker-publish-frontend:
uses: ./.github/workflows/docker-publish.yml
permissions:
contents: read
packages: write
attestations: write
id-token: write
secrets: inherit
with:
image_name: "frontend"
context: "src/frontend"
target: runtime-prod

docker-publish-backend:
uses: ./.github/workflows/docker-publish.yml
permissions:
contents: read
packages: write
attestations: write
id-token: write
secrets: inherit
with:
image_name: "backend"
context: "src/backend"
target: runtime-prod
40 changes: 1 addition & 39 deletions .github/workflows/messages.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Lint and tests

on:
"on":
push:
branches:
- main
Expand Down Expand Up @@ -110,41 +110,3 @@ jobs:
run: |
git diff --quiet || \
(echo "API changes detected. Please run 'make api-update' then commit the changes." && exit 1)

docker-publish-mta-in:
uses: ./.github/workflows/docker-publish.yml
permissions:
contents: read
packages: write
attestations: write
id-token: write
secrets: inherit
with:
image_name: "mta-in"
context: "src/mta-in"
target: runtime-prod

docker-publish-mta-out:
uses: ./.github/workflows/docker-publish.yml
permissions:
contents: read
packages: write
attestations: write
id-token: write
secrets: inherit
with:
image_name: "mta-out"
context: "src/mta-out"
target: runtime-prod

docker-publish-socks-proxy:
uses: ./.github/workflows/docker-publish.yml
permissions:
contents: read
packages: write
attestations: write
id-token: write
secrets: inherit
with:
image_name: "socks-proxy"
context: "src/socks-proxy"
37 changes: 0 additions & 37 deletions bin/scalingo_pgdump.sh

This file was deleted.

8 changes: 7 additions & 1 deletion bin/scalingo_postfrontend
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ mkdir -p build/
mv src/frontend/out build/frontend-out

mv src/backend/* ./
mv src/nginx/* ./

# Replace ${DJANGO_ADMIN_URL} to the erb equivalent with the "admin" default value
# Replace every other shell variable to its erb equivalent
sed \
-e 's/\${DJANGO_ADMIN_URL}/<%= ENV["DJANGO_ADMIN_URL"] || "admin" %>/g' \
-e 's/\${\([A-Z_][A-Z0-9_]*\)}/<%= ENV["\1"] %>/g' \
src/frontend/nginx/nginx.conf.template > ./servers.conf.erb

echo "3.13" > .python-version
7 changes: 0 additions & 7 deletions cron.json

This file was deleted.

48 changes: 29 additions & 19 deletions src/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@
FROM python:3.13.7-slim-trixie AS base

# Bump this to force an update of the apt repositories
ENV MIN_UPDATE_DATE="2025-09-02"
ENV MIN_UPDATE_DATE="2025-12-01"

RUN apt-get update && apt-get upgrade -y \
&& rm -rf /var/lib/apt/lists/*
RUN <<EOR
apt-get update
DEBIAN_FRONTEND="noninteractive" apt-get upgrade -y
rm -rf /var/lib/apt/lists/*
EOR

ENV PYTHONUNBUFFERED=1
ENV PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1

WORKDIR /app

# ---- Poetry package manager and dev system deps ----
FROM base AS poetry

RUN apt-get update && apt-get install -y --no-install-recommends \
RUN <<EOR
apt-get update
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
curl \
rdfind \
&& rm -rf /var/lib/apt/lists/*
libmagic1
rm -rf /var/lib/apt/lists/*
EOR

ENV POETRY_NO_INTERACTION=1
ENV POETRY_VIRTUALENVS_CREATE=0
Expand Down Expand Up @@ -55,13 +62,11 @@ COPY . /app/
WORKDIR /app

# collectstatic
RUN DJANGO_CONFIGURATION=Build \
python manage.py collectstatic --noinput

# Replace duplicated file by a symlink to decrease the overall size of the
# final image
RUN rdfind -makesymlinks true -followsymlinks true -makeresultsfile false ${MESSAGES_STATIC_ROOT}

RUN <<EOR
DJANGO_CONFIGURATION=Build python manage.py collectstatic --noinput
# Replace duplicated file by a symlink to decrease the overall size of the final image
rdfind -makesymlinks true -followsymlinks true -makeresultsfile false ${MESSAGES_STATIC_ROOT}
EOR

# ---- Base runtime image ----
FROM base AS runtime-base
Expand All @@ -72,10 +77,13 @@ FROM base AS runtime-base
RUN chmod g=u /etc/passwd

# Install required packages
RUN apt-get update && apt-get install -y --no-install-recommends \
gettext \
libmagic1 \
&& rm -rf /var/lib/apt/lists/*
RUN <<EOR
apt-get update
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
gettext \
libmagic1
rm -rf /var/lib/apt/lists/*
EOR

# Un-privileged user running the application
ARG DOCKER_USER
Expand Down Expand Up @@ -110,12 +118,14 @@ CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

# ---- Base runtime image for production ----
FROM runtime-base AS runtime-prod
ARG MESSAGES_STATIC_ROOT=/data/static

COPY --from=base-with-deps /venv /venv

COPY --from=link-collector ${MESSAGES_STATIC_ROOT} ${MESSAGES_STATIC_ROOT}

COPY . /app/

# The default command runs gunicorn WSGI server in messages's main module
CMD ["gunicorn", "-c", "/app/gunicorn.conf.py", "messages.wsgi:application"]

HEALTHCHECK --interval=30s --timeout=2s --start-period=30s \
CMD ["python", "-c", "import os; from urllib.request import Request, urlopen; urlopen(Request('http://localhost:8000/healthz/', headers={'Host': f'{os.getenv('DJANGO_ALLOWED_HOSTS', 'localhost').split(',')[0].strip()}', 'X-Forwarded-Proto': 'https'}), timeout=2)"]
16 changes: 14 additions & 2 deletions src/frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM node:22-slim AS frontend-deps
ENV npm_config_cache=/tmp/npm-cache
RUN npm install -g [email protected] && npm cache clean -f

ARG DOCKER_USER
ARG DOCKER_USER=1000
WORKDIR /home/frontend/

RUN chown -R ${DOCKER_USER} /tmp/npm-cache
Expand All @@ -14,7 +14,6 @@ USER ${DOCKER_USER}
COPY --chown=${DOCKER_USER} package*.json ./
RUN npm install


FROM frontend-deps AS frontend-build

WORKDIR /home/frontend/
Expand All @@ -24,3 +23,16 @@ ARG API_ORIGIN
ENV NEXT_PUBLIC_API_ORIGIN=${API_ORIGIN}

RUN npm run build

FROM docker.io/nginxinc/nginx-unprivileged:1-alpine AS runtime-prod

COPY --from=frontend-build /home/frontend/out /app
COPY nginx/nginx.conf.template /etc/nginx/templates/default.conf.template

ENV PORT=8080
ENV MESSAGES_FRONTEND_ROOT=/app
ENV MESSAGES_FRONTEND_BACKEND_SERVER=localhost:8000
ENV DJANGO_ADMIN_URL=admin

HEALTHCHECK --interval=60s --timeout=3s --start-interval=10s \
CMD curl -fsS http://localhost:${PORT}/health
Loading