# Dockerfile and Containerization Strategy for macro-inc/macro: A Complete Guide

> Discover the macro-inc/macro Dockerfile and containerization strategy. This guide details a multi-stage build, isolated compilation, and composite development containers for efficient development and deployment.

- Repository: [Macro/macro](https://github.com/macro-inc/macro)
- Tags: how-to-guide
- Published: 2026-08-15

---

**The macro-inc/macro repository employs a layered, multi-stage Docker strategy that isolates Rust compilation from runtime using Debian Trixie-slim images, alongside service-specific Dockerfiles and a composite development container orchestrated via Docker Compose.**

The **macro-inc/macro** monorepo implements a sophisticated **containerization strategy** designed for microservice isolation and reproducible builds. This architecture leverages multi-stage Dockerfiles to minimize production image sizes while providing comprehensive Docker Compose orchestration for local development and CI/CD pipelines.

## Multi-Stage Production Build Architecture

### The Rust Chef and Builder Stages

The primary production pipeline resides in `docker/Dockerfile`, implementing a three-stage build process. The first stage utilizes a **Rust "chef"** image (`FROM rust:latest AS chef`) to install the Cargo workspace and cache dependencies. The subsequent **builder** stage (`FROM chef AS builder`) compiles every service using `cargo build --release`, creating optimized binaries while maintaining build artifacts in isolated layers.

### The Runtime Runner Stage

The final stage switches to a lightweight **Debian Trixie-slim** base (`FROM debian:trixie-slim AS runner`), copying only the compiled binaries and essential runtime libraries from the builder. This approach yields minimal production images of approximately 100 MB, significantly reducing the attack surface and deployment time compared to standard Rust images.

## Service-Specific Containerization Patterns

### WebSocket Service Container

Individual microservices maintain dedicated Dockerfiles under `docker/` for specialized runtime requirements. The **WebSocket Service** defined in `docker/websocket-service.Dockerfile` utilizes the `oven/bun` base image for Node.js runtime capabilities, copying the pre-compiled binary into an optimized container designed for real-time communication workloads.

### Sync Service Multi-Runtime Build

The **Sync Service** (`docker/sync-service.Dockerfile`) demonstrates complex multi-runtime containerization by combining Rust builder stages with **Node 22-slim** environments. This configuration handles frontend asset compilation alongside backend binary generation, ensuring both Rust and JavaScript dependencies resolve correctly within isolated build contexts.

### Search Processing Service Pipeline

For the search infrastructure, `docker/Dockerfile.search_processing_service` extends the standard pattern with four distinct stages: **chef → planner → builder → runner**. This granular separation optimizes caching for the OpenSearch integration pipeline while maintaining the minimal Debian-based runtime environment.

## Development Environment and Orchestration

### Composite Development Image (Dockerfile.dev)

Local development utilizes `docker/Dockerfile.dev` to create a unified container bundling all services. This sequential layer approach (`FROM services_bundle AS authentication_service`, etc.) enables rapid iteration via `docker compose up`, launching the entire stack from a single image while preserving service isolation in the build steps.

### Docker Compose Orchestration

The [`docker/docker-compose.yml`](https://github.com/macro-inc/macro/blob/main/docker/docker-compose.yml) file orchestrates all microservices alongside supporting infrastructure including PostgreSQL, Redis, and OpenSearch. Each service references its respective Dockerfile, exposing required ports and establishing network connectivity for end-to-end local development.

### Infrastructure Stacks

Additional containerization configurations reside under `infra/`, including [`infra/stacks/fusionauth-instance/docker-compose.yml`](https://github.com/macro-inc/macro/blob/main/infra/stacks/fusionauth-instance/docker-compose.yml) for authentication testing and `infra/local/opensearch/Dockerfile` for search node provisioning. These self-contained stacks embody the repository's "in-repo, self-contained" philosophy for dependency management.

## Build Automation and Tooling

### Just Task Runner Integration

The project employs the **just** task runner to standardize Docker operations across environments. The `just` wrapper commands synchronize SQLx query caches before compilation and manage multi-service builds:

```bash

# Build the production image

just build

# Build only the sync service

just build sync_service

# Prepare database schemas before Docker build

just prepare_db

```

### CI/CD Container Workflows

For continuous integration, the multi-stage Dockerfiles support standardized build patterns. The following commands demonstrate production and single-service builds:

```bash

# Build and tag the production image

docker build -f docker/Dockerfile -t macro:latest .

# Build a specific service image

docker build -f docker/sync-service.Dockerfile -t macro/sync-service .

```

### Local Development Commands

To run the full stack locally, execute the following sequence:

```bash

# Pull supporting infrastructure (Postgres, Redis, OpenSearch)

docker compose -f docker/docker-compose.yml pull

# Build the composite development image

docker build -f docker/Dockerfile.dev -t macro/dev .

# Start all services

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

```

## Summary

- **Multi-stage isolation**: The `docker/Dockerfile` separates Rust compilation (chef/builder) from runtime (Debian Trixie-slim), producing ~100 MB production images.
- **Service-specific optimization**: Individual Dockerfiles like `websocket-service.Dockerfile` and `sync-service.Dockerfile` accommodate multi-runtime requirements (Rust + Bun/Node).
- **Unified development**: `Dockerfile.dev` bundles all services into a single image for rapid `docker compose up` workflows.
- **Infrastructure as code**: The `infra/` directory contains self-contained stacks for OpenSearch and FusionAuth, enabling complete local testing environments.
- **Build automation**: The **just** task runner integrates SQLx cache preparation with Docker builds for reproducible CI/CD pipelines.

## Frequently Asked Questions

### What containerization strategy does macro-inc/macro use?

The repository implements a **multi-stage Docker build strategy** that separates compilation from runtime. Production images are built via `docker/Dockerfile` using Rust chef/builder stages followed by a minimal Debian Trixie-slim runner, while development uses `Dockerfile.dev` to bundle all services into a single composite image orchestrated by Docker Compose.

### How does the multi-stage Dockerfile reduce image size?

By utilizing distinct **builder** and **runner** stages in `docker/Dockerfile`, the build process discards compilation tools and intermediate artifacts after creating the release binaries. Only the compiled binaries and essential runtime libraries are copied to the final Debian Trixie-slim stage, reducing the final image size to approximately 100 MB compared to standard Rust images that include the full toolchain.

### Can I run a single service without building the entire monorepo?

Yes. The repository provides service-specific Dockerfiles such as `docker/sync-service.Dockerfile` and `docker/websocket-service.Dockerfile` that can be built independently. Use `docker build -f docker/sync-service.Dockerfile -t macro/sync-service .` to build only the sync service, then run it attached to the shared Docker Compose network via `docker run -d --network macro_default macro/sync-service`.

### What is the purpose of Dockerfile.dev versus the production Dockerfile?

`docker/Dockerfile` creates minimal, production-ready images containing only compiled binaries for deployment. In contrast, `docker/Dockerfile.dev` generates a **composite development image** that includes all services and development dependencies, allowing developers to launch the entire stack with a single `docker compose up` command for rapid local iteration and debugging.