diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a572269 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Environment variables (NUNCA commitar!) +.env +.env.* +env.* +!.env.example +!env.example + +# OS +.DS_Store +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Logs +*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bca62af --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +# Build stage +FROM golang:1.24-alpine AS builder + +WORKDIR /app + +# Install build dependencies +RUN apk add --no-cache git + +# Copy go mod and sum files from backend +COPY backend/go.mod backend/go.sum ./ + +# Download dependencies +RUN go mod download + +# Copy backend source code +COPY backend/ . + +# Build the Go app +RUN CGO_ENABLED=0 GOOS=linux go build -o api cmd/api/main.go + +# Production stage +FROM alpine:latest + +WORKDIR /app + +# Install ca-certificates for HTTPS requests +RUN apk --no-cache add ca-certificates + +# Copy the binary from builder +COPY --from=builder /app/api . + +# Dokku sets PORT dynamically +EXPOSE 5000 + +# Run the binary +CMD ["./api"] diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..15c5941 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: ./api diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go index aba1311..af0928e 100644 --- a/backend/internal/config/config.go +++ b/backend/internal/config/config.go @@ -28,7 +28,7 @@ func LoadConfig() *Config { return &Config{ AppEnv: getEnv("APP_ENV", "dev"), - AppPort: getEnv("APP_PORT", "8080"), + AppPort: getEnvWithFallback("PORT", "APP_PORT", "8080"), DBDsn: getEnv("DB_DSN", ""), JwtAccessSecret: getEnv("JWT_ACCESS_SECRET", "secret"), JwtRefreshSecret: getEnv("JWT_REFRESH_SECRET", "refresh_secret"), @@ -53,3 +53,15 @@ func getEnvAsInt(key string, fallback int) int { } return fallback } + +// getEnvWithFallback tenta a primeira variável, depois a segunda, depois o fallback +// Útil para compatibilidade com Dokku (PORT) e desenvolvimento local (APP_PORT) +func getEnvWithFallback(primary, secondary, fallback string) string { + if value, ok := os.LookupEnv(primary); ok { + return value + } + if value, ok := os.LookupEnv(secondary); ok { + return value + } + return fallback +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a58d151..a8c6107 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -54,6 +54,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -1300,6 +1301,7 @@ "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -1447,6 +1449,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -2220,6 +2223,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -2279,6 +2283,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -2288,6 +2293,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -2701,6 +2707,7 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4",