一键导入
docker-redis-iac
Multi-stage Docker builds, Docker Compose for local dev, Redis Socket.IO adapter for horizontal scaling, and safe Prisma production migrations.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Multi-stage Docker builds, Docker Compose for local dev, Redis Socket.IO adapter for horizontal scaling, and safe Prisma production migrations.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Review TypeScript DDD clean architecture code for correctness bugs, layer violations, and simplification opportunities. Trigger when the user says "review this", "check this code", "code review", "what's wrong with this", "is this correct DDD?", "does this follow clean architecture?", or when changes touch domain, application, or infrastructure layers.
Security review for TypeScript DDD code — OWASP-mapped checks for injection, auth/authz, data exposure, and misconfiguration. Trigger when the user says "security review", "check for vulnerabilities", "is this secure?", "review auth code", or when changes touch authentication, authorization, input handling, external APIs, file uploads, or user-controlled data.
Review and simplify TypeScript DDD code — remove unnecessary complexity, eliminate duplication, reduce premature abstraction. Trigger when the user says "simplify this", "too much boilerplate", "over-engineered", "clean this up", "refactor this", or when code has grown too abstract or introduces patterns before they prove value.
Design and implement the CQRS (Command Query Responsibility Segregation) pattern in a TypeScript DDD clean architecture project. Trigger when the user says "implement CQRS", "add a command", "add a query", "create a use case", "add a command handler", "build the application layer", "set up the command bus", or when the user needs to add a new feature and is asking how to wire up the application layer. Also trigger when distinguishing between write operations (commands) and read operations (queries) in any context.
Design and implement the Repository pattern in a TypeScript DDD clean architecture project — define repository interfaces in the domain layer and implementations in the infrastructure layer. Trigger when the user says "create a repository", "implement persistence", "add database access", "wire up TypeORM/Prisma/Drizzle", "implement the repository interface", "add Unit of Work", "how do I persist this aggregate", or when connecting domain aggregates to any data store. Also trigger when reviewing persistence code that may be violating the dependency rule.
Design and implement CI/CD pipelines for a TypeScript DDD clean architecture project — GitHub Actions, GitLab CI, Docker builds, environment promotion, and secrets management. Trigger when the user says "set up CI", "add a pipeline", "automate tests", "write a GitHub Actions workflow", "configure deployment", "add Docker support", "set up CD", "automate the build", or when the project needs automated quality gates before merge. Also trigger when the user asks about environment promotion (dev → staging → prod) or secrets management strategy.
| name | docker-redis-iac |
| description | Multi-stage Docker builds, Docker Compose for local dev, Redis Socket.IO adapter for horizontal scaling, and safe Prisma production migrations. |
DevOps and Infrastructure specialist for Node.js apps using Prisma, Express, and Socket.IO. Goal: stateless, scalable, production-ready containers.
docker-composeprisma migrate deploy in CI/CD or Docker entrypointprisma migrate deploy in production only; prisma db push is banned.# ── Stage 1: Builder ───────────────────────────────────────────
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci # reproducible install; respects package-lock.json
COPY prisma ./prisma
RUN npx prisma generate # generate client before compile
COPY tsconfig.json .
COPY src ./src
RUN npm run build # outputs to /app/dist
# ── Stage 2: Runner (lean production image) ───────────────────
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev # production deps only
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
EXPOSE 3000
CMD ["node", "dist/main/server.js"]
Why two stages? The builder needs TypeScript compiler, dev deps, and prisma CLI (~600 MB). The runner copies only compiled JS + prod deps (~80 MB).
# docker-compose.yml
version: '3.9'
services:
app:
build: .
ports:
- '3000:3000'
environment:
DATABASE_URL: postgres://dev:dev@postgres:5432/appdb
REDIS_URL: redis://redis:6379
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
POSTGRES_DB: appdb
ports:
- '5432:5432'
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U dev']
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- '6379:6379'
volumes:
postgres_data:
Install:
npm install @socket.io/redis-adapter ioredis
Wire up only in the Infrastructure bootstrap — the Application layer stays unaware of Redis:
// src/infrastructure/realtime/socket-io.bootstrap.ts
import { createAdapter } from '@socket.io/redis-adapter';
import { Redis } from 'ioredis';
import { Server } from 'socket.io';
export function attachRedisAdapter(io: Server): void {
const pubClient = new Redis(process.env.REDIS_URL!);
const subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));
console.log('[Socket.IO] Redis adapter attached');
}
// src/main/server.ts
import { attachRedisAdapter } from '../infrastructure/realtime/socket-io.bootstrap';
const io = new Server(httpServer, { cors: { origin: '*' } });
attachRedisAdapter(io); // ← Redis wired here, NOT in use cases
// src/infrastructure/publishers/socketio.publisher.ts
import { IRealTimePublisher } from '../../application/ports/realtime-publisher.port';
import { Server } from 'socket.io';
export class SocketIOPublisher implements IRealTimePublisher {
constructor(private readonly io: Server) {}
publish(event: string, payload: unknown): void {
// io.emit broadcasts across ALL nodes via the Redis adapter automatically
this.io.emit(event, payload);
}
}
# entrypoint.sh
#!/bin/sh
set -e
echo "Running database migrations..."
npx prisma migrate deploy # safe, does NOT re-run applied migrations
echo "Starting server..."
exec node dist/main/server.js
# In Dockerfile runner stage — replace CMD with entrypoint
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]
- name: Run Prisma Migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
| Variable | Example | Where set |
|---|---|---|
DATABASE_URL | postgres://user:pass@host:5432/db | .env, Docker secret |
REDIS_URL | redis://redis:6379 | .env, Docker secret |
NODE_ENV | production | Dockerfile ENV directive |
PORT | 3000 | Optional, defaults to 3000 |
When asked to dockerize or scale the application:
DATABASE_URL, REDIS_URL)Dockerfile (builder → runner)docker-compose.yml for local dev (postgres + redis)entrypoint.sh running prisma migrate deploy before server startinfrastructure/ layer only| ❌ Never Do | ✅ Instead |
|---|---|
prisma db push in production | prisma migrate deploy |
| Single-stage Dockerfile with dev deps | Multi-stage: builder + runner |
| Storing Socket.IO rooms in memory | Use @socket.io/redis-adapter |
Importing ioredis in a Use Case | Inject IRealTimePublisher port |
Hardcoding secrets in docker-compose.yml | Use environment variables / Docker secrets |
npm install in runner stage | npm ci --omit=dev in dedicated stage |