# Attachments Configuration Attach service dependencies (databases, caches, queues) to your applications. ## Requirements **Network isolation must be enabled** for attachments to work properly: ```toml [network_isolation] enabled = true ``` Without network isolation, containers run on Docker's default bridge network which **does not provide DNS resolution**. Your application won't be able to reach attachments by hostname (e.g., `postgres:5432`). ## Configuration ```toml [attachments] "app.mydomain.com" = ["postgres:latest", "redis:latest"] "api.mydomain.com" = ["postgres:latest"] ``` ## Syntax ```toml [attachments] "" = [":", ":"] ``` | Component | Description | |-----------|-------------| | `domain-or-group` | Route domain or network group name | | `image:tag` | Service images to deploy alongside the app | ## How Attachments Work When you define attachments: 1. Gordon deploys attachment containers to the same network as your app 2. Services are accessible by their image name (before the colon) 3. Attachments start before your main application 4. Attachments persist across app updates ``` ┌───────────────────────────────────────────────────┐ │ Network: gordon-app-mydomain-com │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ App │───>│ postgres │ │ redis │ │ │ │ :3000 │ │ :5432 │ │ :6379 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ └───────────────────────────────────────────────────┘ ``` ## Service Discovery Attachments are accessible by their image name within the network: ```toml [attachments] "app.mydomain.com" = ["postgres:latest", "redis:latest"] ``` In your application: ```javascript // Connect using simple hostnames const db = await pg.connect("postgresql://postgres:5432/mydb"); const cache = await redis.connect("redis://redis:6379"); ``` ## Persistent Storage Use Dockerfile VOLUME directives for persistent data: ```dockerfile # postgres.Dockerfile FROM postgres:18 VOLUME ["/var/lib/postgresql/data"] ENV POSTGRES_DB=myapp ENV POSTGRES_USER=app ENV POSTGRES_PASSWORD=secret ``` Build and push to Gordon: ```bash docker build -f postgres.Dockerfile -t my-postgres:latest . docker push registry.mydomain.com/my-postgres:latest ``` Use in attachments: ```toml [attachments] "app.mydomain.com" = ["my-postgres:latest"] ``` ## Shared Attachments with Network Groups Share services between multiple apps using network groups: ```toml [network_groups] "backend" = ["app.mydomain.com", "api.mydomain.com"] [attachments] "backend" = ["shared-postgres:latest", "shared-redis:latest"] ``` Both `app.mydomain.com` and `api.mydomain.com` can access the shared services. ## Per-App vs Shared Attachments ### Per-App Attachments Each app gets its own isolated service instances: ```toml [attachments] "app.mydomain.com" = ["postgres:latest"] # App's own postgres "api.mydomain.com" = ["postgres:latest"] # API's own postgres ``` ### Shared Attachments Multiple apps share the same service instances: ```toml [network_groups] "backend" = ["app.mydomain.com", "api.mydomain.com"] [attachments] "backend" = ["postgres:latest", "redis:latest"] # Shared by both ``` ### Mixed Approach ```toml [network_groups] "backend" = ["app.mydomain.com", "api.mydomain.com"] [attachments] "backend" = ["redis:latest"] # Shared cache "app.mydomain.com" = ["postgres:latest"] # App's own database "api.mydomain.com" = ["postgres:latest"] # API's own database ``` ## Examples ### Web App with Database ```toml [routes] "app.mydomain.com" = "myapp:latest" [attachments] "app.mydomain.com" = ["postgres:18", "redis:7-alpine"] ``` ### Microservices with Shared Queue ```toml [routes] "orders.mydomain.com" = "orders-service:latest" "inventory.mydomain.com" = "inventory-service:latest" "notifications.mydomain.com" = "notifications-service:latest" [network_groups] "services" = ["orders.mydomain.com", "inventory.mydomain.com", "notifications.mydomain.com"] [attachments] "services" = ["rabbitmq:3-management"] "orders.mydomain.com" = ["orders-db:latest"] "inventory.mydomain.com" = ["inventory-db:latest"] ``` ### Custom Service Images Build custom service images with your configuration: ```dockerfile # my-postgres.Dockerfile FROM postgres:18 VOLUME ["/var/lib/postgresql/data"] ENV POSTGRES_DB=production ENV POSTGRES_USER=appuser # Password should come from env file ``` ```dockerfile # my-redis.Dockerfile FROM redis:7-alpine VOLUME ["/data"] CMD ["redis-server", "--appendonly", "yes"] ``` ```toml [attachments] "app.mydomain.com" = ["my-postgres:latest", "my-redis:latest"] ``` ## Container Naming Attachment containers are named: - `gordon--` - Example: `gordon-app-mydomain-com-postgres` ## Labels Gordon adds labels to attachment containers: | Label | Value | |-------|-------| | `gordon.managed` | `true` | | `gordon.attachment` | `true` | | `gordon.attached-to` | Domain or group name | ## CLI Management Manage attachments via the CLI without editing configuration files. ### List Attachments ```bash # List all attachments gordon attachments list # List attachments for a specific domain or network group gordon attachments list app.mydomain.com gordon attachments list backend # Remote mode gordon attachments list --remote https://gordon.mydomain.com --token $TOKEN ``` ### Add Attachments ```bash # Add attachment to a domain gordon attachments add app.mydomain.com postgres:18 # Add attachment to a network group gordon attachments add backend redis:7-alpine # Remote mode gordon attachments add app.mydomain.com postgres:18 --remote https://gordon.mydomain.com --token $TOKEN ``` ### Remove Attachments ```bash # Remove attachment from a domain gordon attachments remove app.mydomain.com postgres:18 # Remove from network group gordon attachments remove backend redis:7-alpine # Remote mode gordon attachments remove app.mydomain.com postgres:18 --remote https://gordon.mydomain.com --token $TOKEN ``` ### Alias The `gordon attach` command is an alias for `gordon attachments`: ```bash gordon attach list gordon attach add app.mydomain.com postgres:18 gordon attach remove app.mydomain.com postgres:18 ``` ## Related - [Network Isolation](./network-isolation.md) - [Network Groups](./network-groups.md) - [Routes](./routes.md) - [CLI Commands](/docs/cli/index.md)