Golang & Docker — Microservices (RESTful API) for Enterprise Model

Written by karthiknagesh | Published 2017/09/02
Tech Story Tags: docker | golang-tutorial | docker-image | alpine | golang

TLDRvia the TL;DR App

Beauty And The Beast :)

“Golang” the language created by Google that provides impeccable performance over application that demands concurrency has grabbed a separate spot in the tech community, few well known Inc’s that adopted the language include Facebook, Netflix , Dropbox etc. When Go API’s are dockerized it gives more flexibility and control over the applications being deployed on cloud. Even the Docker software is written on Go that manifest its emerging prominence in the industry

We will walkthrough on building an alpine image holding a Go API and the steps to get it achievable is split into several fragments as below

  • Build Go Restful API with echo framework
  • Build Go binary on golang base image with Docker
  • Build lightweight image (Alpine) holding Go binaries
  • Create containers with Docker

Build Go Restful API with echo framework

Name the file as main.go that contains dependencies — echo, logrus and net/http. We have multiple third party frameworks like Gradle, Martini ,Revel etc that gives customized features for building RESTful API’s. Its absolutely your choice to choose one that satisfies your needs and you can also only rely on golang lib “net/http” to create one RESTful service.

Code Snippet

package main

import ("fmt""github.com/labstack/echo""github.com/labstack/echo/middleware""github.com/sirupsen/logrus""net/http")var log =logrus.New()

func init() {log.Formatter = new(logrus.JSONFormatter)log.Formatter = new(logrus.TextFormatter) // defaultlog.Level = logrus._DebugLevel_}

func main() {fmt.Println("Main function :")e := echo.New()e.Use(middleware.Logger())e.Use(middleware.Recover())// Routese.GET("/go-docker", goWithDocker)e.Logger.Fatal(e.Start(":8080"))}

func goWithDocker(c echo.Context)error{return c.JSON(http.StatusOK, "Go with Docker Container")}

The service is available through a HTTP end point

http://localhost:8080/go-docker

There are multiple IDE’s available in market a few are Sublime, Atom, Gogland etc. I have been using Gogland as it has multiple features and there is early build, give it a try!!

Now lets talk about the program, we have exposed a simple GET operation that has Routes configured /go-docker exposed on a HTTP protocol**.** Logs are written using logrus framework for tracking the request and response.

For build management you could use Jenkins with Docker plugin installed to make it interactive with Docker CLI.

Build Go binary on golang base image with Docker

Use any of the golang images available in docker hub as per your need https://hub.docker.com/_/golang/ , we will be using golang:1.8 in this blog

Ref A: Image containing the go binary

Pull the image from docker hub and create a folder structure pattern /go/src (as expected by Go) to compile the files. Line 5–7 clubs multiple commands, pulling the required source code and vendor dependencies in your Github repo(assuming your repo has 3rd party in /vendor dir). Line 6 & 7 specifies the generated build will be specific to linux environments. The best practice is to always combine multiple RUN statements into one in order to avoid creating multiple layers during image creation.

The resulting Docker build will have a binary go_docker.exe under your /bin folder

Build lightweight image (Alpine) holding Go binaries

Let’s pull the alpine 3.6 base in this demo as it is pretty light weight image which comes with minimal prerequisites to serve as a linux base.

Ref B : Alpine built with binary

Install bash inside the image to make it interactive once the container is up and running via docker. In line 14 we use the feature of multi-stage builds released in the newer versions of docker. The — from tag will allow you to fetch and refer its contents from previously created image by mentioning the source and destination dir. Refer the previous Ref A image Line 1 that specifies goimage which helps in line 14 to reference it

The ENTRYPOINT command instructs container start up should execute the .exe file i.e. go_docker file

All the above contents to be put in one single file named as Dockerfile to get executed in one shot. Build docker image and tag it under a version using the tag -t to avoid conflicts in future builds or else docker will assign a tag “latest” by default

Code Snippet

FROM golang:1.8 as goimageENV SRC=/go/src/RUN mkdir -p /go/src/WORKDIR /go/src/go_dockerRUN git clone -b <Specify-branchname> — single-branch <Github HTTP Url> /go/src/go_docker/ \&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \go build -o bin/go_docker

FROM alpine:3.6 as baseimagealpRUN apk add — no-cache bashENV WORK_DIR=/docker/binWORKDIR $WORK_DIRCOPY — from=goimage /go/src/go_docker/bin/ ./ENTRYPOINT /docker/bin/go_dockerEXPOSE 8080

Note : — indicates double hyphens

The image can be built and viewed by issuing the following commands.

docker build -t go_docker:1.0 .

docker images

Is there anything that we missed!! Containers ? We are covering it in the next section

Create containers with Docker

Create container from the image and expose it by mentioning a port. You could specify your desired port range and expose the container to outside world. In AWS you could push the images to EC2 Service via ECS as tasks.

docker run — rm -p 8080:8080 go_docker

Note : — indicates double hyphens

Once the container is started you could see something similar as below on your terminal

Images can be pushed to a docker repo by mentioning the desired URL.The steps for image creation and push can be automated via Shell

docker login -u=<UserName> -p=<PWD> <Docker REPO URL>

docker push -t <Imagename>:<Version>

Conclusion

Choosing Go is a wise decision that gives scalability and concurrency for your application and selecting a light weight image like alpine will make the push and pull of the image to registries faster, also small size base gives you minimal operating features to build functional container where you can add/install necessary dependencies in future. Using Docker has gained wider acceptance as it makes use of disk space efficiently with at most use of its resources efficiently.

Simply Go With Docker !!!


Published by HackerNoon on 2017/09/02