Using Docker with Project QRE

A Guide to Containerized Development

To ensure a consistent and reproducible environment for development and testing, Project QRE is fully containerized using Docker. This guide provides instructions on how to build and run the application and its dependency (HashiCorp Vault) using Docker and Docker Compose.

Prerequisites

Step 1: Project Files

Ensure your project contains a `requirements.txt`, `.dockerignore` file, `Dockerfile`, and `docker-compose.yml` in the root directory. These files define the Python dependencies, files to exclude from the build, instructions for building the application image, and the services to run.

The `.dockerignore` File

This file prevents unnecessary or sensitive files from being included in the Docker image, optimizing the build process. It should exclude virtual environments, Git history, and IDE configuration files.

# .dockerignore
__pycache__/
*.pyc
.git/
.venv/
.env
docs/
tests/

The `Dockerfile`

This contains the recipe for building our FastAPI application image. It sets up the Python environment, installs dependencies, and copies the application code.

# Dockerfile
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

WORKDIR /app

# Note: System dependencies like cmake or build-essential
# might be needed here if pip cannot find pre-compiled wheels.
# RUN apt-get update && apt-get install -y build-essential cmake

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "api_server.main:app", "--host", "0.0.0.0", "--port", "8000"]

The `docker-compose.yml` File

This file is the heart of our containerized setup. It defines two services: our `api_server` and the `vault` dependency, and configures them to communicate with each other.

# docker-compose.yml
version: '3.8'

services:
  vault:
    image: hashicorp/vault:latest
    ports: ["8200:8200"]
    environment:
      VAULT_DEV_ROOT_TOKEN_ID: "mydevroot"
      VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"
    cap_add: [IPC_LOCK]

  api_server:
    build: .
    ports: ["8000:8000"]
    volumes: [".:/app"] # For live-reloading in development
    environment:
      VAULT_ADDR: "http://vault:8200"
      VAULT_TOKEN: "mydevroot"
      SERVER_API_KEY: "poc_super_secret_api_key_123!"
    depends_on: [vault]
    command: uvicorn api_server.main:app --host 0.0.0.0 --port 8000 --reload

Step 2: Running the Application

With these files in your project root, running the entire stack is simple.

  1. Open a terminal in your project's root directory.
  2. Run the command:
    docker-compose up --build
  3. This command builds the `api_server` image and starts both the API and Vault containers. You will see logs from both services in your terminal.

Step 3: Accessing Services and Testing

Once the containers are running, you can access the services:

You can run your `pytest` suite from a separate terminal against the running API at `http://localhost:8000/api/v1`.

Stopping the Services

To stop the containers, press `Ctrl+C` in the terminal where `docker-compose up` is running. To remove the containers and network completely, run:

docker-compose down