Skip to content

Commit

Permalink
Feat/unified docker (#5)
Browse files Browse the repository at this point in the history
* feat: restructure Docker setup to build backend and frontend in separate stages, update nginx configuration for API proxying

* feat: enhance GitHub Actions workflow to support pull requests and dynamic image tagging

* feat: update Docker configuration to set default VITE_API_URL and adjust service build context, improve network naming

* fix: correct syntax for VITE_API_URL argument in Dockerfile

* docs: update README to streamline sections and improve clarity; remove outdated Docker deployment details
  • Loading branch information
kek-Sec authored Dec 19, 2024
1 parent cf75db3 commit c8850f3
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 230 deletions.
62 changes: 15 additions & 47 deletions .github/workflows/build-and-push-docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

permissions:
Expand All @@ -12,7 +15,7 @@ permissions:

jobs:
build-backend:
name: 🛠️ Build and Push Backend
name: 🛠️ Build and Push
runs-on: ubuntu-latest
steps:
- name: 🚀 Checkout Code
Expand All @@ -22,6 +25,13 @@ jobs:
run: |
echo "GIT_COMMIT_SHA=${{ github.sha }}" >> $GITHUB_ENV
echo "GIT_VERSION=${{ github.ref_name }}" >> $GITHUB_ENV
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/main" ]]; then
echo "IMAGE_TAG=latest" >> $GITHUB_ENV
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "IMAGE_TAG=rc-${{ github.event.pull_request.number }}" >> $GITHUB_ENV
else
echo "IMAGE_TAG=unknown" >> $GITHUB_ENV
fi
- name: 🛠️ Set up Docker Buildx
uses: docker/setup-buildx-action@v2
Expand All @@ -33,63 +43,21 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.TOKEN }}

- name: 📦 Build and Push Backend Image
- name: 📦 Build and Push Image
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
push: true
tags: ghcr.io/kek-sec/gopherdrop:backend-latest
annotations: |
org.opencontainers.image.description=Backend API for GopherDrop, a secure one-time secret sharing service
build-args: |
GIT_COMMIT_SHA=${{ env.GIT_COMMIT_SHA }}
GIT_VERSION=${{ env.GIT_VERSION }}
labels: |
org.opencontainers.image.source=https://github.com/kek-sec/gopherdrop
org.opencontainers.image.revision=${{ env.GIT_COMMIT_SHA }}
org.opencontainers.image.version=${{ env.GIT_VERSION }}
cache-from: type=registry,ref=ghcr.io/kek-sec/gopherdrop:backend-latest
cache-to: type=inline

build-ui:
name: 🖥️ Build and Push UI
runs-on: ubuntu-latest
steps:
- name: 🚀 Checkout Code
uses: actions/checkout@v4

- name: 🏗️ Set Build Variables
run: |
echo "GIT_COMMIT_SHA=${{ github.sha }}" >> $GITHUB_ENV
echo "GIT_VERSION=${{ github.ref_name }}" >> $GITHUB_ENV
- name: 🛠️ Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: 🔐 Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.TOKEN }}

- name: 📦 Build and Push UI Image
uses: docker/build-push-action@v4
with:
context: ./ui
file: ./ui/Dockerfile
push: true
tags: ghcr.io/kek-sec/gopherdrop:ui-latest
tags: ghcr.io/kek-sec/gopherdrop:${{ env.IMAGE_TAG }}
annotations: |
org.opencontainers.image.description=UI for GopherDrop, a secure one-time secret sharing service
org.opencontainers.image.description=GopherDrop, a secure one-time secret sharing service
build-args: |
GIT_COMMIT_SHA=${{ env.GIT_COMMIT_SHA }}
GIT_VERSION=${{ env.GIT_VERSION }}
VITE_API_URL=http://app:8080
labels: |
org.opencontainers.image.source=https://github.com/kek-sec/gopherdrop
org.opencontainers.image.revision=${{ env.GIT_COMMIT_SHA }}
org.opencontainers.image.version=${{ env.GIT_VERSION }}
cache-from: type=registry,ref=ghcr.io/kek-sec/gopherdrop:ui-latest
cache-from: type=registry,ref=ghcr.io/kek-sec/gopherdrop:latest
cache-to: type=inline
47 changes: 33 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Stage 1: Build the Go binary
FROM golang:1.22-alpine AS builder
# Stage 1: Build the Go Backend
FROM golang:1.22-alpine AS backend-builder

WORKDIR /app
COPY . .
Expand All @@ -16,30 +16,49 @@ RUN if [ "$DEBUG" = "true" ]; then \
go mod download && go build -o server ./cmd/server/main.go; \
fi

# Stage 2: Create the production image
FROM alpine:3.18
# Stage 2: Build the Vue.js Frontend
FROM node:18-alpine AS frontend-builder

WORKDIR /app
COPY --from=builder /app/server .
COPY ui/package.json ui/package-lock.json ./
RUN npm install --legacy-peer-deps

ARG VITE_API_URL="/api"
ENV VITE_API_URL=${VITE_API_URL}

COPY ui ./
RUN npm run build

# Stage 3: Combine Backend and Frontend into a Single Image
FROM nginx:alpine

# Add OCI Image Spec labels
LABEL org.opencontainers.image.title="GopherDrop Backend" \
org.opencontainers.image.description="Backend for GopherDrop, a secure one-time secret sharing service" \
ARG GIT_COMMIT_SHA
ARG GIT_VERSION

