diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..668522b
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,13 @@
+/**
+!/cmd/africastalking
+!/common
+!/config
+!/initializers
+!/internal
+!/models
+!/remote
+!/services
+!/LICENSE
+!/README.md
+!/go.*
+!/.env
\ No newline at end of file
diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml
new file mode 100644
index 0000000..77f4f78
--- /dev/null
+++ b/.github/workflows/docker.yaml
@@ -0,0 +1,58 @@
+name: release
+
+on:
+  push:
+    tags:
+      - "v*"
+
+jobs:
+  docker:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v2
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v2
+
+      - name: Check out repo
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Cache Docker layers
+        uses: actions/cache@v3
+        with:
+          path: /tmp/.buildx-cache
+          key: ${{ runner.os }}-buildx-${{ github.sha }}
+          restore-keys: |
+            ${{ runner.os }}-buildx-
+
+      - name: Login to GHCR Docker registry
+        uses: docker/login-action@v1
+        with:
+          registry: ghcr.io
+          username: ${{ github.repository_owner }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Set outputs
+        run: |
+          echo "RELEASE_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV \
+          && echo "RELEASE_SHORT_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
+
+      - name: Build and push image
+        uses: docker/build-push-action@v2
+        with:
+          context: ./
+          file: ./Dockerfile
+          platforms:
+            - linux/amd64
+            - linux/arm64
+          push: true
+          build-args: |
+            BUILD=${{ env.RELEASE_SHORT_COMMIT }}
+          cache-from: type=local,src=/tmp/.buildx-cache
+          cache-to: type=local,dest=/tmp/.buildx-cache
+          tags: |
+            ghcr.io/grassrootseconomics/urdt-ussd:latest
+            ghcr.io/grassrootseconomics/urdt-ussd:${{ env.RELEASE_TAG }}
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..6d88926
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,40 @@
+FROM golang:1.23.0-bookworm AS build
+
+ENV CGO_ENABLED=1
+
+ARG BUILDPLATFORM
+ARG TARGETPLATFORM
+ARG BUILD=dev
+
+WORKDIR /build
+COPY . .
+RUN apt update && apt install libgdbm-dev
+RUN git clone https://git.defalsify.org/vise.git go-vise
+
+WORKDIR /build/services/registration
+RUN echo "Compiling go-vise files"
+RUN make VISE_PATH=/build/go-vise -B
+
+WORKDIR /build
+RUN echo "Building on $BUILDPLATFORM, building for $TARGETPLATFORM"
+RUN go mod download
+RUN go build -o ussd-africastalking -ldflags="-X main.build=${BUILD} -s -w" cmd/africastalking/main.go
+
+FROM debian:bookworm-slim
+
+ENV DEBIAN_FRONTEND=noninteractive
+
+RUN apt update && apt install libgdbm-dev ca-certificates -y
+RUN apt-get clean && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /service
+
+COPY --from=build /build/ussd-africastalking .
+COPY --from=build /build/LICENSE .
+COPY --from=build /build/README.md .
+COPY --from=build /build/services ./services
+COPY --from=build /build/.env .
+
+EXPOSE 7123
+
+CMD ["./ussd-africastalking"]
\ No newline at end of file
diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go
index 5a523e7..9f5b501 100644
--- a/cmd/africastalking/main.go
+++ b/cmd/africastalking/main.go
@@ -29,8 +29,10 @@ import (
 )
 
 var (
-	logg        = logging.NewVanilla()
-	scriptDir   = path.Join("services", "registration")
+	logg      = logging.NewVanilla()
+	scriptDir = path.Join("services", "registration")
+
+	build = "dev"
 )
 
 func init() {
@@ -115,7 +117,7 @@ func main() {
 	flag.UintVar(&port, "p", initializers.GetEnvUint("PORT", 7123), "http port")
 	flag.Parse()
 
-	logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size)
+	logg.Infof("start command", "build", build, "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size)
 
 	ctx := context.Background()
 	ctx = context.WithValue(ctx, "Database", database)
@@ -157,6 +159,10 @@ func main() {
 	}
 
 	lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, err.Error())
+		os.Exit(1)
+	}
 	lhs.SetDataStore(&userdataStore)
 
 	if err != nil {
diff --git a/dev/dialoguss/sample_user.yaml b/dev/dialoguss/sample_user.yaml
new file mode 100644
index 0000000..83e690e
--- /dev/null
+++ b/dev/dialoguss/sample_user.yaml
@@ -0,0 +1,3 @@
+url: http://localhost:7123
+dial: "*384*96#"
+phoneNumber: +254722123456
diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml
new file mode 100644
index 0000000..5d65b54
--- /dev/null
+++ b/dev/docker-compose.yaml
@@ -0,0 +1,21 @@
+services:
+  ussd-pg-store:
+    image: postgres:17-alpine
+    restart: unless-stopped
+    user: postgres
+    environment:
+      - POSTGRES_PASSWORD=postgres
+      - POSTGRES_USER=postgres
+    volumes:
+      - ./init_db.sql:/docker-entrypoint-initdb.d/init_db.sql
+      - ussd-pg:/var/lib/postgresql/data
+    ports:
+      - "127.0.0.1:5432:5432"
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready"]
+      interval: 10s
+      timeout: 5s
+      retries: 5
+volumes:
+  ussd-pg:
+    driver: local
diff --git a/dev/init_db.sql b/dev/init_db.sql
new file mode 100644
index 0000000..9ee26b8
--- /dev/null
+++ b/dev/init_db.sql
@@ -0,0 +1 @@
+CREATE DATABASE urdt_ussd;
\ No newline at end of file