diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000..155986e --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,62 @@ +name: Docker Build and Push + +on: + push: + branches: [ "main", "master" ] + paths-ignore: + - 'docs/**' + - '**.md' + pull_request: + branches: [ "main", "master" ] + paths-ignore: + - 'docs/**' + - '**.md' + +env: + REGISTRY: ghcr.io + # Use message-nest to match release workflow naming, or use ${{ github.repository }} for default + IMAGE_NAME: message-nest + +jobs: + build: + 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 the Container registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' }} + type=ref,event=branch + type=ref,event=pr + type=sha + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 2268922..81b41fa 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -37,7 +37,7 @@ dockers: - image_templates: - "docker.io/engigu/{{ .Env.DOCKER_IMAGE_NAME }}:{{ .Version }}-amd64" - "ghcr.io/engigu/{{ .Env.DOCKER_IMAGE_NAME }}:{{ .Version }}-amd64" - dockerfile: Dockerfile + dockerfile: Dockerfile.release extra_files: - LICENSE - README.md @@ -56,7 +56,7 @@ dockers: - "docker.io/engigu/{{ .Env.DOCKER_IMAGE_NAME }}:{{ .Version }}-arm64v8" - "ghcr.io/engigu/{{ .Env.DOCKER_IMAGE_NAME }}:{{ .Version }}-arm64v8" goarch: arm64 - dockerfile: Dockerfile + dockerfile: Dockerfile.release extra_files: - LICENSE - README.md @@ -76,7 +76,7 @@ dockers: - "ghcr.io/engigu/{{ .Env.DOCKER_IMAGE_NAME }}:{{ .Version }}-armv7" goarch: arm goarm: 7 - dockerfile: Dockerfile + dockerfile: Dockerfile.release extra_files: - LICENSE - README.md diff --git a/Dockerfile b/Dockerfile index 51f6fa3..c6165bd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,64 @@ -FROM debian:latest +# Stage 1: Build Frontend +FROM node:20-alpine AS frontend-builder + +WORKDIR /web + +# Copy package files first for caching +COPY web/package*.json ./ +COPY web/tsconfig*.json ./ +COPY web/vite.config.ts ./ +COPY web/index.html ./ + +# Install dependencies +RUN npm install + +# Copy source code +COPY web/ ./ + +# Build frontend +RUN npm run build + +# Stage 2: Build Backend +FROM golang:1.24 AS backend-builder + +WORKDIR /app + +# Copy Go module files +COPY go.mod go.sum ./ +RUN go mod download + +# Copy source code +COPY . . + +# Copy frontend build artifacts to the location expected by go:embed +# The embed directive in main.go is //go:embed web/dist/* +COPY --from=frontend-builder /web/dist ./web/dist + +# Build the binary +# CGO_ENABLED=0 for static binary +RUN CGO_ENABLED=0 GOOS=linux go build -o Message-Nest main.go + +# Stage 3: Runtime +FROM debian:stable-slim ENV TZ=Asia/Shanghai -RUN apt update \ - && apt install -y ca-certificates \ - && update-ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -COPY ./ /app/ +RUN apt-get update \ + && apt-get install -y ca-certificates tzdata \ + && rm -rf /var/lib/apt/lists/* WORKDIR /app + +# Copy binary +COPY --from=backend-builder /app/Message-Nest . + +# Copy configuration directory (contains app.example.ini) +COPY --from=backend-builder /app/conf ./conf + +# Copy other necessary files +COPY --from=backend-builder /app/LICENSE . +COPY --from=backend-builder /app/README.md . + EXPOSE 8000 -CMD ["/app/Message-Nest"] - +CMD ["./Message-Nest"] diff --git a/Dockerfile.release b/Dockerfile.release new file mode 100644 index 0000000..51f6fa3 --- /dev/null +++ b/Dockerfile.release @@ -0,0 +1,16 @@ +FROM debian:latest + +ENV TZ=Asia/Shanghai + +RUN apt update \ + && apt install -y ca-certificates \ + && update-ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +COPY ./ /app/ + +WORKDIR /app +EXPOSE 8000 + +CMD ["/app/Message-Nest"] +