LABEL org.opencontainers.image.title="GopherDrop" \
org.opencontainers.image.description="GopherDrop - Secure one-time secret sharing service" \
org.opencontainers.image.source="https://github.com/kek-Sec/gopherdrop" \
org.opencontainers.image.revision="${GIT_COMMIT_SHA}" \
org.opencontainers.image.version="${GIT_VERSION}" \
org.opencontainers.image.url="https://github.com/kek-Sec/gopherdrop" \
org.opencontainers.image.documentation="https://github.com/kek-Sec/gopherdrop" \
org.opencontainers.image.licenses="MIT"

# Environment variables
ENV LISTEN_ADDR=:8080
ENV STORAGE_PATH=/app/storage
# Copy the Go server binary
COPY --from=backend-builder /app/server /app/server

# Copy the frontend static files
COPY --from=frontend-builder /app/dist /usr/share/nginx/html

# Copy Nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Create the storage directory
# Create the storage directory for the backend
RUN mkdir -p /app/storage

EXPOSE 8080
# Expose the ports for Nginx and the Go server
EXPOSE 80 8080

# Command to run the server
CMD ["/app/server"]
# Run both the Go server and Nginx using a simple script
CMD ["/bin/sh", "-c", "/app/server & nginx -g 'daemon off;'"]
84 changes: 16 additions & 68 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ GopherDrop is a secure, self-hostable REST API and UI for sharing encrypted one-

1. [Features](#-features)
2. [Installation](#-installation)
3. [Build and Run](#-build-and-run)
4. [Configuration](#-configuration)
5. [Endpoints](#-endpoints)
3. [Build and Run](#-build-and-run)
4. [Configuration](#-configuration)
5. [Endpoints](#-endpoints)
6. [Docker Deployment](#-docker-deployment)
7. [Persistence](#-persistence)
8. [Reverse Proxy Support](#-reverse-proxy-support)
9. [Contributing](#-contributing)
10. [License](#-license)
11. [Community and Support](#-community-and-support)
7. [Contributing](#-contributing)
8. [License](#-license)
9. [Community and Support](#-community-and-support)

---

Expand All @@ -35,6 +33,15 @@ GopherDrop is a secure, self-hostable REST API and UI for sharing encrypted one-
- **Dockerized Deployment**: Simple setup with Docker and Docker Compose.
- **Production and Debug Modes**: Easily switch between production and debug builds.


---

## 🐳 **Docker Deployment**

### **Production `docker-compose.yml`**

> docker-compose.prod.sample.yaml
---

## 📥 **Installation**
Expand All @@ -50,12 +57,11 @@ GopherDrop is a secure, self-hostable REST API and UI for sharing encrypted one-
git clone https://github.com/kek-Sec/gopherdrop.git
cd gopherdrop
```

---

## 🛠️ **Build and Run**

### **Production Setup**
### **Local Setup**

To build and run GopherDrop in production mode:

Expand Down Expand Up @@ -85,13 +91,6 @@ make down
make test
```

### **Access the Application**

- **UI**: `http://localhost:8081`
- **API**: `http://localhost:8080`

---

## ⚙️ **Configuration**

### **Using `.env` File**
Expand Down Expand Up @@ -135,57 +134,6 @@ MAX_FILE_SIZE=10485760
| `GET` | `/send/:id` | Retrieve a send by its hash |
| `GET` | `/send/:id/check` | Check if a send requires a password |

### **Example: Create a Send**

```bash
curl -X POST http://localhost:8080/send \
-F "type=text" \
-F "data=This is a secret message" \
-F "password=mysecurepassword"
```

---

## 🐳 **Docker Deployment**

### **Production `docker-compose.yml`**

> clone repository
> docker-compose.prod.sample.yaml
---

## 🌐 **Reverse Proxy Support**

### **Nginx Configuration**

Create a `nginx.conf`:

```nginx
server {
listen 80;
location / {
proxy_pass http://frontend:80;
}
location /api/ {
proxy_pass http://backend:8080/;
}
}
```

### **Traefik Configuration**

Add this to `docker-compose.yml`:

```yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.gopherdrop.rule=Host(`example.com`)"
- "traefik.http.services.gopherdrop.loadbalancer.server.port=8080"
```

---

Expand Down
30 changes: 7 additions & 23 deletions docker-compose.prod.sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ services:
timeout: 5s
retries: 5
networks:
- goepher_net
- gophernet

app:
image: ghcr.io/kek-sec/gopherdrop:backend-latest
image: ghcr.io/kek-sec/gopherdrop:latest
container_name: gopherdrop_app
environment:
DB_HOST: db
Expand All @@ -29,30 +29,14 @@ services:
LISTEN_ADDR: :8080
STORAGE_PATH: /app/storage
MAX_FILE_SIZE: 10485760
volumes:
- ./app_storage:/app/storage
depends_on:
db:
condition: service_healthy
volumes:
- ./app_storage:/app/storage
networks:
- goepher_net
ports:
- "8080:8080"

ui:
build:
context: ./ui
dockerfile: Dockerfile
args:
VITE_API_URL: "http://app:8080"
container_name: gopherdrop_ui
depends_on:
- app
networks:
- goepher_net
ports:
- "8081:80"
- gophernet

networks:
goepher_net:
external: true
gophernet:
external: true
Loading

0 comments on commit c8850f3

Please sign in to comment.