# Railway Docker Deploy

> Deploy a Next.js application to Railway using Docker with multi-stage builds. Use when the user wants to deploy to Railway, create a Dockerfile for a Node.js/Next.js app, set up CI/CD with Railway CLI, or troubleshoot Railway deployment issues.

- Skill: `ph13917403910/railway-docker-deploy` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ph13917403910/railway-docker-deploy`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ph13917403910/railway-docker-deploy/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: PH13917403910 (https://skillmd.com/u/ph13917403910)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/ph13917403910/railway-docker-deploy

---


# Railway + Docker Deployment

## Prerequisites

```bash
# Install Railway CLI (macOS)
brew install railway

# Login
railway login

# Link to existing project or create new
railway link        # existing
railway init        # new
```

## Multi-stage Dockerfile

Optimized for Next.js with custom server:

```dockerfile
# ── Stage 1: Install dependencies ──
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

# ── Stage 2: Build ──
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

# ── Stage 3: Run ──
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production

RUN addgroup --system --gid 1001 nodejs && \
    adduser --system --uid 1001 nextjs

COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./
COPY --from=builder /app/server.mjs ./
COPY --from=builder /app/next.config.ts ./

USER nextjs

ENV PORT=3000
EXPOSE 3000
CMD ["node", "server.mjs"]
```

If not using a custom server, replace the last line with `CMD ["npm", "start"]`.

## .railwayignore

Prevents uploading unnecessary files (reduces deploy time):

```
node_modules/
.next/
.env*.local
*.tsbuildinfo
.git/
```

## .dockerignore

```
node_modules
.next
.git
*.md
.env*.local
```

## Deploy

```bash
# Deploy and detach (non-blocking)
railway up --detach

# Watch logs
railway logs -f
```

## Environment variables

Set via Railway dashboard or CLI:

```bash
railway variables set NODE_ENV=production
railway variables set ADMIN_PWD=your-secret
railway variables set PORT=3000
```

Railway auto-injects `PORT` — your server must listen on `process.env.PORT`.

## Troubleshooting

### Upload timeout

If `railway up` times out during upload:

1. **Check `.railwayignore`** — make sure `node_modules/`, `.next/`, `.git/` are excluded
2. **Check large files** — videos/assets in `public/` add upload time
3. **Local proxy interference** — if you use a proxy (e.g. Clash, Surge), it can intercept Railway CLI uploads. Bypass with:

```bash
HTTP_PROXY="" HTTPS_PROXY="" ALL_PROXY="" \
http_proxy="" https_proxy="" all_proxy="" no_proxy="*" \
railway up --detach
```

### Build failures

- Check `railway logs` for the specific error
- Ensure `Dockerfile` copies all files needed at runtime
- Verify `ENV PORT` matches what your server listens on

### Video/large assets

For large static files (videos, images):

- **Option A**: Serve from `public/` — simple but increases Docker image and deploy time
- **Option B**: Use external storage (S3, R2, CDN) — better for production
- Compress videos before adding to `public/`:

```bash
ffmpeg -i input.mp4 -c:v libx264 -crf 26 -preset slow \
  -c:a aac -b:a 128k -movflags +faststart output.mp4
```

## Railway-specific notes

- Railway provides HTTPS automatically (no cert setup needed)
- Custom domains: `railway domain` to get a `*.up.railway.app` URL, or add custom domain in dashboard
- Railway uses Nixpacks by default; having a `Dockerfile` overrides this
- Healthcheck: Railway pings your app — ensure it responds to HTTP on `PORT`

## Checklist

- [ ] `Dockerfile` with multi-stage build (deps → builder → runner)
- [ ] `.railwayignore` excludes `node_modules/`, `.next/`, `.git/`
- [ ] `.dockerignore` excludes dev-only files
- [ ] Server listens on `process.env.PORT`
- [ ] Environment variables set via Railway dashboard/CLI
- [ ] Large assets compressed or moved to external storage
- [ ] Tested locally with `docker build -t app . && docker run -p 3000:3000 app`

