Skip to content

CI In a Box

TL;DR

Bundle all the steps you normally is run as part of a standard docker build .

Content

Example Django Project: origami.zip

The following is an adaptation of the sort of Dockerfile I would use for a Python application. It take the idea of multi-stage Docker images a step further by adding stages that are never actually used by the final stage - but are present purely to run the various QA tools that a CI server would normally perform.

You can --target individual stages to run the various CI steps. Take a look at the Makefile in the example project for how this is done.

# The BASE images
FROM python:3.8.5 as dev_base
ENV PYTHONUNBUFFERED=1
RUN pip install -U pip  && \
    pip install poetry && \
    poetry config virtualenvs.in-project true
RUN mkdir /app
WORKDIR /app
COPY poetry.lock pyproject.toml /app/
RUN poetry install
COPY . /app
RUN poetry install

# ------------ #
# LINTING STEP #
# ------------ #
FROM dev_base as linting
RUN poetry run flake8 .

# ------------------- #
# SECURITY CHECK STEP #
# ------------------- #
FROM dev_base as security
RUN poetry export -f requirements.txt | poetry run safety check \
    --full-report \
    --stdin

# -------------------- #
# TYPING CHECKING STEP #
# -------------------- #
FROM dev_base as typing
RUN poetry run mypy src

# --------------- #
# TEST SUITE STEP #
# --------------- #
FROM dev_base as testing
RUN poetry run pytest

# ------------------ #
# ACTUAL BUILD STEPS
# ------------------ #
FROM dev_base as packager
RUN rm -rf dist && poetry build

FROM python:3.8.5 as builder
ENV PYTHONUNBUFFERED=1

RUN apt-get update && apt-get install -y \
    build-essential \
    libffi-dev \
    libpq-dev \
    && rm -rf /var/lib/apt/lists/*

COPY --from=packager /app/dist/*.whl /
RUN python -m venv /venv/

# _activate_ the virtual environment
ENV VIRTUAL_ENV=/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"

RUN pip install -U pip && pip install *.whl

# ------------- #
# RUNTIME IMAGE #
# ------------- #
FROM python:3.8.2-slim-buster as runtime
ENV PYTHONUNBUFFERED=1

# Runtime deps
RUN apt-get update && apt-get install -y \
    libpq5 \
    && rm -rf /var/lib/apt/lists/*

COPY --from=builder /venv /venv

# _activate_ the virtual environment
ENV VIRTUAL_ENV=/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"