diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..867c788 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,61 @@ +name: Build and Push Docker Images + +on: + push: + branches: [main] + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=sha,prefix= + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push backend image + uses: docker/build-push-action@v5 + with: + context: ./backend + push: true + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-backend:${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Build and push frontend image + uses: docker/build-push-action@v5 + with: + context: ./frontend + push: true + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-frontend:${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..22eebe2 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,25 @@ +FROM golang:1.21-alpine AS builder + +WORKDIR /app + +RUN apk add --no-cache git + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . + +RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server ./cmd/server + +FROM alpine:latest + +WORKDIR /app + +RUN apk add --no-cache ca-certificates tzdata + +COPY --from=builder /app/server . +COPY --from=builder /app/uploads ./uploads + +EXPOSE 8080 + +CMD ["./server"] diff --git a/backend/cmd/server/sale.db b/backend/cmd/server/sale.db new file mode 100644 index 0000000..1d93588 Binary files /dev/null and b/backend/cmd/server/sale.db differ diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..425b415 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3.8' + +services: + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: sale-backend + ports: + - "8080:8080" + volumes: + - ./backend/uploads:/app/uploads + - ./backend/sale.db:/app/sale.db + environment: + - DATABASE_PATH=sale.db + restart: unless-stopped + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + container_name: sale-frontend + ports: + - "80:80" + depends_on: + - backend + restart: unless-stopped diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..1ff99f4 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,19 @@ +FROM node:20-alpine AS builder + +WORKDIR /app + +COPY package*.json ./ +RUN npm ci + +COPY . . +RUN npm run build + +FROM nginx:alpine + +COPY --from=builder /app/dist /usr/share/nginx/html + +COPY nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 0000000..3d908db --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,27 @@ +server { + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /api/ { + proxy_pass http://backend:8080/api/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_cache_bypass $http_upgrade; + } + + location /uploads/ { + proxy_pass http://backend:8080/uploads/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } +}