UXDL Docs

Docker

Multi-stage Dockerfile, compose for local, and image publishing.

Express + TypeScript services ship as a single Node.js container. Socket.io runs on the same HTTP server — no separate worker process.

Dockerfile

dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
 
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 appuser
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER appuser
EXPOSE 4000
HEALTHCHECK CMD wget -qO- http://localhost:4000/health || exit 1
CMD ["node", "dist/server.js"]

Ensure tsconfig.json outputs to dist/ and your entry is src/server.ts (includes both Express and Socket.io).

Build and run

bash
docker build -t backend-api:local .
docker run -p 4000:4000 --env-file .env.local backend-api:local
curl http://localhost:4000/health

Publish to ECR

Images are pushed to Amazon ECR before ECS deployment:

bash
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $ECR_REPO
docker tag backend-api:local $ECR_REPO:$TAG
docker push $ECR_REPO:$TAG

See AWS ECS for task definitions and service updates.

docker-compose (local full stack)

yaml
services:
  api:
    build: .
    ports: ["4000:4000"]
    env_file: .env.local
    depends_on: [postgres]
    environment:
      DATABASE_URL: postgres://app:app@postgres:5432/app
      CORS_ORIGIN: http://localhost:3000
 
  postgres:
    image: postgres:16-alpine
    ports: ["5432:5432"]
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: app
      POSTGRES_DB: app
    volumes: [postgres_data:/var/lib/postgresql/data]
 
  # Optional — only if the service uses MongoDB
  mongo:
    image: mongo:7
    ports: ["27017:27017"]
    volumes: [mongo_data:/data/db]
 
volumes:
  postgres_data:
  mongo_data:

Remove the mongo service if your service uses PostgreSQL only.

Health endpoint

typescript
// src/routes/health.routes.ts
router.get("/health", (_req, res) => {
  res.json({ status: "ok", uptime: process.uptime() });
});

Official documentation