|
| 1 | +# Docker Setup Documentation |
| 2 | + |
| 3 | +## Issue: Infinite Restart Loop |
| 4 | + |
| 5 | +This document explains the Docker configuration issues that caused infinite restart loops and how they were resolved. |
| 6 | + |
| 7 | +## Problems Identified |
| 8 | + |
| 9 | +### 1. Import Path Issue |
| 10 | +**Location:** `src/common/color.js:3` |
| 11 | + |
| 12 | +**Problem:** The import path was pointing to `../../themes/index.js` (root level) but themes directory was moved to `src/themes/` |
| 13 | + |
| 14 | +**Solution:** |
| 15 | +```javascript |
| 16 | +// Before |
| 17 | +import { themes } from "../../themes/index.js"; |
| 18 | + |
| 19 | +// After |
| 20 | +import { themes } from "../themes/index.js"; |
| 21 | +``` |
| 22 | + |
| 23 | +### 2. Missing Dependencies |
| 24 | +**Location:** `src/package.json` |
| 25 | + |
| 26 | +**Problem:** The src/package.json only had devDependencies, missing all runtime dependencies needed by the application. |
| 27 | + |
| 28 | +**Solution:** Added production dependencies: |
| 29 | +```json |
| 30 | +"dependencies": { |
| 31 | + "axios": "^1.13.1", |
| 32 | + "dotenv": "^17.2.3", |
| 33 | + "emoji-name-map": "^2.0.3", |
| 34 | + "github-username-regex": "^1.0.0", |
| 35 | + "word-wrap": "^1.2.5" |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +### 3. Wrong Docker Build Context |
| 40 | +**Location:** `docker-compose.yml` |
| 41 | + |
| 42 | +**Problem:** Build context was set to `./src` but the actual server file (`express.js`) and `api/` directory are at the root level. |
| 43 | + |
| 44 | +**Solution:** |
| 45 | +```yaml |
| 46 | +# Before |
| 47 | +build: |
| 48 | + context: ./src |
| 49 | + dockerfile: Dockerfile |
| 50 | + |
| 51 | +# After |
| 52 | +build: |
| 53 | + context: . |
| 54 | + dockerfile: Dockerfile |
| 55 | +``` |
| 56 | +
|
| 57 | +### 4. Wrong Entry Point |
| 58 | +**Location:** `Dockerfile` CMD instruction |
| 59 | + |
| 60 | +**Problem:** Container was trying to run `src/index.js` which only exports modules, not the actual Express server. |
| 61 | + |
| 62 | +**Solution:** |
| 63 | +```dockerfile |
| 64 | +# Before |
| 65 | +CMD ["node", "index.js"] |
| 66 | +
|
| 67 | +# After |
| 68 | +CMD ["node", "express.js"] |
| 69 | +``` |
| 70 | + |
| 71 | +### 5. Node Version Mismatch |
| 72 | +**Location:** `Dockerfile` |
| 73 | + |
| 74 | +**Problem:** Dockerfile used Node 18, but `package.json` requires Node >=22 |
| 75 | + |
| 76 | +**Solution:** |
| 77 | +```dockerfile |
| 78 | +# Before |
| 79 | +FROM node:18-alpine AS base |
| 80 | +
|
| 81 | +# After |
| 82 | +FROM node:22-alpine AS base |
| 83 | +``` |
| 84 | + |
| 85 | +### 6. Husky Prepare Script |
| 86 | +**Location:** `Dockerfile` npm install step |
| 87 | + |
| 88 | +**Problem:** The `prepare` script tries to run `husky` (git hooks) during Docker build, which fails and isn't needed in containers. |
| 89 | + |
| 90 | +**Solution:** |
| 91 | +```dockerfile |
| 92 | +npm ci --omit=dev --ignore-scripts |
| 93 | +``` |
| 94 | + |
| 95 | +## Final Working Configuration |
| 96 | + |
| 97 | +### Dockerfile Structure |
| 98 | +```dockerfile |
| 99 | +FROM node:22-alpine AS base |
| 100 | +
|
| 101 | +# Dependencies stage - installs only production dependencies |
| 102 | +FROM base AS deps |
| 103 | +RUN apk add --no-cache libc6-compat |
| 104 | +WORKDIR /app |
| 105 | +COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./ |
| 106 | +RUN npm ci --omit=dev --ignore-scripts |
| 107 | +
|
| 108 | +# Builder stage - prepares application files |
| 109 | +FROM base AS builder |
| 110 | +WORKDIR /app |
| 111 | +COPY --from=deps /app/node_modules ./node_modules |
| 112 | +COPY . . |
| 113 | +
|
| 114 | +# Runner stage - production image |
| 115 | +FROM base AS runner |
| 116 | +WORKDIR /app |
| 117 | +ENV NODE_ENV=production |
| 118 | +COPY --from=builder /app/package.json ./package.json |
| 119 | +COPY --from=builder /app/node_modules ./node_modules |
| 120 | +COPY --from=builder /app/src ./src |
| 121 | +COPY --from=builder /app/api ./api |
| 122 | +COPY --from=builder /app/themes ./themes |
| 123 | +COPY --from=builder /app/express.js ./express.js |
| 124 | +
|
| 125 | +EXPOSE 3000 |
| 126 | +CMD ["node", "express.js"] |
| 127 | +``` |
| 128 | + |
| 129 | +## Testing the Setup |
| 130 | + |
| 131 | +### Start the container |
| 132 | +```bash |
| 133 | +docker compose up -d |
| 134 | +``` |
| 135 | + |
| 136 | +### Check container status |
| 137 | +```bash |
| 138 | +docker ps --filter "name=github-readme-stats" |
| 139 | +``` |
| 140 | + |
| 141 | +### View logs |
| 142 | +```bash |
| 143 | +docker logs github-readme-stats |
| 144 | +``` |
| 145 | + |
| 146 | +Expected output: |
| 147 | +``` |
| 148 | +[[email protected]] injecting env (0) from .env |
| 149 | +Server running on port 3000 |
| 150 | +``` |
| 151 | + |
| 152 | +### Test the API |
| 153 | +```bash |
| 154 | +curl "http://localhost:3000/api/?username=YOUR_GITHUB_USERNAME" |
| 155 | +``` |
| 156 | + |
| 157 | +## Deployment Notes |
| 158 | + |
| 159 | +Before deploying to VPS: |
| 160 | + |
| 161 | +1. **Environment Variables:** Create a `.env` file with your GitHub token: |
| 162 | + ``` |
| 163 | + PAT_1=your_github_personal_access_token |
| 164 | + ``` |
| 165 | + |
| 166 | +2. **Port Configuration:** Update `docker-compose.yml` if you need a different port: |
| 167 | + ```yaml |
| 168 | + ports: |
| 169 | + - "8080:3000" # Maps host port 8080 to container port 3000 |
| 170 | + ``` |
| 171 | + |
| 172 | +3. **Domain Configuration:** Update Traefik labels in `docker-compose.yml`: |
| 173 | + ```yaml |
| 174 | + - "traefik.http.routers.github-readme-stats.rule=Host(`your-domain.com`)" |
| 175 | + ``` |
| 176 | +
|
| 177 | +4. **SSL/TLS:** Ensure your Traefik setup has a valid cert resolver configured |
| 178 | +
|
| 179 | +## Troubleshooting |
| 180 | +
|
| 181 | +### Container keeps restarting |
| 182 | +```bash |
| 183 | +# Check logs immediately |
| 184 | +docker logs github-readme-stats --tail 50 |
| 185 | + |
| 186 | +# Common issues: |
| 187 | +# - Missing dependencies: Check package.json |
| 188 | +# - Module not found: Check import paths |
| 189 | +# - Port conflicts: Check if port 3000 is available |
| 190 | +``` |
| 191 | + |
| 192 | +### Port already in use |
| 193 | +```bash |
| 194 | +# Windows PowerShell |
| 195 | +Get-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess |
| 196 | +Stop-Process -Id <PID> -Force |
| 197 | + |
| 198 | +# Linux/Mac |
| 199 | +lsof -ti:3000 | xargs kill -9 |
| 200 | +``` |
| 201 | + |
| 202 | +## File Structure |
| 203 | +``` |
| 204 | +github-readme-stats/ |
| 205 | +├── api/ # API endpoints |
| 206 | +├── src/ # Source code |
| 207 | +│ ├── common/ # Common utilities |
| 208 | +│ ├── cards/ # Card generators |
| 209 | +│ ├── fetchers/ # Data fetchers |
| 210 | +│ └── themes/ # Theme definitions |
| 211 | +├── themes/ # Root themes (legacy) |
| 212 | +├── express.js # Express server (entry point) |
| 213 | +├── Dockerfile # Docker configuration |
| 214 | +├── docker-compose.yml # Docker Compose setup |
| 215 | +└── package.json # Dependencies |
| 216 | +``` |
0 commit comments