How to Set Up Local Development with Docker Compose for Macro

Macro is a multi-service Rust application that orchestrates PostgreSQL, Redis, Kafka, OpenSearch, and authentication services locally using Docker Compose, allowing developers to start the entire stack with a few CLI commands.

Setting up a local development environment for Macro requires coordinating multiple backend services and Rust micro-services. The macro-inc/macro repository provides Docker Compose configurations that containerize the entire architecture, eliminating the need to install Rust toolchains or databases directly on your host machine. This guide walks you through the exact steps to set up local development with Docker Compose for Macro using the official compose files.

Prerequisites

Before starting, ensure you have the following tools installed:

  • Docker Desktop or Docker Engine with Compose v2 support.
  • Git to clone the repository.
  • Optional: Node.js or Bun if you plan to modify the lexical or analytics workers (though these build inside containers).

Clone the Repository

Start by cloning the official Macro repository and navigating into the project root:

git clone https://github.com/macro-inc/macro.git
cd macro

Configure Environment Variables

The compose files load configuration from ${MACRO_ENV_FILE:-.env}, defaulting to a .env file in the project root. While optional for basic setups, you should create this file if you need to override secrets, ports, or connection strings:

touch .env

You can populate this file with custom values, but the stack runs with sensible defaults if left empty.

Start the Core Infrastructure

The databases stack defines PostgreSQL, Redis, Kafka, and OpenSearch in docker/docker-compose-databases.yml. Start these dependencies first:

docker compose -f docker/docker-compose-databases.yml up -d

Key configuration details from this file include:

  • PostgreSQL runs on port 5432 with max connections set to 500 (lines 9-13).
  • Redis exposes its management UI on port 8001.
  • Kafka operates as a single-node KRaft broker on port 9092.
  • OpenSearch runs in single-node mode on port 9200 (lines 80-85).

Start the Authentication Stack (Optional)

If your development work requires local authentication, start the FusionAuth stack defined in infra/stacks/fusionauth-instance/docker-compose.yml:

docker compose -f infra/stacks/fusionauth-instance/docker-compose.yml up -d

This provides an authentication service on port 9011 alongside a dedicated PostgreSQL instance for user data.

Launch the Macro Services

With infrastructure running, start the main Rust application stack using docker/docker-compose.yml. This file defines the x-common-env extension (lines 11-18) for shared environment variables and the x-rust-services-image extension (lines 19-24) which builds the macro-local-rust-services:dev image from docker/Dockerfile.dev.

docker compose -f docker/docker-compose.yml up -d

This command launches:

  • Micro-services such as authentication-service (port 8080), document_storage_service (port 8086), and email_service, each with dedicated health checks (lines 36-70, 84-95, 98-110).
  • Background workers including the ai_editing_worker (lines 124-130) and lexical_service (lines 172-180), which build from their respective Dockerfiles.

Verify the Installation

Confirm all services are healthy by querying their HTTP health endpoints:

curl http://localhost:8080/health          # authentication-service

curl http://localhost:8086/health          # document_storage_service

curl http://localhost:16686                # Jaeger UI (if using jaeger profile)

Stop the Environment

When finished developing, tear down the containers in reverse order:

docker compose -f docker/docker-compose.yml down
docker compose -f docker/docker-compose-databases.yml down
docker compose -f infra/stacks/fusionauth-instance/docker-compose.yml down

Optional Observability Profiles

The main compose file includes optional profiles for monitoring and tracing.

Jaeger (Distributed Tracing)

Start the Jaeger trace viewer on port 16686:

docker compose -f docker/docker-compose.yml --profile jaeger up -d

This profile is defined in lines 112-118 of docker/docker-compose.yml.

Datadog Agent (OTLP Export)

Export telemetry to Datadog by providing your API key:

DD_API_KEY=<your-key> docker compose -f docker/docker-compose.yml --profile datadog up -d

Defined in lines 140-147, this profile runs the Datadog Agent as an OTLP exporter.

Summary

Frequently Asked Questions

Do I need to install Rust locally to develop Macro?

No. The docker/Dockerfile.dev builds the macro-local-rust-services:dev image containing all compiled Rust binaries inside the container. You only need Docker Compose and Git to run the full stack.

Why are the databases and services split into separate compose files?

The separation allows you to manage infrastructure lifecycles independently. You can keep PostgreSQL, Redis, Kafka, and OpenSearch running continuously while restarting only the Rust micro-services during active development, reducing startup time.

How do I override default configuration values?

Create a .env file in the project root. The compose files reference ${MACRO_ENV_FILE:-.env}, loading your overrides for secrets, ports, or connection strings automatically when starting the stack.

Can I run specific services instead of the entire stack?

Yes. Docker Compose supports service names as arguments. For example, to run only the authentication service and its dependencies: docker compose -f docker/docker-compose.yml up -d authentication-service.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →