# Understanding the MobileAudit Docker Compose Architecture: Web, Worker, and Service Interactions

> Explore the MobileAudit Docker Compose architecture. Understand how Nginx, Django web, Celery workers, RabbitMQ, and PostgreSQL services interact to manage audit data and tasks.

- Repository: [Mónica Pastor/mobileaudit](https://github.com/mpast/mobileaudit)
- Tags: architecture
- Published: 2026-03-07

---

**MobileAudit uses a five-service Docker Compose architecture where Nginx proxies external traffic to a Django web application, which delegates background tasks to Celery workers via RabbitMQ, with PostgreSQL persisting all audit data.**

The `mpast/mobileaudit` repository implements a clean microservice-style **Docker Compose architecture** that separates concerns across five distinct containers. This design isolates the web interface, background processing, message queuing, data persistence, and reverse proxying into dedicated services that communicate over a shared Docker network.

## Overview of the MobileAudit Service Stack

The architecture defined in [`docker-compose.yaml`](https://github.com/mpast/mobileaudit/blob/main/docker-compose.yaml) orchestrates five primary services:

- **db**: PostgreSQL 16 database for persistent storage
- **web**: Django application server handling HTTP requests
- **nginx**: Reverse proxy terminating external traffic on port 8888
- **rabbitmq**: Message broker managing asynchronous task queues
- **worker**: Celery background processor consuming tasks from RabbitMQ

Each service runs in isolation but resolves other services by their container names (e.g., `db`, `rabbitmq`) through Docker's internal DNS.

## Service Definitions and Configurations

### Database Service (db)

The `db` service uses the official `postgres:16-bullseye` image and exposes port `${SQL_PORT:-5432}`. It mounts a named volume `db-data` to ensure audit records survive container restarts.

Configuration loads from `.env.example`, defining the database name, user, and password. The web and worker services connect via the hostname `db` on the default PostgreSQL port.

### Web Application Service (web)

Built from the repository root using `Dockerfile`, the `web` service produces the `mobile_audit` image. It executes [`entrypoint/web_entrypoint.sh`](https://github.com/mpast/mobileaudit/blob/main/entrypoint/web_entrypoint.sh) to initialize Django and start the development server on port 8000.

The service mounts the source code into `/app` for live reloading during development. It declares an explicit dependency on the `db` service to ensure database readiness before application startup.

### Reverse Proxy Service (nginx)

The `nginx` service runs `nginx:stable-bullseye` and binds host port 8888 to container port 8888. It loads [`nginx/app.conf`](https://github.com/mpast/mobileaudit/blob/main/nginx/app.conf), which defines upstream proxying to the `web` service.

Nginx terminates SSL (if configured) and handles static file serving, load balancing, and connection pooling. The service depends on `web`, ensuring the application server is available before accepting external traffic.

### Message Broker Service (rabbitmq)

Using `rabbitmq:3.13.0-management`, this service provides AMQP messaging on port 5672 and the management UI. Credentials source from `.env.example`, matching the configuration used by Django's Celery integration.

The `worker` service links directly to `rabbitmq`, enabling hostname resolution and network access for message consumption.

### Background Worker Service (worker)

Also using the `mobile_audit` image, the `worker` service executes [`entrypoint/worker_entrypoint.sh`](https://github.com/mpast/mobileaudit/blob/main/entrypoint/worker_entrypoint.sh) to start Celery workers. It processes audit tasks asynchronously, fetching jobs from `rabbitmq` and persisting results to the `db` service.

The worker links to both `rabbitmq` (for task consumption) and `web` (for configuration access), with an explicit `depends_on` constraint ensuring RabbitMQ starts first.

## Service Interactions and Data Flow

### Startup Sequence and Dependencies

Docker Compose orchestrates startup order through `depends_on` directives defined in [`docker-compose.yaml`](https://github.com/mpast/mobileaudit/blob/main/docker-compose.yaml):

1. **db** initializes first, creating the PostgreSQL instance
2. **web** starts once `db` is ready, running migrations and starting the Django server
3. **nginx** launches after `web` is healthy, opening port 8888 for external access
4. **rabbitmq** starts independently, providing the message queue
5. **worker** initializes last, after `rabbitmq` is available, to begin consuming tasks

### HTTP Request Handling Flow

External clients interact with the **Docker Compose architecture** through the following path:

1. Client sends request to `http://localhost:8888`
2. **nginx** (listening on host port 8888) receives the connection
3. Nginx proxies the request to the **web** service at `web:8000` according to [`nginx/app.conf`](https://github.com/mpast/mobileaudit/blob/main/nginx/app.conf)
4. The Django application processes the request, querying the **db** service via PostgreSQL protocol on port 5432
5. Response flows back through nginx to the client

### Asynchronous Task Processing Flow

Background audit jobs flow through the message broker architecture:

1. The **web** service publishes audit tasks to **rabbitmq** using Celery's AMQP producer on port 5672
2. **rabbitmq** queues the message in the appropriate exchange
3. The **worker** service (running Celery workers) consumes the message from `rabbitmq:5672`
4. The worker performs the audit, fetching additional configuration from **web** if needed
5. Results are persisted to the **db** service using SQLAlchemy or Django ORM connections

### Data Persistence Strategy

The architecture ensures data durability through Docker volumes and service separation:

- **db-data** volume: Mounts `/var/lib/postgresql/data` in the `db` container, preserving audit records across container restarts and rebuilds
- **Source mounts**: The `web` and `worker` services mount the repository root into `/app`, enabling live code updates without image rebuilds during development
- **Configuration externalization**: All sensitive credentials and environment variables load from `.env.example`, keeping secrets out of the container images

## Key Configuration Files

The **Docker Compose architecture** relies on several critical files located in the repository root:

- **[`docker-compose.yaml`](https://github.com/mpast/mobileaudit/blob/main/docker-compose.yaml)**: Defines the five services, their dependencies, port mappings, volume mounts, and environment variable injection
- **`Dockerfile`**: Multi-stage build definition creating the `mobile_audit` image used by both `web` and `worker` services
- **[`entrypoint/web_entrypoint.sh`](https://github.com/mpast/mobileaudit/blob/main/entrypoint/web_entrypoint.sh)**: Initialization script that waits for database readiness, runs Django migrations, and starts the Gunicorn development server
- **[`entrypoint/worker_entrypoint.sh`](https://github.com/mpast/mobileaudit/blob/main/entrypoint/worker_entrypoint.sh)**: Startup script that initializes Celery workers and connects them to the RabbitMQ broker
- **[`nginx/app.conf`](https://github.com/mpast/mobileaudit/blob/main/nginx/app.conf)**: Reverse proxy configuration defining upstream servers, static file handling, and client connection parameters

## Common Operations and Commands

Manage the MobileAudit **Docker Compose architecture** using these standard commands:

Start the entire stack in detached mode:

```bash
docker compose up -d

```

View real-time logs across all services:

```bash
docker compose logs -f

```

Execute Django management commands inside the web container:

```bash
docker compose exec web python manage.py migrate

```

Access the PostgreSQL database directly from the host:

```bash
psql -h localhost -p 5432 -U postgres -d audit

```

Publish a test message to the RabbitMQ queue:

```bash
docker compose exec rabbitmq rabbitmqadmin publish exchange=amq.default routing_key=task payload='{"type":"audit","target":"example.com"}'

```

## Summary

- MobileAudit implements a **five-service Docker Compose architecture** separating web serving, background processing, data persistence, message queuing, and reverse proxying.
- **Nginx** terminates external traffic on port 8888 and proxies to the Django **web** service, which depends on the **db** PostgreSQL container.
- **RabbitMQ** handles asynchronous task distribution between the **web** application and **worker** processes, enabling scalable background audit jobs.
- All services communicate over Docker's internal network using service names as hostnames, with data persisted via named volumes and environment configuration externalized to `.env.example`.

## Frequently Asked Questions

### What is the startup order of services in MobileAudit?

Docker Compose starts services according to the `depends_on` directives defined in [`docker-compose.yaml`](https://github.com/mpast/mobileaudit/blob/main/docker-compose.yaml). The **db** service initializes first, followed by the **web** service once the database is ready. **Nginx** starts after the web service is healthy, while **rabbitmq** launches independently. The **worker** service starts last, ensuring the message broker is available before consuming tasks.

### How does Nginx communicate with the web service?

Nginx acts as a reverse proxy using the configuration defined in [`nginx/app.conf`](https://github.com/mpast/mobileaudit/blob/main/nginx/app.conf). It listens on host port 8888 and forwards incoming HTTP requests to the **web** service at its internal address `web:8000`. The `depends_on` constraint ensures Nginx only starts after the web container is running, preventing connection errors during startup.

### What is the role of RabbitMQ in the MobileAudit architecture?

RabbitMQ serves as the **message broker** for Celery-based asynchronous task processing. When the **web** service enqueues an audit job, it publishes a message to RabbitMQ's AMQP endpoint at `rabbitmq:5672`. The **worker** service consumes these messages, executes the background audit tasks, and persists results to the database, decoupling heavy processing from the HTTP request/response cycle.

### How is data persisted across container restarts?

MobileAudit uses **Docker named volumes** and externalized configuration to ensure data durability. The **db** service mounts a volume named `db-data` to `/var/lib/postgresql/data`, preserving all audit records and schema changes across container restarts. Environment variables and credentials load from `.env.example`, ensuring configuration persists independently of container lifecycles.