Skip to content

Commit f6314c3

Browse files
committed
Enable running locally using docker; add db migrations
1 parent a931d1f commit f6314c3

File tree

14 files changed

+1522
-54
lines changed

14 files changed

+1522
-54
lines changed

Dockerfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Build stage
2+
FROM golang:1.19-alpine3.16 AS builder
3+
WORKDIR /app
4+
COPY go.mod .
5+
COPY go.sum .
6+
RUN go mod download
7+
COPY . .
8+
RUN go build -o main cmd/main.go
9+
10+
# Run stage
11+
FROM alpine:3.16
12+
WORKDIR /app
13+
COPY --from=builder /app/main .
14+
COPY app.env .
15+
COPY start.sh .
16+
COPY wait-for.sh .
17+
RUN chmod +x start.sh wait-for.sh
18+
COPY postgres/migrations ./postgres/migrations
19+
20+
EXPOSE 8085
21+
CMD [ "/app/main" ]

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,12 @@
11
# todo
22
Example project meant to demonstrate a production-ready, enterprise-style REST API using go-kit.
3+
4+
To run:
5+
```
6+
docker-compose build && docker-compose up -d
7+
```
8+
9+
To stop:
10+
```
11+
docker-compose down
12+
```

app.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ SERVER_WRITE_TIMEOUT=15s
33
SERVER_READ_TIMEOUT=15s
44
SERVER_IDLE_TIMEOUT=60s
55
GRACEFUL_SHUTDOWN_TIMEOUT=30s
6+
DB_SOURCE=postgresql://root:secret@postgres:5432/todo?sslmode=disable
7+
DB_CONNECT_TIMEOUT=5s
8+
OTEL_EXPORTER_JAEGER_ENDPOINT=http://jaeger:14268/api/traces

cmd/main.go

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,23 @@ package main
22

