tsk-8: Added docker support (#13)

Closes #8

Reviewed-on: phoenix/textsender-auth#13
Co-authored-by: phoenix <kundeng00@pm.me>
Co-committed-by: phoenix <kundeng00@pm.me>
This commit is contained in:
phoenix
2025-11-05 16:50:14 +00:00
committed by phoenix
parent b627c832fa
commit ef39949e77
8 changed files with 141 additions and 4 deletions
+9
View File
@@ -0,0 +1,9 @@
vendor/
# Ignore git directory
.git/
.gitea/
# Ignore environment files (configure via docker-compose instead)
.env*
+7
View File
@@ -0,0 +1,7 @@
SECRET_KEY=NULqYIzgt28bTiyziCd7IOO7b6LnWDW!
DB_NAME=textsender_auth_db
DB_USER=textsender_auth
DB_PASSWORD=password
DB_HOST=auth_db
DB_PORT=5432
DB_SSLMODE=disable
+1
View File
@@ -2,5 +2,6 @@
.env
.env.local
.env.docker
/vendor
+52
View File
@@ -0,0 +1,52 @@
# Multi-stage Dockerfile for Go application
FROM golang:1.25.3 AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
openssh-client git
RUN mkdir -p -m 0700 ~/.ssh && \
ssh-keyscan git.kundeng.us >> ~/.ssh/known_hosts
# Configure Git to use SSH for GitHub
RUN git config --global url."ssh://git@git.kundeng.us".insteadOf "https://git.kundeng.us"
# Set up the Go environment for private modules
ENV GOPRIVATE=git.kundeng.us
# Copy go mod and sum files
COPY go.mod go.sum ./
RUN --mount=type=ssh mkdir src && \
go mod download
# Copy source code
COPY ./cmd ./cmd
COPY ./internal ./internal
COPY ./Makefile .
COPY ./.env .
COPY ./migrations ./migrations
# Build the application
RUN CGO_ENABLED=0 GOOS=linux make build
# Runtime stage
FROM alpine:latest AS production
RUN apk --no-cache add ca-certificates
WORKDIR /root/
# Copy the pre-built binary file from the previous stage
COPY --from=builder /app/textsender-auth .
COPY --from=builder /app/.env ./
COPY --from=builder /app/migrations ./migrations
# Expose port
EXPOSE 9080
# Command to run the executable
CMD ["./textsender-auth"]
+9 -2
View File
@@ -14,7 +14,7 @@ import (
"github.com/go-chi/chi/v5/middleware"
"git.kundeng.us/phoenix/textsender-auth/internal/config"
"git.kundeng.us/phoenix/textsender-auth/internal/db"
database "git.kundeng.us/phoenix/textsender-auth/internal/db"
"git.kundeng.us/phoenix/textsender-auth/internal/handler"
"git.kundeng.us/phoenix/textsender-auth/internal/handler/endpoint"
mdleware "git.kundeng.us/phoenix/textsender-auth/internal/middleware"
@@ -28,7 +28,7 @@ func main() {
os.Exit(-1)
}
db, err := db.NewDatabase(cfg.GetDBConnString())
db, err := database.NewDatabase(cfg.GetDBConnString())
if err != nil {
log.Fatalf("Failed to connect to database: %v", err)
}
@@ -43,6 +43,13 @@ func main() {
}
log.Println("Database reset completed. Exiting.")
return
} else {
if exists, err := database.TableExists(ctx, db.Pool, "users"); err == nil && !exists {
fmt.Println("Resetting database")
err = db.ResetDatabase(ctx)
} else {
fmt.Println(err.Error())
}
}
// Services
+44
View File
@@ -0,0 +1,44 @@
version: '3.8' # Use a recent version
services:
auth_api:
build: # Tells docker-compose to build the Dockerfile in the current directory
context: .
ssh: ["default"] # Uses host's SSH agent
container_name: textsender_auth # Optional: Give the container a specific name
ports:
# Map host port 8000 to container port 3000 (adjust as needed)
- "9080:9080"
env_file:
- .env
depends_on:
auth_db:
condition: service_healthy # Wait for the DB to be healthy before starting the app
restart: unless-stopped # Optional: Restart policy
# PostgreSQL Database Service
auth_db:
image: postgres:18.0-alpine # Use an official Postgres image (Alpine variant is smaller)
container_name: textsender_auth_db # Optional: Give the container a specific name
environment:
# These MUST match the user, password, and database name in the DATABASE_URL above
POSTGRES_USER: ${POSTGRES_AUTH_USER:-textsender_auth}
POSTGRES_PASSWORD: ${POSTGRES_AUTH_PASSWORD:-password}
POSTGRES_DB: ${POSTGRES_AUTH_DB:-textsender_auth_db}
volumes:
# Persist database data using a named volume
- postgres_data:/var/lib/postgresql/data
ports: []
healthcheck:
# Checks if Postgres is ready to accept connections
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: always # Optional: Restart policy
# Define the named volume for data persistence
volumes:
postgres_data:
driver: local # Use the default local driver
-2
View File
@@ -27,11 +27,9 @@ type ConnectionInfo struct {
SslMode string
}
const Port = "9080"
const App_Name = "textsender_auth"
func (ci ConnectionInfo) Parse() string {
return fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s", ci.Username, ci.Password, ci.Host, ci.Port, ci.Database, ci.SslMode)
}
+19
View File
@@ -54,6 +54,25 @@ func NewDatabase(connString string) (*Database, error) {
return &Database{Pool: pool}, nil
}
func TableExists(ctx context.Context, conn *pgxpool.Pool, tableName string) (bool, error) {
var exists bool
query := `
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = $1
);
`
err := conn.QueryRow(ctx, query, tableName).Scan(&exists)
if err != nil {
return false, fmt.Errorf("error checking if table exists: %w", err)
}
return exists, nil
}
func (db *Database) Close() {
if db.Pool != nil {
db.Pool.Close()