1# Docker Compose with PostgreSQL
2#
3# Usage:
4# docker-compose -f docker-compose.postgres.yaml up -d
5#
6# This file extends the base docker-compose.yaml with a PostgreSQL database.
7# Set the following in your .env file:
8# COCOON_DB_TYPE=postgres
9# POSTGRES_PASSWORD=your-secure-password
10
11version: '3.8'
12
13services:
14 postgres:
15 image: postgres:16-alpine
16 container_name: cocoon-postgres
17 environment:
18 POSTGRES_USER: cocoon
19 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
20 POSTGRES_DB: cocoon
21 volumes:
22 - postgres_data:/var/lib/postgresql/data
23 healthcheck:
24 test: ["CMD-SHELL", "pg_isready -U cocoon -d cocoon"]
25 interval: 10s
26 timeout: 5s
27 retries: 5
28 restart: unless-stopped
29
30 init-keys:
31 build:
32 context: .
33 dockerfile: Dockerfile
34 image: ghcr.io/haileyok/cocoon:latest
35 container_name: cocoon-init-keys
36 volumes:
37 - ./keys:/keys
38 - ./data:/data/cocoon
39 - ./init-keys.sh:/init-keys.sh:ro
40 environment:
41 COCOON_DID: ${COCOON_DID}
42 COCOON_HOSTNAME: ${COCOON_HOSTNAME}
43 COCOON_ROTATION_KEY_PATH: /keys/rotation.key
44 COCOON_JWK_PATH: /keys/jwk.key
45 COCOON_CONTACT_EMAIL: ${COCOON_CONTACT_EMAIL}
46 COCOON_RELAYS: ${COCOON_RELAYS:-https://bsky.network}
47 COCOON_ADMIN_PASSWORD: ${COCOON_ADMIN_PASSWORD}
48 entrypoint: ["/bin/sh", "/init-keys.sh"]
49 restart: "no"
50
51 cocoon:
52 build:
53 context: .
54 dockerfile: Dockerfile
55 image: ghcr.io/haileyok/cocoon:latest
56 container_name: cocoon-pds
57 depends_on:
58 init-keys:
59 condition: service_completed_successfully
60 postgres:
61 condition: service_healthy
62 ports:
63 - "8080:8080"
64 volumes:
65 - ./data:/data/cocoon
66 - ./keys/rotation.key:/keys/rotation.key:ro
67 - ./keys/jwk.key:/keys/jwk.key:ro
68 environment:
69 # Required settings
70 COCOON_DID: ${COCOON_DID}
71 COCOON_HOSTNAME: ${COCOON_HOSTNAME}
72 COCOON_ROTATION_KEY_PATH: /keys/rotation.key
73 COCOON_JWK_PATH: /keys/jwk.key
74 COCOON_CONTACT_EMAIL: ${COCOON_CONTACT_EMAIL}
75 COCOON_RELAYS: ${COCOON_RELAYS:-https://bsky.network}
76 COCOON_ADMIN_PASSWORD: ${COCOON_ADMIN_PASSWORD}
77 COCOON_SESSION_SECRET: ${COCOON_SESSION_SECRET}
78
79 # Database configuration - PostgreSQL
80 COCOON_ADDR: ":8080"
81 COCOON_DB_TYPE: postgres
82 COCOON_DATABASE_URL: postgres://cocoon:${POSTGRES_PASSWORD}@postgres:5432/cocoon?sslmode=disable
83 COCOON_BLOCKSTORE_VARIANT: ${COCOON_BLOCKSTORE_VARIANT:-sqlite}
84
85 # Optional: SMTP settings for email
86 COCOON_SMTP_USER: ${COCOON_SMTP_USER:-}
87 COCOON_SMTP_PASS: ${COCOON_SMTP_PASS:-}
88 COCOON_SMTP_HOST: ${COCOON_SMTP_HOST:-}
89 COCOON_SMTP_PORT: ${COCOON_SMTP_PORT:-}
90 COCOON_SMTP_EMAIL: ${COCOON_SMTP_EMAIL:-}
91 COCOON_SMTP_NAME: ${COCOON_SMTP_NAME:-}
92
93 # Optional: S3 configuration
94 COCOON_S3_BACKUPS_ENABLED: ${COCOON_S3_BACKUPS_ENABLED:-false}
95 COCOON_S3_BLOBSTORE_ENABLED: ${COCOON_S3_BLOBSTORE_ENABLED:-false}
96 COCOON_S3_REGION: ${COCOON_S3_REGION:-}
97 COCOON_S3_BUCKET: ${COCOON_S3_BUCKET:-}
98 COCOON_S3_ENDPOINT: ${COCOON_S3_ENDPOINT:-}
99 COCOON_S3_ACCESS_KEY: ${COCOON_S3_ACCESS_KEY:-}
100 COCOON_S3_SECRET_KEY: ${COCOON_S3_SECRET_KEY:-}
101
102 # Optional: Fallback proxy
103 COCOON_FALLBACK_PROXY: ${COCOON_FALLBACK_PROXY:-}
104 restart: unless-stopped
105 healthcheck:
106 test: ["CMD", "curl", "-f", "http://localhost:8080/xrpc/_health"]
107 interval: 30s
108 timeout: 10s
109 retries: 3
110 start_period: 40s
111
112 create-invite:
113 build:
114 context: .
115 dockerfile: Dockerfile
116 image: ghcr.io/haileyok/cocoon:latest
117 container_name: cocoon-create-invite
118 volumes:
119 - ./keys:/keys
120 - ./create-initial-invite.sh:/create-initial-invite.sh:ro
121 environment:
122 COCOON_DID: ${COCOON_DID}
123 COCOON_HOSTNAME: ${COCOON_HOSTNAME}
124 COCOON_ROTATION_KEY_PATH: /keys/rotation.key
125 COCOON_JWK_PATH: /keys/jwk.key
126 COCOON_CONTACT_EMAIL: ${COCOON_CONTACT_EMAIL}
127 COCOON_RELAYS: ${COCOON_RELAYS:-https://bsky.network}
128 COCOON_ADMIN_PASSWORD: ${COCOON_ADMIN_PASSWORD}
129 COCOON_DB_TYPE: postgres
130 COCOON_DATABASE_URL: postgres://cocoon:${POSTGRES_PASSWORD}@postgres:5432/cocoon?sslmode=disable
131 depends_on:
132 cocoon:
133 condition: service_healthy
134 entrypoint: ["/bin/sh", "/create-initial-invite.sh"]
135 restart: "no"
136
137 caddy:
138 image: caddy:2-alpine
139 container_name: cocoon-caddy
140 ports:
141 - "80:80"
142 - "443:443"
143 volumes:
144 - ./Caddyfile.postgres:/etc/caddy/Caddyfile:ro
145 - caddy_data:/data
146 - caddy_config:/config
147 restart: unless-stopped
148 environment:
149 COCOON_HOSTNAME: ${COCOON_HOSTNAME}
150 CADDY_ACME_EMAIL: ${COCOON_CONTACT_EMAIL:-}
151
152volumes:
153 postgres_data:
154 driver: local
155 caddy_data:
156 driver: local
157 caddy_config:
158 driver: local