CrewAI Tutorial (TypeScript): deploying with Docker for intermediate developers

By Cyprian AaronsUpdated 2026-04-21
crewaideploying-with-docker-for-intermediate-developerstypescript

This tutorial shows you how to package a CrewAI TypeScript agent into a Docker image, run it locally, and prepare it for deployment. You need this when your agent works on your laptop but you want the same runtime, dependencies, and environment variables in staging or production.

What You'll Need

  • Node.js 20+
  • Docker Desktop or Docker Engine
  • A CrewAI TypeScript project already initialized
  • An OpenAI API key set as an environment variable
  • npm or pnpm
  • These packages installed in your project:
    • crewai
    • dotenv
    • typescript
    • tsx for local execution
  • A .env file with your API key:
    • OPENAI_API_KEY=...

Step-by-Step

  1. Start with a minimal CrewAI setup that works locally. Keep the agent, task, and crew definitions in one file so you can validate the behavior before containerizing anything.
import "dotenv/config";
import { Agent, Task, Crew, Process } from "crewai";

const researcher = new Agent({
  role: "Research Analyst",
  goal: "Summarize customer support trends",
  backstory: "You analyze operational data for insurance teams.",
});

const task = new Task({
  description: "Write a short summary of common support issues.",
  expectedOutput: "A concise bullet list of support themes.",
  agent: researcher,
});

const crew = new Crew({
  agents: [researcher],
  tasks: [task],
  process: Process.sequential,
});

async function main() {
  const result = await crew.kickoff();
  console.log(result);
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
  1. Add TypeScript and runtime scripts so the app is easy to run both locally and inside Docker. This keeps the container command simple and avoids baking build logic into the image entrypoint.
{
  "name": "crewai-docker-ts",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "tsx src/index.ts",
    "build": "tsc -p tsconfig.json",
    "start": "node dist/index.js"
  },
  "dependencies": {
    "crewai": "^0.0.0",
    "dotenv": "^16.4.5"
  },
  "devDependencies": {
    "@types/node": "^22.10.2",
    "tsx": "^4.19.2",
    "typescript": "^5.7.2"
  }
}
  1. Configure TypeScript for a clean production build. The important part is compiling ESM output into dist/, because Docker should run compiled JavaScript rather than source TypeScript.
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*.ts"]
}
  1. Create a production Dockerfile that installs dependencies, builds the app, and runs only the compiled output. Use a non-root user and keep the final image small enough for repeatable deployments.
FROM node:20-alpine AS builder
WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY tsconfig.json ./
COPY src ./src
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production

COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force

COPY --from=builder /app/dist ./dist

USER node
CMD ["node", "dist/index.js"]
  1. Add a .dockerignore so your image does not include local clutter or secrets. This reduces build time and prevents accidental leakage of files you do not want in production.
node_modules
dist
.env
.git
Dockerfile
docker-compose.yml
npm-debug.log
README.md
  1. Build and run the container with your API key injected at runtime. Do not bake secrets into the image; pass them through environment variables so you can rotate them without rebuilding.
docker build -t crewai-ts-agent .
docker run --rm \
  --env-file .env \
  crewai-ts-agent

Testing It

Run the app locally first with npm run dev to confirm your CrewAI task returns output before touching Docker. Then build the image and check that docker run prints the same result using the same .env file.

If it fails in Docker but works locally, inspect three things first: Node version mismatch, missing environment variables, and whether your TypeScript compiles cleanly into dist/. For deployment debugging, also inspect logs with docker logs <container_id> if you run it detached.

Next Steps

  • Split this into multiple agents and tasks with explicit handoffs.
  • Add structured outputs so downstream services can parse results reliably.
  • Move from a single container to Compose or Kubernetes when you need retries, scaling, or scheduled runs.

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides