add docker configuration and gitea workflow for automated image builds
Introduce a multi-stage Dockerfile, docker-compose setup, and a Gitea Actions workflow to automate building and pushing images to the registry. The configuration includes an entrypoint script for persistent logging and a .dockerignore to optimize the build context.
This commit is contained in:
31
.dockerignore
Normal file
31
.dockerignore
Normal file
@@ -0,0 +1,31 @@
|
||||
# Build artifacts
|
||||
build/
|
||||
tmp/
|
||||
*.exe
|
||||
|
||||
# Test artifacts
|
||||
*.out
|
||||
*.test
|
||||
coverage.*
|
||||
*.coverprofile
|
||||
|
||||
# Dev tooling
|
||||
.air.toml
|
||||
|
||||
# Secrets & local config
|
||||
.env
|
||||
|
||||
# Version control
|
||||
.git/
|
||||
.gitignore
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Docs
|
||||
*.md
|
||||
LICENSE
|
||||
|
||||
# Claude
|
||||
.claude/
|
||||
55
.gitea/workflows/docker.yml
Normal file
55
.gitea/workflows/docker.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
name: Build & Publish Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Strip "https://" from the server URL to get the registry hostname
|
||||
- name: Resolve registry host
|
||||
id: reg
|
||||
run: |
|
||||
host=$(echo "${{ gitea.server_url }}" | sed 's|https://||;s|http://||;s|/||g')
|
||||
echo "host=$host" >> $GITHUB_OUTPUT
|
||||
echo "image=$host/${{ gitea.repository }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ steps.reg.outputs.host }}
|
||||
username: ${{ secrets.REGISTRY_USER }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ steps.reg.outputs.image }}
|
||||
tags: |
|
||||
type=raw,value=latest,enable=${{ gitea.ref == 'refs/heads/main' }}
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha,prefix=sha-,format=short
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -24,8 +24,9 @@ profile.cov
|
||||
go.work
|
||||
go.work.sum
|
||||
|
||||
# env file
|
||||
# env files
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# Editor/IDE
|
||||
.idea/
|
||||
|
||||
29
Dockerfile
Normal file
29
Dockerfile
Normal file
@@ -0,0 +1,29 @@
|
||||
# --- Build stage ---
|
||||
FROM golang:alpine AS builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o emly-api .
|
||||
|
||||
# --- Runtime stage ---
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk --no-cache add ca-certificates tzdata
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /build/emly-api .
|
||||
COPY --from=builder /build/internal/database/schema ./internal/database/schema
|
||||
COPY --from=builder /build/internal/handlers/templates ./internal/handlers/templates
|
||||
COPY docker/entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
RUN mkdir -p /logs
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
25
docker-compose.yml
Normal file
25
docker-compose.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
services:
|
||||
api:
|
||||
build: .
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${PORT:-8080}:8080"
|
||||
environment:
|
||||
PORT: ${PORT:-8080}
|
||||
DB_DSN: ${DB_DSN}
|
||||
DATABASE_NAME: ${DATABASE_NAME}
|
||||
API_KEY: ${API_KEY}
|
||||
ADMIN_KEY: ${ADMIN_KEY}
|
||||
DB_MAX_OPEN_CONNS: ${DB_MAX_OPEN_CONNS:-25}
|
||||
DB_MAX_IDLE_CONNS: ${DB_MAX_IDLE_CONNS:-5}
|
||||
DB_CONN_MAX_LIFETIME: ${DB_CONN_MAX_LIFETIME:-5}
|
||||
volumes:
|
||||
- logs:/logs
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "5"
|
||||
|
||||
volumes:
|
||||
logs:
|
||||
8
docker/entrypoint.sh
Normal file
8
docker/entrypoint.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
mkdir -p /logs
|
||||
|
||||
# Run the app and tee output to both stdout (for `docker logs`) and a
|
||||
# persistent log file inside the mounted volume.
|
||||
exec ./emly-api 2>&1 | tee -a /logs/app.log
|
||||
@@ -15,7 +15,10 @@ import (
|
||||
// r.Mount("/v2", v2.NewRouter(db))
|
||||
func RegisterAll(r chi.Router, db *sqlx.DB) {
|
||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("emly-api-go"))
|
||||
_, err := w.Write([]byte("emly-api-go"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
r.Mount("/v1", v1.NewRouter(db))
|
||||
|
||||
Reference in New Issue
Block a user