···11# Binaries
22bin/
33dist/
44+tmp/
4556# Test artifacts
67.atcr-pids
+20-7
Dockerfile.appview
···11-FROM docker.io/golang:1.25.2-trixie AS builder
11+# ==========================================
22+# Stage 1: Development with Air hot reload
33+# ==========================================
44+FROM docker.io/golang:1.25.2-trixie AS dev
2536ENV DEBIAN_FRONTEND=noninteractive
4758RUN apt-get update && \
69 apt-get install -y --no-install-recommends sqlite3 libsqlite3-dev && \
77- rm -rf /var/lib/apt/lists/*
1010+ rm -rf /var/lib/apt/lists/* && \
1111+ go install github.com/air-verse/air@latest
81299-WORKDIR /build
1313+WORKDIR /app
10141515+# Copy go.mod first for layer caching
1116COPY go.mod go.sum ./
1217RUN go mod download
13181919+# For development: source mounted as volume, Air handles builds
2020+EXPOSE 5000
2121+CMD ["air", "-c", ".air.toml"]
2222+2323+# ==========================================
2424+# Stage 2: Production build
2525+# ==========================================
2626+FROM dev AS builder
2727+1428COPY . .
15291630RUN go generate ./...
···2135 -o atcr-appview ./cmd/appview
22362337# ==========================================
2424-# Stage 2: Minimal FROM scratch runtime
3838+# Stage 3: Minimal runtime
2539# ==========================================
2640FROM scratch
4141+2742# Copy CA certificates for HTTPS (PDS, Jetstream, relay connections)
2843COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
2944# Copy timezone data for timestamp formatting
3045COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
3146# Copy optimized binary (SQLite embedded)
3232-COPY --from=builder /build/atcr-appview /atcr-appview
4747+COPY --from=builder /app/atcr-appview /atcr-appview
33483434-# Expose ports
3549EXPOSE 5000
36503737-# OCI image annotations
3851LABEL org.opencontainers.image.title="ATCR AppView" \
3952 org.opencontainers.image.description="ATProto Container Registry - OCI-compliant registry using AT Protocol for manifest storage" \
4053 org.opencontainers.image.authors="ATCR Contributors" \
+12-6
Makefile
···3344.PHONY: all build build-appview build-hold build-credential-helper build-oauth-helper \
55 generate test test-race test-verbose lint clean help install-credential-helper \
66- develop develop-detached develop-down
66+ develop develop-detached develop-down dev
7788.DEFAULT_GOAL := help
99···8181 install -m 755 bin/docker-credential-atcr /usr/local/sbin/docker-credential-atcr
8282 @echo "✓ Installed docker-credential-atcr to /usr/local/sbin/"
83838484+##@ Development Targets
8585+8686+dev: $(GENERATED_ASSETS) ## Run AppView locally with Air hot reload
8787+ @which air > /dev/null || (echo "→ Installing Air..." && go install github.com/air-verse/air@latest)
8888+ air -c .air.toml
8989+8490##@ Docker Targets
85918686-develop: ## Build Docker images and start docker-compose for development
9292+develop: ## Build and start docker-compose with Air hot reload
8793 @echo "→ Building Docker images..."
8894 docker-compose build
8989- @echo "→ Starting docker-compose..."
9595+ @echo "→ Starting docker-compose with hot reload..."
9096 docker-compose up
91979292-develop-detached: ## Build and start docker-compose in detached mode
9898+develop-detached: ## Build and start docker-compose with hot reload (detached)
9399 @echo "→ Building Docker images..."
94100 docker-compose build
9595- @echo "→ Starting docker-compose (detached)..."
101101+ @echo "→ Starting docker-compose with hot reload (detached)..."
96102 docker-compose up -d
9797- @echo "✓ Services started in background"
103103+ @echo "✓ Services started in background with hot reload"
98104 @echo " AppView: http://localhost:5000"
99105 @echo " Hold: http://localhost:8080"
100106
+10-6
docker-compose.yml
···33 build:
44 context: .
55 dockerfile: Dockerfile.appview
66- image: atcr-appview:latest
66+ target: dev
77+ image: atcr-appview-dev:latest
78 container_name: atcr-appview
89 ports:
910 - "5000:5000"
···1516 ATCR_HTTP_ADDR: :5000
1617 ATCR_DEFAULT_HOLD_DID: did:web:172.28.0.3:8080
1718 # UI configuration
1818- ATCR_UI_ENABLED: true
1919- ATCR_BACKFILL_ENABLED: true
1919+ ATCR_UI_ENABLED: "true"
2020+ ATCR_BACKFILL_ENABLED: "true"
2021 # Test mode - fallback to default hold when user's hold is unreachable
2121- TEST_MODE: true
2222+ TEST_MODE: "true"
2223 # Logging
2324 ATCR_LOG_LEVEL: debug
2425 volumes:
2525- # Auth keys (JWT signing keys)
2626- # - atcr-auth:/var/lib/atcr/auth
2626+ # Mount source code for Air hot reload
2727+ - .:/app
2828+ # Cache go modules between rebuilds
2929+ - go-mod-cache:/go/pkg/mod
2730 # UI database (includes OAuth sessions, devices, and Jetstream cache)
2831 - atcr-ui:/var/lib/atcr
2932 restart: unless-stopped
···8285 atcr-hold:
8386 atcr-auth:
8487 atcr-ui:
8888+ go-mod-cache: