Skip to content

Commit fb69c2a

Browse files
authored
feat: docker environments for gsw (#42)
1 parent 94eefe4 commit fb69c2a

14 files changed

Lines changed: 248 additions & 2 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Build and publish Docker image
2+
3+
on:
4+
push:
5+
branches:
6+
- 'main'
7+
8+
env:
9+
REGISTRY: ghcr.io
10+
IMAGE_NAME: ${{ github.repository }}
11+
12+
jobs:
13+
build-and-push-image:
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: read
17+
packages: write
18+
attestations: write
19+
id-token: write
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v5
23+
- name: Log in to the Container registry
24+
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1
25+
with:
26+
registry: ${{ env.REGISTRY }}
27+
username: ${{ github.actor }}
28+
password: ${{ secrets.GITHUB_TOKEN }}
29+
- name: Extract metadata (tags, labels) for Docker
30+
id: meta
31+
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f
32+
with:
33+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
34+
- name: Build and push Docker image
35+
id: push
36+
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
37+
with:
38+
context: .
39+
file: cmd/Containerfile
40+
push: true
41+
tags: ${{ steps.meta.outputs.tags }}
42+
labels: ${{ steps.meta.outputs.labels }}
43+
44+
- name: Generate artifact attestation
45+
uses: actions/attest-build-provenance@v3
46+
with:
47+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
48+
subject-digest: ${{ steps.push.outputs.digest }}
49+
push-to-registry: true

README.md

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,60 @@ You can always run the GSW service by doing a `./gsw_service` after building. Fo
1212
### Compatibility
1313
Some machines do not have a /dev/shm directory. The directory used for shared memory can be changed with the flag `-shm (DIRECTORY_NAME)`. For example, `go run cmd/mem_view/mem_view.go -shm /someDirectory/RAMDrive`.
1414

15+
## Docker
16+
It may be easier to run the GSW in a docker container. This might be better for compatibility and easier for people on Windows hosts (as docker desktop will natively use a WLS 2 backend).
17+
18+
A dockerfile for GSW is provided in `./cmd/Containerfile` and can be built and run with:
19+
```shell
20+
$ docker build -t launch-gsw -f ./cmd/Containerfile .
21+
```
22+
23+
And the container could be started with:
24+
```shell
25+
$ docker run --name gsw-service \
26+
-p 11020:11020/udp \
27+
-p 13020:13020/udp \
28+
-p 12005:12005/udp \
29+
-p 12006:12006/udp \
30+
-p 12002:12002/udp \
31+
launch-gsw
32+
```
33+
34+
### `docker-compose`
35+
36+
For simplicity, a `docker-compose` file is provided for building and running GSW, Grafana, and InfluxDB:
37+
```shell
38+
$ docker compose up --build
39+
```
40+
41+
#### Accessing Grafana
42+
43+
Grafana should be exposed at <http://localhost:3000>.
44+
The default compose file has anonymous access enabled where the default user only has viewer permissions.
45+
If you need to change dashboards or datasources, set `GF_AUTH_ANONYMOUS_ORG_ROLE=Admin` in `compose.yaml` before starting the container.
46+
47+
#### Accessing InfluxDB
48+
49+
You can access the InfluxDB CLI using `docker compose exec -it influxdb influx`.
50+
For example, to export all receiver telemetry as a CSV, run:
51+
```shell
52+
$ docker compose exec influxdb influx \
53+
-database "gsw" \
54+
-format csv \
55+
-execute "SELECT * FROM receiver"
56+
```
57+
58+
### Attaching to the container
59+
60+
If you need to run any of the apps in `cmd/`, you can get a shell into the container using:
61+
```shell
62+
$ docker exec -it gsw-service sh
63+
```
64+
65+
(if you're using docker compose this will be `docker compose exec -it gsw sh`)
66+
67+
All binaries are in PATH as the names of their folders in `cmd/`.
68+
1569
## Unit Tests
1670
There are several unit tests that can be run. You can do a `go test ./...` from the root project directory to execute all tests. It is also recommended to run with the -cover
1771
flag to get coverage statements.
@@ -46,7 +100,7 @@ Once set up, the grafana_live application can be run from the root directory (wi
46100
Make sure the GSW service is running before starting the application.
47101

48102
In case the setup utility does not work, live data streaming can be set up manually as follows:
49-
1. Import a new dashboard into Grafana using the JSON file located at `data/grafana/Backplane-Live.json`. The dashboard can have any name and UID.
103+
1. Import a new dashboard into Grafana using the JSON file located at `data/grafana/dashboards/Backplane-Live.json`. The dashboard can have any name and UID.
50104
2. Create a service account at the following URL: [http://localhost:3000/org/serviceaccounts/create](http://localhost:3000/org/serviceaccounts/create) (replace `http://localhost:3000` if you are using a different host).
51105
The service account can have any display name but must be given the Admin role ([More information about creating service accounts](https://grafana.com/docs/grafana/latest/administration/service-accounts/)).
52106
3. Click "Add service account token" and then "Generate token". The token can have any display name. Don't set an expiration date unless you want the token to become invalid after that date.

cmd/Containerfile

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
FROM golang:1.25-alpine AS build
2+
3+
RUN apk add --update --no-cache build-base
4+
5+
WORKDIR /go/src/app
6+
7+
COPY go.mod .
8+
COPY go.sum .
9+
10+
RUN --mount=type=cache,id=gsw_mod,target=/go/pkg/mod \
11+
go mod download
12+
13+
COPY . .
14+
15+
RUN --mount=type=cache,id=gsw_mod,target=/go/pkg/mod \
16+
--mount=type=cache,id=gsw_build,target=/root/.cache/go-build \
17+
CGO_ENABLED=1 GOOS=linux go build \
18+
-trimpath \
19+
-o /build-output/bin/gsw_service \
20+
-v \
21+
./cmd/gsw_service.go
22+
23+
RUN --mount=type=cache,id=gsw_mod,target=/go/pkg/mod \
24+
--mount=type=cache,id=gsw_build,target=/root/.cache/go-build \
25+
for binary in grafana_live live_setup mem_view pipeline_benchmark telem_view udp_command; do \
26+
CGO_ENABLED=1 GOOS=linux go build \
27+
-trimpath \
28+
-o /build-output/bin/$binary \
29+
-v \
30+
./cmd/$binary/; \
31+
done
32+
33+
FROM alpine
34+
35+
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
36+
37+
COPY data /opt/app/data
38+
COPY --from=build /build-output/bin/ /usr/bin/
39+
40+
WORKDIR /opt/app
41+
42+
USER appuser
43+
44+
ENV GSW_LOGGER_OUTPUT_PATHS=stdout
45+
46+
ENTRYPOINT [ "gsw_service" ]

cmd/gsw_service.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ func readConfig() (*viper.Viper, int) {
123123
flag.Parse()
124124
config.SetConfigName(*configFilepath)
125125
config.SetConfigType("yaml")
126+
config.SetEnvPrefix("GSW")
127+
config.AutomaticEnv()
126128
config.AddConfigPath("data/config/")
127129
err := config.ReadInConfig()
128130

cmd/live_setup/live_setup.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"strings"
1717
)
1818

19-
const DashboardJsonFile = "data/grafana/Backplane-Live.json"
19+
const DashboardJsonFile = "data/grafana/dashboards/Backplane-Live.json"
2020

2121
// Prompts the user for the Grafana username, password, and URL.
2222
// Returns a URL to Grafana containing the username and password info for basic auth.

compose.yaml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
services:
2+
gsw:
3+
build:
4+
context: .
5+
dockerfile: cmd/Containerfile
6+
depends_on:
7+
influxdb:
8+
condition: service_started
9+
grafana:
10+
condition: service_started
11+
environment:
12+
- GSW_DATABASE_HOST_NAME=influxdb
13+
ports:
14+
- 11020:11020/udp
15+
- 13020:13020/udp
16+
- 12005:12005/udp
17+
- 12006:12006/udp
18+
- 12002:12002/udp
19+
20+
grafana:
21+
build:
22+
context: data/grafana
23+
dockerfile: Containerfile
24+
ports:
25+
- "127.0.0.1:3000:3000/tcp"
26+
depends_on:
27+
influxdb:
28+
condition: service_started
29+
environment:
30+
- GSW_GRAFANA_INFLUXDB_URL=http://influxdb:8086
31+
- GSW_GRAFANA_INFLUXDB_USER=root
32+
- GSW_GRAFANA_INFLUXDB_PASSWORD=root
33+
- GF_AUTH_ANONYMOUS_ENABLED=true
34+
- GF_AUTH_ANONYMOUS_ORG_ROLE=Viewer
35+
- GF_AUTH_BASIC_ENABLED=false
36+
volumes:
37+
- grafana-data:/var/lib/grafana
38+
influxdb:
39+
image: influxdb:1.11-alpine
40+
volumes:
41+
- influxdb-data:/var/lib/influxdb
42+
environment:
43+
- INFLUXDB_UDP_ENABLED=true
44+
- INFLUXDB_UDP_DATABASE=gsw
45+
46+
volumes:
47+
grafana-data:
48+
influxdb-data:

data/grafana/Containerfile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM alpine AS build-dashboards
2+
3+
RUN apk add --update --no-cache jq
4+
5+
WORKDIR /dashboards
6+
7+
COPY dashboards/ .
8+
RUN mkdir processed
9+
10+
RUN for dashboard in *.json; do \
11+
jq 'walk(if type == "object" and .datasource.type == "influxdb" and (.datasource | has("uid")) then .datasource.uid = "gsw-influxdb" else . end)' "$dashboard" > "processed/$dashboard"; \
12+
done
13+
14+
FROM grafana/grafana:12.1
15+
16+
COPY --from=build-dashboards /dashboards/processed /etc/grafana/provisioning/gsw-dashboards
17+
COPY provisioning/datasources /etc/grafana/provisioning/datasources
18+
COPY provisioning/gsw-dashboard-provider.yaml /etc/grafana/provisioning/dashboards/gsw-dashboard-provider.yaml
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)