Skip to content

Commit 6a1d7bc

Browse files
authored
Merge pull request #18 from veverkap/main
add docker support
2 parents 0a107bf + 800f78e commit 6a1d7bc

File tree

9 files changed

+520
-2
lines changed

9 files changed

+520
-2
lines changed

.dockerignore

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Ignore files not needed in the Docker build context
2+
3+
# Git
4+
.git
5+
.gitignore
6+
7+
# Documentation
8+
README.md
9+
.github/
10+
11+
# Python
12+
__pycache__/
13+
*.pyc
14+
*.pyo
15+
*.pyd
16+
.Python
17+
*.so
18+
.pytest_cache/
19+
.coverage
20+
htmlcov/
21+
venv/
22+
.env
23+
24+
# Node.js
25+
node_modules/
26+
npm-debug.log*
27+
yarn-debug.log*
28+
yarn-error.log*
29+
.yarn/
30+
31+
# Build outputs (will be copied from build stage)
32+
frontend/dist/
33+
frontend/node_modules/
34+
35+
# Application outputs
36+
outputs/
37+
logs/
38+
*.log
39+
40+
# IDE and editor files
41+
.vscode/
42+
.idea/
43+
*.swp
44+
*.swo
45+
*~
46+
47+
# OS files
48+
.DS_Store
49+
Thumbs.db
50+
51+
# Temporary files
52+
tmp/
53+
temp/
54+
*.tmp

.env.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GOOGLE_API_KEY=dummy_key_for_test