33
import (
44
"context"
5-
"database/sql"
6-
"fmt"
75
"net/http"
86
"os"
97
"os/signal"
108

119
"github.com/go-kit/log"
10+
_ "github.com/golang-migrate/migrate/v4/database/postgres"
11+
_ "github.com/golang-migrate/migrate/v4/source/file"
1212
_ "github.com/lib/pq"
1313
"github.com/prometheus/client_golang/prometheus/promhttp"
1414
"go.opentelemetry.io/contrib/propagators/b3"
1515
"go.opentelemetry.io/otel"
16+
"go.opentelemetry.io/otel/attribute"
1617
"go.opentelemetry.io/otel/exporters/jaeger"
1718
"go.opentelemetry.io/otel/propagation"
19+
"go.opentelemetry.io/otel/sdk/resource"
1820
"go.opentelemetry.io/otel/sdk/trace"
21+
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
1922

2023
"github.com/jarri-abidi/todo/checklist"
2124
"github.com/jarri-abidi/todo/config"
@@ -31,36 +34,37 @@ func main() {
3134
os.Exit(1)
3235
}
3336

34-
var db *sql.DB
35-
{
36-
ctx, cancel := context.WithTimeout(context.Background(), conf.DBConnectTimeout)
37-
defer cancel()
38-
db, err = postgres.NewDB(ctx, conf.DBSource)
39-
if err != nil {
40-
logger.Log("msg", "could not connect to postgres", "err", err)
41-
os.Exit(1)
42-
}
37+
ctx, cancel := context.WithTimeout(context.Background(), conf.DBConnectTimeout)
38+
defer cancel()
39+
db, err := postgres.NewDB(ctx, conf.DBSource)
40+
if err != nil {
41+
logger.Log("msg", "could not connect to postgres", "err", err)
42+
os.Exit(1)
4343
}
4444

45-
var exporter trace.SpanExporter
46-
{
47-
exporter, err = jaeger.New(jaeger.WithCollectorEndpoint())
48-
if err != nil {
49-
logger.Log("msg", "could not create jaeger exporter", "err", err)
50-
os.Exit(1)
51-
}
45+
if err = postgres.Migrate("file://postgres/migrations", db); err != nil {
46+
logger.Log("msg", "could not run postgres schema migrations", "err", err)
47+
os.Exit(1)
5248
}
5349

54-
var tp *trace.TracerProvider
55-
{
56-
tp = trace.NewTracerProvider(
57-
trace.WithSampler(trace.AlwaysSample()),
58-
trace.WithBatcher(exporter),
59-
)
60-
otel.SetTracerProvider(tp)
61-
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(b3.New()))
50+
exporter, err := jaeger.New(jaeger.WithCollectorEndpoint())
51+
if err != nil {
52+
logger.Log("msg", "could not create jaeger exporter", "err", err)
53+
os.Exit(1)
6254
}
6355

56+
tp := trace.NewTracerProvider(
57+
trace.WithSampler(trace.AlwaysSample()),
58+
trace.WithBatcher(exporter),
59+
trace.WithResource(resource.NewWithAttributes(
60+
semconv.SchemaURL,
61+
semconv.ServiceNameKey.String("todo"),
62+
attribute.String("environment", "dev"),
63+
)),
64+
)
65+
otel.SetTracerProvider(tp)
66+
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(b3.New()))
67+
6468
tasks := postgres.NewTaskRepository(db)
6569

6670
var service checklist.Service
@@ -79,14 +83,6 @@ func main() {
7983
Handler: mux,
8084
}
8185

82-
fmt.Println(`
83-
_____ _
84-
/__ \___ __| | ___
85-
/ /\/ _ \ / _ |/ _ \
86-
/ / | (_) | (_| | (_) |
87-
\/ \___/ \__,_|\___/
88-
`)
89-
9086
sig := make(chan os.Signal, 1)
9187
signal.Notify(sig, os.Interrupt)
9288

@@ -100,19 +96,19 @@ func main() {
10096

10197
logger.Log("received", <-sig, "msg", "terminating")
10298

103-
if err := server.Shutdown(context.Background()); err != nil {
99+
if err = server.Shutdown(context.Background()); err != nil {
104100
logger.Log("msg", "could not shutdown http server", "err", err)
105101
}
106102

107-
if err := db.Close(); err != nil {
103+
if err = db.Close(); err != nil {
108104
logger.Log("msg", "could not close db connection", "err", err)
109105
}
110106

111-
if err := tp.Shutdown(context.Background()); err != nil {
107+
if err = tp.Shutdown(context.Background()); err != nil {
112108
logger.Log("msg", "could not shutdown tracer provider", "err", err)
113109
}
114110

115-
if err := exporter.Shutdown(context.Background()); err != nil {
111+
if err = exporter.Shutdown(context.Background()); err != nil {
116112
logger.Log("msg", "could not shutdown traces exporter", "err", err)
117113
}
118114

config/config.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ import (
1111
// Config stores all configurations of the application.
1212
// The values are read from a file or environment variables.
1313
type Config struct {
14-
ServerAddress string `envconfig:"SERVER_ADDRESS"`
15-
ServerWriteTimeout time.Duration `envconfig:"SERVER_WRITE_TIMEOUT"`
16-
ServerReadTimeout time.Duration `envconfig:"SERVER_READ_TIMEOUT"`
17-
ServerIdleTimeout time.Duration `envconfig:"SERVER_IDLE_TIMEOUT"`
18-
GracefulShutdownTimeout time.Duration `envconfig:"GRACEFUL_SHUTDOWN_TIMEOUT"`
19-
DBSource string `envconfig:"DB_SOURCE"`
20-
DBConnectTimeout time.Duration `envconfig:"DB_CONNECT_TIMEOUT"`
14+
ServerAddress string `envconfig:"SERVER_ADDRESS"`
15+
ServerWriteTimeout time.Duration `envconfig:"SERVER_WRITE_TIMEOUT"`
16+
ServerReadTimeout time.Duration `envconfig:"SERVER_READ_TIMEOUT"`
17+
ServerIdleTimeout time.Duration `envconfig:"SERVER_IDLE_TIMEOUT"`
18+
GracefulShutdownTimeout time.Duration `envconfig:"GRACEFUL_SHUTDOWN_TIMEOUT"`
19+
DBSource string `envconfig:"DB_SOURCE"`
20+
DBConnectTimeout time.Duration `envconfig:"DB_CONNECT_TIMEOUT"`
21+
OTELExporterJaegerEndpoint string `envconfig:"OTEL_EXPORTER_JAEGER_ENDPOINT"`
2122
}
2223

2324
// Load returns configuration from file or environment variables.

docker-compose.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
version: "3.9"
2+
services:
3+
postgres:
4+
image: postgres:14-alpine
5+
environment:
6+
- POSTGRES_USER=root
7+
- POSTGRES_PASSWORD=secret
8+
- POSTGRES_DB=todo
9+
jaeger:
10+
image: jaegertracing/all-in-one:latest
11+
ports:
12+
- "16687:16686"
13+
todo:
14+
build:
15+
context: .
16+
dockerfile: Dockerfile
17+
ports:
18+
- "8085:8085"
19+
environment:
20+
- DB_SOURCE=postgresql://root:secret@postgres:5432/todo?sslmode=disable
21+
depends_on:
22+
- postgres
23+
entrypoint:
24+
[
25+
"/app/wait-for.sh",
26+
"postgres:5432",
27+
"--",
28+
"/app/start.sh"
29+
]
30+
command: [ "/app/main" ]

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ go 1.14
55
require (
66
github.com/go-kit/kit v0.12.0
77
github.com/go-kit/log v0.2.0
8+
github.com/golang-migrate/migrate/v4 v4.15.2
89
github.com/gorilla/mux v1.8.0
910
github.com/joho/godotenv v1.4.0
1011
github.com/kelseyhightower/envconfig v1.4.0
11-
github.com/lib/pq v1.10.7 // indirect
12+
github.com/lib/pq v1.10.7
1213
github.com/pkg/errors v0.9.1
1314
github.com/prometheus/client_golang v1.11.0
1415
github.com/stretchr/testify v1.8.0
1516
go.opentelemetry.io/contrib/instrumentation/github.com/go-kit/kit/otelkit v0.35.0
16-
go.opentelemetry.io/contrib/propagators/b3 v1.10.0 // indirect
17+
go.opentelemetry.io/contrib/propagators/b3 v1.10.0
1718
go.opentelemetry.io/otel v1.10.0
1819
go.opentelemetry.io/otel/exporters/jaeger v1.10.0
1920
go.opentelemetry.io/otel/sdk v1.10.0

0 commit comments

Comments
 (0)