Add Docker Compose support for frontend + backend - #7
Conversation
Co-authored-by: Rikul <1149512+Rikul@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds Docker containerization support for BillScan, enabling users to deploy the application using docker compose up. The implementation uses lightweight Alpine-based images with a multi-stage build for the frontend and includes data persistence via Docker volumes.
Key changes:
- Multi-stage frontend Dockerfile producing a ~30MB nginx-served static site
- Backend Dockerfile with node:22-alpine and configurable database location
- Docker Compose orchestration with persistent volume for SQLite data
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| Dockerfile | Frontend multi-stage build (Node.js build → nginx serve) |
| server/Dockerfile | Backend Node.js container with production dependencies |
| docker-compose.yml | Orchestrates frontend + backend services with data volume |
| nginx.conf | Configures SPA routing, API proxy, and upload limits |
| server/db.js | Adds DATA_DIR environment variable for volume-mounted database |
| .dockerignore | Excludes build artifacts and sensitive files from frontend image |
| server/.dockerignore | Excludes build artifacts and database from backend image |
| README.md | Documents Docker deployment workflow and architecture |
Critical issue: The Docker setup is missing environment variable configuration for AI service API keys, which are required for the application to function. API keys need to be passed as build arguments to the frontend (since Vite embeds them at build time) and configured in docker-compose.yml.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
| frontend: | ||
| build: | ||
| context: . | ||
| dockerfile: Dockerfile | ||
| ports: | ||
| - "8080:80" | ||
| depends_on: | ||
| - backend | ||
| environment: | ||
| - NODE_ENV=production | ||
| restart: unless-stopped |
There was a problem hiding this comment.
The Docker setup is missing environment variable configuration for AI service API keys. According to the README, BillScan requires API keys (e.g., GEMINI_API_KEY, OPENAI_API_KEY, etc.) to function. These need to be passed as build arguments to the frontend Dockerfile and configured in the docker-compose.yml.
Suggested fix for docker-compose.yml frontend service:
frontend:
build:
context: .
dockerfile: Dockerfile
args:
- GEMINI_API_KEY=${GEMINI_API_KEY}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- OLLAMA_HOST=${OLLAMA_HOST}
- OLLAMA_MODEL=${OLLAMA_MODEL}
- OPENAI_MODEL=${OPENAI_MODEL}
- ANTHROPIC_MODEL=${ANTHROPIC_MODEL}
- AI_SERVICE=${AI_SERVICE}And in the Dockerfile, add ARG declarations before the build step and pass them as environment variables during the build.
There was a problem hiding this comment.
Added build args for all AI service API keys to the frontend service in docker-compose.yml. Users can now configure API keys via a .env file, and they'll be passed as build arguments during the Docker build. Commit: e6d82ea
| depends_on: | ||
| - backend |
There was a problem hiding this comment.
[nitpick] The depends_on configuration only ensures the backend container starts before the frontend, but doesn't wait for the backend service to be ready to accept connections. This can cause issues during initial startup.
Consider adding a health check to the backend service and using condition: service_healthy:
backend:
# ... existing config ...
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/bills"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
frontend:
# ... existing config ...
depends_on:
backend:
condition: service_healthyThis ensures the frontend only starts after the backend is accepting requests.
There was a problem hiding this comment.
Added health check to the backend service with condition: service_healthy for the frontend's depends_on. The backend now waits for /api/bills to respond before the frontend starts. Commit: e6d82ea
| COPY package.json ./ | ||
|
|
||
| # Install dependencies | ||
| RUN npm install --production |
There was a problem hiding this comment.
[nitpick] Consider copying package-lock.json if it exists and using npm ci instead of npm install for more reproducible builds. While package-lock.json is currently in .gitignore, using npm ci when the lock file exists provides better build consistency.
Change line 7 to:
COPY package*.json ./And line 10 to:
RUN if [ -f package-lock.json ]; then npm ci --production; else npm install --production; fi| COPY package.json ./ | |
| # Install dependencies | |
| RUN npm install --production | |
| COPY package*.json ./ | |
| # Install dependencies | |
| RUN if [ -f package-lock.json ]; then npm ci --production; else npm install --production; fi |
There was a problem hiding this comment.
Updated to use COPY package*.json ./ and conditional npm ci --production when a lock file exists. Commit: e6d82ea
| ```bash | ||
| docker compose up --build | ||
| ``` | ||
|
|
There was a problem hiding this comment.
The Docker Quick Start section does not explain how to configure required API keys. Without API key configuration, the application will not function.
Add a note after line 59 explaining how to pass environment variables:
**Important:** Before running, create a `.env` file in the project root with your API keys:
```bash
# .env file
GEMINI_API_KEY=your_key_here
AI_SERVICE=gemini
# Add other keys as needed (see AI Service Configuration)Then Docker Compose will automatically load these variables.
```suggestion
**Important:** Before running, create a `.env` file in the project root with your API keys:
```bash
# .env file
GEMINI_API_KEY=your_key_here
AI_SERVICE=gemini
# Add other keys as needed (see AI Service Configuration)
Then Docker Compose will automatically load these variables.
There was a problem hiding this comment.
Added step 1 to the Docker Quick Start section explaining how to create a .env file with API keys before running docker compose up. Commit: e6d82ea
There was a problem hiding this comment.
This was already addressed in commit e6d82ea. The README now includes step 1 in the Docker Quick Start section that explains how to create a .env file with API keys before running docker compose up. See lines 57-63 in README.md.
| COPY package.json ./ | ||
|
|
||
| # Install dependencies | ||
| RUN npm install |
There was a problem hiding this comment.
[nitpick] Consider copying package-lock.json if it exists and using npm ci instead of npm install for more reproducible builds. While package-lock.json is currently in .gitignore, using npm ci when the lock file exists provides better build consistency.
Change line 7 to:
COPY package*.json ./And line 10 to:
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi| COPY package.json ./ | |
| # Install dependencies | |
| RUN npm install | |
| COPY package*.json ./ | |
| # Install dependencies | |
| RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi |
There was a problem hiding this comment.
Updated to use COPY package*.json ./ and conditional npm ci when a lock file exists. Commit: e6d82ea
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
… npm ci support Co-authored-by: Rikul <1149512+Rikul@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| healthcheck: | ||
| test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/bills"] |
There was a problem hiding this comment.
Fix backend healthcheck command for alpine base
The backend healthcheck is defined as wget --no-verbose --tries=1 --spider http://localhost:3000/api/bills, but the backend image is built on node:22-alpine (see server/Dockerfile line 2), which ships BusyBox wget that lacks the --no-verbose flag. BusyBox exits with an error on that option, so the healthcheck fails even when the API is healthy, keeping the backend in an unhealthy state and preventing the frontend from starting because depends_on waits for a healthy backend.
Useful? React with 👍 / 👎.
Adds containerized deployment via
docker compose upwith lightweight Alpine-based images.Changes
.envfileDATA_DIRenv var support for volume-mounted databaseUsage
.envfile with your API keys:Data persists in
billscan-datavolume across restarts.Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.