.github/workflows/README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# GitHub Actions Workflows
2+
3+
## Docker Build (`docker-build.yml`)
4+
5+
This workflow automatically builds and publishes the BrowserPilot Docker image when changes are merged to the main branch.
6+
7+
### Triggers
8+
- **Push to main branch**: When code is merged to main, specifically when these files change:
9+
- `Dockerfile`
10+
- `docker-compose*.yml`
11+
- `backend/**`
12+
- `frontend/**`
13+
- `requirements.txt`
14+
- **Pull Requests**: Builds (but doesn't push) images for PRs to test the build process
15+
- **Manual trigger**: Can be run manually from the GitHub Actions tab
16+
17+
### What it does
18+
1. **Builds the Docker image** using the multi-stage Dockerfile
19+
2. **Publishes to GitHub Container Registry** (`ghcr.io`) with multiple tags:
20+
- `latest` (for main branch)
21+
- `main` (branch name)
22+
- `main-<sha>` (commit SHA)
23+
3. **Multi-architecture support**: Builds for both `linux/amd64` and `linux/arm64`
24+
4. **Caching**: Uses GitHub Actions cache for faster builds
25+
5. **Security**: Generates build attestations for supply chain security
26+
27+
### Published Images
28+
The Docker images are published to:
29+
- `ghcr.io/veverkap/browserpilot:latest`
30+
- `ghcr.io/veverkap/browserpilot:main`
31+
- `ghcr.io/veverkap/browserpilot:main-<commit-sha>`
32+
33+
### Usage
34+
Users can pull and run the published images:
35+
36+
```bash
37+
# Pull the latest image
38+
docker pull ghcr.io/veverkap/browserpilot:latest
39+
40+
# Run with Docker
41+
docker run -p 8000:8000 -e GOOGLE_API_KEY=your_key ghcr.io/veverkap/browserpilot:latest
42+
43+
# Or use in docker-compose.yml
44+
services:
45+
browserpilot:
46+
image: ghcr.io/veverkap/browserpilot:latest
47+
# ... other config
48+
```
49+
50+
### Permissions Required
51+
The workflow needs the following permissions (automatically granted):
52+
- `contents: read` - To checkout the repository
53+
- `packages: write` - To publish to GitHub Container Registry
54+
55+
### Optional: Docker Hub Integration
56+
The workflow includes an optional step to update Docker Hub descriptions if you want to also publish to Docker Hub. To enable this:
57+
1. Add `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` secrets to your repository
58+
2. The workflow will automatically update the Docker Hub repository description using `README.docker.md`

.github/workflows/docker-build.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Build and Publish Docker Image
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
env:
10+
REGISTRY: ghcr.io
11+
IMAGE_NAME: ${{ github.repository }}
12+
13+
jobs:
14+
build-and-publish:
15+
runs-on: ubuntu-latest
16+
permissions:
17+
contents: read
18+
packages: write
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
24+
- name: Set up Docker Buildx
25+
uses: docker/setup-buildx-action@v3
26+
27+
- name: Log in to the Container Registry
28+
uses: docker/login-action@v3
29+
with:
30+
registry: ${{ env.REGISTRY }}
31+
username: ${{ github.actor }}
32+
password: ${{ secrets.GITHUB_TOKEN }}
33+
34+
- name: Extract metadata (tags, labels) for Docker
35+
id: meta
36+
uses: docker/metadata-action@v5
37+
with:
38+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
39+
tags: |
40+
type=ref,event=branch
41+
type=sha,prefix={{branch}}-
42+
type=raw,value=latest,enable={{is_default_branch}}
43+
44+
- name: Build and push Docker image
45+
uses: docker/build-push-action@v5
46+
with:
47+
context: .
48+
platforms: linux/amd64,linux/arm64
49+
push: true
50+
tags: ${{ steps.meta.outputs.tags }}
51+
labels: ${{ steps.meta.outputs.labels }}

Dockerfile

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Multi-stage Dockerfile for BrowserPilot
2+
# Stage 1: Build the React frontend
3+
FROM node:20-alpine AS frontend-builder
4+
5+
# Set working directory for frontend
6+
WORKDIR /app/frontend
7+
8+
# Copy package files
9+
COPY frontend/package*.json ./
10+
11+
# Install all dependencies (including dev dependencies needed for build)
12+
RUN npm config set strict-ssl false && npm install
13+
14+
# Copy frontend source code
15+
COPY frontend/ ./
16+
17+
# Build the frontend
18+
RUN npm run build
19+
20+
# Stage 2: Use Playwright's official Docker image with Python (Ubuntu-based)
21+
FROM mcr.microsoft.com/playwright/python:v1.53.0-jammy
22+
23+
# Set working directory
24+
WORKDIR /app
25+
26+
# Copy Python requirements and install dependencies
27+
COPY requirements.txt .
28+
# Install compatible versions of numpy and pandas for Python 3.10
29+
RUN pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --no-cache-dir \
30+
fastapi==0.111.0 \
31+
uvicorn[standard]==0.29.0 \
32+
playwright==1.53.0 \
33+
google-generativeai==0.5.0 \
34+
pydantic==2.7.1 \
35+
bs4==0.0.2 \
36+
lxml==5.2.1 \
37+
markdownify==0.11.6 \
38+
"numpy>=1.24.0,<2.3.0" \
39+
"pandas>=2.0.0,<2.3.0" \
40+
python-dateutil==2.9.0.post0 \
41+
pytz==2025.2 \
42+
tzdata==2025.2 \
43+
reportlab==4.4.2
44+
45+
# Copy backend source code
46+
COPY backend/ ./backend/
47+
48+
# Copy built frontend from the frontend-builder stage
49+
COPY --from=frontend-builder /app/frontend/dist ./frontend/
50+
51+
# Create outputs directory
52+
RUN mkdir -p outputs
53+
54+
# Set environment variables
55+
ENV PYTHONPATH=/app
56+
ENV PYTHONUNBUFFERED=1
57+
58+
# Expose the port the app runs on
59+
EXPOSE 8000
60+
61+
# Create a non-root user for security (the playwright image already has pwuser)
62+
RUN chown -R pwuser:pwuser /app
63+
USER pwuser
64+
65+
# Health check
66+
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
67+
CMD curl -f http://localhost:8000/ || exit 1
68+
69+
# Run the application
70+
CMD ["python", "-m", "uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000"]

0 commit comments

Comments
 (0)