In this article we will create a Go application which will accept http requests and interact with Postgresql database. Then we will deploy the app together with the database to a Kubernetes cluster. In order to run the code, Docker registry and Kubernetes cluster must be available to you. If not, you can slightly amend the code in order to run it locally. You can follow it step by step or get the source from: https://github.com/marukhno/go-demo-app
Our application is going to provide four methods which can be called with the following sample requests:
curl -X GET "http://HOST:PORT/ping"
curl -X GET "http://HOST:PORT/ticker?ticker=TSLA"
curl -X POST -d '{"ticker":"AAPL", "price":"140.00"}' "http://HOST:PORT/order"
curl -X GET "http://HOST:PORT/order?id=1"
/order methods will interact with the database.
Swagger file is available on: https://github.com/marukhno/go-demo-app/blob/main/swagger.yaml
The article includes steps to:
1. Create a new Go module
2. Prepare and run a database
3. Developing an application
4. Testing an application
1. Create a new Go module
mkdir go-demo-app && cd go-demo-app
git init
git remote add origin https://github.com/marukhno/go-demo-app.git
go mod init github.com/marukhno/go-demo-app
2. Prepare and run a database
From go-demo-app folder create a directory for the database files. Let's call it initdb:
mkdir initdb && cd initdb
Create init.sql script with initial sql to create an empty table for our service.
vi init.sql
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
ticker varchar(100) NOT NULL,
price NUMERIC(12, 2),
created timestamp
);
Create a Dockerfile from postgres image. Copy init.sql script to /docker-entrypoint-initdb.d/
vi Dockerfile
FROM postgres:13.1
ENV POSTGRES_USER docker
ENV POSTGRES_DB docker
ENV POSTGRES_PASSWORD passw0rd
VOLUME /var/lib/postgresql/data
COPY init.sql /docker-entrypoint-initdb.d/
Build an image for our database. Use you docker registry as a tag.
docker build --tag=YOUR_REGISTRY_HOST:YOUR_REGISTRY_PORT/go-demo-app-postgres:1.0.0 .
Push the image to your registry
docker push YOUR_REGISTRY_HOST:YOUR_REGISTRY_PORT/go-demo-app-postgres:1.0.0
Prepare Deployment and Service to run the database in Kubernetes
In this example I will run a pod without persistent volume. If you need to make the data persistent mount a volume for /var/lib/postgresql/data.
vi go-demo-app-postgres-install.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-demo-app-postgres
spec:
replicas: 1
selector:
matchLabels:
app: go-demo-app-postgres
template:
metadata:
labels:
app: go-demo-app-postgres
spec:
containers:
- name: go-demo-postgres
image: YOUR_REGISTRY_HOST:YOUR_REGISTRY_PORT/go-demo-app-postgres:1.0.0
resources:
limits:
memory: "2Gi"
cpu: "1000m"
ports:
- containerPort: 5432
---
apiVersion: v1
kind: Service
metadata:
name: go-demo-app-postgres
spec:
selector:
app: go-demo-app-postgres
ports:
- protocol: TCP
port: 5432
targetPort: 5432
Apply the Deployment
kubectl apply -f go-demo-app-postgres-install.yaml -n NAMESPACE
Validate that the database pod has started
kubectl get po -n NAMESPACE | grep go-demo-app
3. Developing an application
Lets add models to use in our code
vi models.go
The code is available here: https://github.com/marukhno/go-demo-app/blob/main/models.go
Now we create functions to handle communication with the database.
vi db.go
The code is available here: https://github.com/marukhno/go-demo-app/blob/main/db.go
And develop the main function
vi main.go
The code is available here: https://github.com/marukhno/go-demo-app/blob/main/main.go
Optionally, we can add some tests for our function. We will override enviroment variables to test the code locally. This require a database running and available externally.
vi main_test.go
The code is available here: https://github.com/marukhno/go-demo-app/blob/main/main_test.go
Prepare a Dockerfile for our application
vi Dockerfile
FROM golang:1.16.0
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY db.go ./db.go
COPY models.go ./models.go
COPY main.go ./main.go
RUN go build -o main .
EXPOSE 8080
CMD ["./main"]
Build an image for the application
docker build --tag=YOUR_REGISTRY_HOST:YOUR_REGISTRY_PORT/go-demo-app:1.0.0 .
Push the image to your registry
docker push YOUR_REGISTRY_HOST:YOUR_REGISTRY_PORT/go-demo-app:1.0.0
Prepare Deployment and Service to run and expose the app. Prepare Secret to keep database credentials.
Where:
go-demo-app-postgres - a name of the Service we created for the database
go-demo-app-db-secret - a name of the Secret
username and passwod - base64 encoded credentials to access the database
vi go-demo-app-install.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-demo-app
spec:
replicas: 1
selector:
matchLabels:
app: go-demo-app
template:
metadata:
labels:
app: go-demo-app
spec:
containers:
- name: go-demo-app
image: YOUR_REGISTRY_HOST:YOUR_REGISTRY_PORT/go-demo-app:1.0.0
env:
- name: DATABASE_URL
value: "go-demo-app-postgres:5432/docker"
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: go-demo-app-db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: go-demo-app-db-secret
key: password
resources:
limits:
memory: "2Gi"
cpu: "1000m"
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: go-demo-app
spec:
type: NodePort
selector:
app: go-demo-app
ports:
- port: 8080
targetPort: 8080
---
apiVersion: v1
kind: Secret
metadata:
name: go-demo-app-db-secret
data:
username: ZG9ja2Vy
password: cGFzc3cwcmQ=
Apply the Deployment
kubectl apply -f go-demo-app-install.yaml -n NAMESPACE
4. Testing an application
Optionally, run go test: go test -v
Be sure you configured the environment for this test.

Now let's test the app deployed in the Kubernetes.
First of all, lets find out the NodePort for our service:
kubectl get svc -n NAMESPACE | grep go-demo-app

We can use curl to make a few calls.
curl -s -X GET v101:30629/ping
curl -s X GET "v101:30629/ticker?ticker=TSLA"
curl -s X POST -d '{"ticker":"AAPL", "price":"150.45"}' v101:30629/order
curl -s X GET "v101:30629/order?id=2"

Another way is to import service's swagger file to a testing tool like Postman.
The swagger can be found here: https://github.com/marukhno/go-demo-app/blob/main/swagger.yaml
