Skip to content

Commit 9b2ec0c

Browse files
committed
On branch main
Your branch is up to date with 'origin/main'. Changes to be committed: new file: CLAUDE.md
1 parent 200094a commit 9b2ec0c

File tree

1 file changed

+229
-0
lines changed

1 file changed

+229
-0
lines changed

CLAUDE.md

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
This is the official Discourse Docker deployment system (`discourse_docker`). It provides Docker images, launcher scripts, and templates for deploying and managing Discourse forum instances. The system uses a container orchestration approach with pups-managed YAML templates.
8+
9+
## Core Architecture
10+
11+
### Launcher Script (`./launcher`)
12+
13+
The primary interface for all container operations. Written in Bash, it manages the complete lifecycle of Discourse containers:
14+
15+
- `./launcher bootstrap CONFIG` - Initial container setup from templates
16+
- `./launcher start CONFIG` - Start a container
17+
- `./launcher stop CONFIG` - Stop a running container
18+
- `./launcher restart CONFIG` - Restart a container
19+
- `./launcher destroy CONFIG` - Stop and remove a container
20+
- `./launcher enter CONFIG` - Shell into a running container
21+
- `./launcher logs CONFIG` - View container logs
22+
- `./launcher rebuild CONFIG` - Full rebuild (destroy + bootstrap + start)
23+
- `./launcher cleanup` - Remove stopped containers (>24h old)
24+
25+
CONFIG refers to a YAML file in `/containers/` (e.g., `app.yml`).
26+
27+
### Setup Scripts
28+
29+
- `./discourse-setup` - Interactive initial configuration wizard that creates container YAML files
30+
- `./discourse-doctor` - Diagnostic tool for troubleshooting installations
31+
32+
### Directory Structure
33+
34+
- `/containers/` - User-managed container definitions (you create these)
35+
- `/samples/` - Example container configurations to copy from:
36+
- `standalone.yml` - All-in-one single container setup (easiest)
37+
- `data.yml` + `web_only.yml` - Multi-container setup (production)
38+
- `mail-receiver.yml` - Mail receiver container
39+
- `redis.yml` - Standalone Redis container
40+
- `/templates/` - pups-managed YAML templates that are composed into containers:
41+
- `postgres.template.yml` - PostgreSQL (current stable version)
42+
- `postgres.{15,13,12,10,9.5}.template.yml` - Specific PostgreSQL versions
43+
- `redis.template.yml` - Redis configuration
44+
- `web.template.yml` - Nginx + Rails web server
45+
- `web.ssl.template.yml` - SSL/HTTPS support
46+
- `web.letsencrypt.ssl.template.yml` - Let's Encrypt SSL
47+
- `web.ratelimited.template.yml` - Rate limiting
48+
- `cron.template.yml` - Scheduled tasks
49+
- Other specialized templates for CDN, caching, etc.
50+
- `/image/` - Dockerfiles and build scripts for base images
51+
- `/shared/` - Persistent data mounted into containers (logs, uploads, backups)
52+
- `/cids/` - Container IDs for running containers
53+
54+
### Container Configuration (YAML Files)
55+
56+
Container definitions use YAML with these sections:
57+
58+
- `templates:` - Array of template files to compose
59+
- `expose:` - Port mappings (format: `"host_port:container_port"`)
60+
- `params:` - Template parameters (e.g., `db_shared_buffers`, `version`)
61+
- `env:` - Environment variables for the container
62+
- `volumes:` - Volume mounts (host to guest mappings)
63+
- `links:` - Link to other containers
64+
- `hooks:` - Custom pups hooks (before_code, after_code, etc.)
65+
- `run:` - Commands to execute during bootstrap
66+
67+
**IMPORTANT**: YAML is whitespace-sensitive. Use https://yamllint.com/ to validate.
68+
69+
### pups Template System
70+
71+
Templates use pups (https://github.com/discourse/pups) which processes YAML configurations. Templates define:
72+
- Base images via `base_image:`
73+
- Environment setup via `env:` and `params:`
74+
- Bootstrap commands via `run:` blocks
75+
- File creation via `file:` directives
76+
- Command execution via `exec:` directives
77+
- Text replacement via `replace:` directives
78+
79+
### Docker Images
80+
81+
Built via `image/auto_build.rb`:
82+
83+
```bash
84+
# Build a specific image (run from /image/ directory)
85+
ruby auto_build.rb IMAGE_NAME
86+
```
87+
88+
Available images (defined in `auto_build.rb`):
89+
- `base_*` - Base images with Discourse dependencies (multiple targets: deps, slim, web_only, release)
90+
- `discourse_dev_*` - Development environment (includes Redis + PostgreSQL)
91+
- `discourse_test_*` - Test environment with testing tools
92+
- Suffixes: `_amd64` or `_arm64` for architecture
93+
- Variations: `_main` (latest) or `_stable` (stable branch)
94+
95+
Image types:
96+
- **discourse/base** - Production-ready with all dependencies (postgres, nginx, ruby, imagemagick, etc.)
97+
- **discourse/discourse_dev** - All-in-one dev container (mount source to `/src`)
98+
- **discourse/discourse_test** - Test environment with testing tools
99+
100+
Published to Docker Hub at `discourse/base` and `discourse/discourse_dev`.
101+
102+
## Common Development Tasks
103+
104+
### Testing discourse-setup
105+
106+
Run tests from `/tests/` directory:
107+
108+
```bash
109+
cd tests
110+
./run-all-tests # Run all tests
111+
./standalone-tests # Test standalone.yml generation
112+
./two-container-tests # Test multi-container setup
113+
./update-old-templates # Test template upgrades
114+
```
115+
116+
**Note**: Tests require that `app.yml` and `web_only.yml` do not exist.
117+
118+
### Building Docker Images
119+
120+
```bash
121+
cd image
122+
ruby auto_build.rb base_release_main_amd64 # Build amd64 release image
123+
ruby auto_build.rb discourse_dev_arm64 # Build arm64 dev image
124+
```
125+
126+
See `.github/workflows/build.yml` for the full CI build process.
127+
128+
### Deploying Containers
129+
130+
```bash
131+
# Copy a sample configuration
132+
cp samples/standalone.yml containers/app.yml
133+
134+
# Edit the configuration (set DISCOURSE_HOSTNAME, SMTP settings, etc.)
135+
nano containers/app.yml
136+
137+
# Bootstrap and start
138+
sudo ./launcher bootstrap app
139+
sudo ./launcher start app
140+
141+
# Or rebuild everything
142+
sudo ./launcher rebuild app
143+
```
144+
145+
### Upgrading Discourse
146+
147+
Two methods:
148+
1. Web UI: `http://yoursite.com/admin/upgrade`
149+
2. Command line: `sudo ./launcher rebuild app`
150+
151+
### Troubleshooting
152+
153+
```bash
154+
# View logs
155+
./launcher logs app
156+
157+
# Enter container for debugging
158+
./launcher enter app
159+
160+
# Run diagnostics
161+
./discourse-doctor app
162+
```
163+
164+
## Architecture Notes
165+
166+
### Single vs Multi-Container
167+
168+
**Single Container** (`standalone.yml`):
169+
- All services in one container (PostgreSQL, Redis, Nginx, Rails)
170+
- Easiest to set up and manage
171+
- Suitable for smaller installations
172+
173+
**Multi-Container** (`data.yml` + `web_only.yml`):
174+
- Separate data and web containers
175+
- Zero-downtime upgrades (rebuild web while data keeps running)
176+
- Horizontal scaling capability
177+
- Requires firewall configuration (iptables/ufw) to protect PostgreSQL/Redis ports
178+
179+
### Template Composition
180+
181+
Containers compose templates in order. Later templates can override earlier ones via hooks. Example from `standalone.yml`:
182+
183+
```yaml
184+
templates:
185+
- "templates/postgres.template.yml"
186+
- "templates/redis.template.yml"
187+
- "templates/web.template.yml"
188+
- "templates/web.ratelimited.template.yml"
189+
```
190+
191+
### Bundled Plugins
192+
193+
The launcher script defines `BUNDLED_PLUGINS` array (line 26-59) containing official Discourse plugins that can be installed via the docker_manager.
194+
195+
## Important Constraints
196+
197+
- **Root required**: `launcher` and `discourse-setup` must run as root (use `sudo`)
198+
- **Email required**: Discourse requires SMTP configuration to function
199+
- **No bare IPs**: Must use a domain name for `DISCOURSE_HOSTNAME`
200+
- **Persistent data**: All data stored in `/shared` volumes - containers are stateless
201+
- **Port conflicts**: Default ports 80/443 must be available (or configure alternative ports)
202+
- **YAML sensitivity**: Indentation and whitespace matter - validate before rebuilding
203+
204+
## CI/CD
205+
206+
GitHub Actions workflow (`.github/workflows/build.yml`):
207+
- Builds all image variants (amd64/arm64, main/stable, slim/web_only/release)
208+
- Runs Discourse specs on built images
209+
- Publishes to Docker Hub on main branch
210+
- Creates multi-arch manifests
211+
- Scheduled daily builds
212+
213+
## Environment Variables
214+
215+
Key environment variables in container configs:
216+
- `DISCOURSE_HOSTNAME` - Domain name (required)
217+
- `DISCOURSE_DEVELOPER_EMAILS` - Admin emails on first signup
218+
- `DISCOURSE_SMTP_ADDRESS/PORT/USER_NAME/PASSWORD` - Email config (required)
219+
- `DISCOURSE_DB_HOST/PORT/SOCKET` - Database connection
220+
- `UNICORN_WORKERS` - Web worker count (auto-detected based on CPU)
221+
- `LETSENCRYPT_ACCOUNT_EMAIL` - For Let's Encrypt SSL
222+
- `DISCOURSE_CDN_URL` - CDN configuration
223+
- `RAILS_ENV` - Usually 'production'
224+
225+
## Version Management
226+
227+
- Default: Uses `version: latest` to pull latest Discourse version
228+
- Can pin to specific version: `version: v3.1.0` in container params
229+
- Base image version specified in `web.template.yml` (e.g., `discourse/base:2.0.20251003-1437`)

0 commit comments

Comments
 (0)