Microservices in Go Lang with Postgres (Local, Docker to Render Public hosting)

Microservices in Go Lang with Postgres (Local, Docker to Render Public hosting)

·

5 min read

This project will summarize the steps to create a microservice using Golang and Postgresql. We will be using 4 different data models each implementing CRUD operations. The structure of the project will be like -

  • internal/database - This will contain the database connection and the schema and data files.

  • internal/models - This will contain the data models.

  • internal/db_errors - This will contain the error handling for the database.

  • internal/server - This will contain the server and the main function.

Elaborated schema for the project using E-R diagram

E-R Diagram

The following are dependencies we will be using, along with the steps to run your project locally.

Link to my github repo for the code - https://github.com/bindian0509/microservices-with-golang

Pre-requisites (for mac OS ventura)

Use getting started for creating Postgres container

  • Create a dir in your home folder called data-postgres-go under docker-vols

    • mkdir -p ~/docker-vols/data-postgres-go
  • Create a postgres container

      docker run -d --rm \
          --name local-pg \
          -e POSTGRES_PASSWORD=postgres \
          -p 5432:5432 \
          -e PGDATA=/var/lib/postgresql/data/pgdata \
          -v /Users/<user-name>/docker-vols/data-postgres-go:/var/lib/postgresql/data \
      postgres
    
  • Login via psql

    • docker exec -it local-pg psql -U postgres
  • Create database schema via schema.sql

    • psql -U postgres -f schema.sql
  • Insert data to the database via data.sql

    • psql -U postgres -f data.sql

Setting up the go project

  • Create a directory called microservices-with-golang in your home folder

    • mkdir -p ~/microservices-with-golang

    • cd ~/microservices-with-golang

  • Use go mod init to create a go module

  • Use go mod tidy to download the dependencies

    • go mod tidy
  • To start the project run

    • go run main.go voila you have your project up and running
   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.11.1
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8080

Testing Microservices

Checking the database connection and liveness probe

  • To start the server

    • go run main.go
  • To check everything is working fine

    • http :8080/readiness

    • http :8080/liveness

  • Expected output

    HTTP/1.1 200 OK
    Content-Length: 16
    Content-Type: application/json; charset=UTF-8
    Date: Tue, 22 Aug 2023 11:30:52 GMT

    {
        "status": "OK"
    }

Testing Get All customer API endpoint (GET)

  • To get all customers

    • http :8080/customers
[
    {
        "address": "556 Lakewood Park, Bismarck, ND 58505",
        "customerId": "e2579031-41f8-4c1b-851d-d05dd0327230",
        "emailAddress": "penatibus.et@lectusa.com",
        "firstName": "Cally",
        "lastName": "Reynolds",
        "phoneNumber": "(901) 166-8355"
    },
    {
        "address": "4829 Badeau Parkway, Chattanooga, TN 37405",
        "customerId": "8db81915-7955-47ac-abf1-fa3a3f27e0a3",
        "emailAddress": "nibh@ultricesposuere.edu",
        "firstName": "Sydney",
        "lastName": "Bartlett",
        "phoneNumber": "(982) 231-7357"
    },
    ...
]
HTTP/1.1 200 OK
Content-Length: 223
Content-Type: application/json; charset=UTF-8
Date: Tue, 22 Aug 2023 13:26:37 GMT

[
    {
        "address": "602 Sommers Parkway, Norfolk, VA 23520",
        "customerId": "44f82d9d-b0a6-49b2-ac04-cb05b4cbf189",
        "emailAddress": "magna.Phasellus@Phasellus.net",
        "firstName": "Brock",
        "lastName": "Case",
        "phoneNumber": "(544) 534-1984"
    }
]

Testing create customer API endpoint (POST)

  • To create a new customer

    • http POST :8080/customers firstName=John lastName=Reese emailAddress="john@root.com" phoneNumber="515-555-1235" address="36 ChinaTown, Borivali East, Mumbi, MH, INDIA"
    HTTP/1.1 201 Created
    Content-Length: 210
    Content-Type: application/json; charset=UTF-8
    Date: Tue, 22 Aug 2023 18:28:38 GMT

    {
        "address": "36 ChinaTown, Borivali East, Mumbi, MH, INDIA",
        "customerId": "68fb0b27-1e9a-4ce8-81ac-f41cc1e3f5d6",
        "emailAddress": "john@root.com",
        "firstName": "John",
        "lastName": "Reese",
        "phoneNumber": "515-555-1235"
    }

Testing Get customer from Id API endpoint (GET)

  • To get customer with customerId

    • http :8080/customers/8db81915-7955-47ac-abf1-fa3a3f27e0a3
    HTTP/1.1 200 OK
    Content-Length: 225
    Content-Type: application/json; charset=UTF-8
    Date: Wed, 23 Aug 2023 11:10:49 GMT

    {
        "address": "4829 Badeau Parkway, Chattanooga, TN 37405",
        "customerId": "8db81915-7955-47ac-abf1-fa3a3f27e0a3",
        "emailAddress": "nibh@ultricesposuere.edu",
        "firstName": "Sydney",
        "lastName": "Bartlett",
        "phoneNumber": "(982) 231-7357"
    }

Testing Update customer API endpoint (PUT)

  • To update customer with customerId

    • http PUT :8080/customers/e2579031-41f8-4c1b-851d-d05dd0327230 address="556 Lakewood Park, Bismarck, ND 58505" customerId="e2579031-41f8-4c1b-851d-d05dd0327230" emailAddress="penatibus.et@lectusa.com" firstName="Ryan" lastName="Reynolds" phoneNumber="(901) 166-8355"
    HTTP/1.1 200 OK
    Content-Length: 218
    Content-Type: application/json; charset=UTF-8
    Date: Fri, 25 Aug 2023 19:04:49 GMT

    {
        "address": "556 Lakewood Park, Bismarck, ND 58505",
        "customerId": "e2579031-41f8-4c1b-851d-d05dd0327230",
        "emailAddress": "penatibus.et@lectusa.com",
        "firstName": "Ryan",
        "lastName": "Reynolds",
        "phoneNumber": "(901) 166-8355"
    }

Testing Delete customer API endpoint (DELETE)

  • To update customer with customerId

    • http DELETE :8080/customers/8db81915-7955-47ac-abf1-fa3a3f27e0a3
    HTTP/1.1 205 Reset Content
    Content-Length: 0
    Date: Fri, 25 Aug 2023 19:31:23 GMT

Running the same project with docker image (using Dockerfile)

  • Step 1: Build the docker image for the application

    • docker build -t microservices-with-golang .
  • Step 2: Run the docker image

    • docker run -e env=docker --env-file db.docker.env --network host --name microservices-with-golang-app microservices-with-golang
  • Step 3: Since this container is not exposed to outside world we can login inside it and test the API

    • docker exec -it microservices-with-golang-app sh

    • http :8080/liveness (this will work fine since the docker file already has apk add httpie)

Production release of the application using Render.com free tiers

  • Sign up for render.com using github or other options

  • At first we need to spinup a database service (PostgreSQL)

    • Click on create a new database

    • Select the free tier

    • Select the region

    • Select the database name

    • Select the database password

    • Click on create database

  • Use psql command option to be copied and dump the files to prod db via following commands

  • Create a new web service

    • Select the github repo

    • Select the branch

    • Select the docker file path

    • Select the port

    • Select the environment variables

      • Refer to db.env file for list of args

      • sslmode=require is for production db cluster

    • Select the free tier

    • Click on create web service

  • Once the web service is created you can see the logs and the application running on the url provided by render.com