At Agira, Technology Simplified, Innovation Delivered, and Empowering Business is what we are passionate about. We always strive to build solutions that boost your productivity.

How To Deploy a Golang Web Application with Docker

  • By Reddy Sai
  • September 5, 2017
  • 1493 Views

If you are also a Golang web developer like me, You must be probably knowing that Go code can be compiled into binary code and does not require the Go environment to run. Also, we know that Golang web applications will have templates and configuration files. When we have a large number of files in our project, there is the possibility that some of the files may not be synced. This may lead to a lot of errors and issues.

Here comes the role of Docker. By using docker the files can be kept in sync with binary. So we can overcome these types of issues using Docker.

In this blog, I’m going to discuss how to create a Docker container for the Golang web application and deploying a Docker container.

To deploy the application with docker, we will need to:

At first, you need,

Creating simple Golang web application

For your understanding and demonstration, I have created a sample web application here. This application uses HTML templates for views and exposes routes for the contact form.

Directory structure

Our web application directory structure looks like,

contact_registry
├── Dockerfile
├──main.go
└── views
└── forms.html

Content of main.go

// main.go
package main
import (
 "fmt"
 "path"
 "runtime"
 "net/http"
 "html/template"
)
// contact details structure
type ContactDetails struct {
 Email   string
 Department string
 Description string
}
// Execution start with main function
func main() {
 // Handle http requests with home path / with the formHandler function.
 http.HandleFunc("/", formHandler)
 http.ListenAndServe(":8080", nil)
}
// formHandler is an HTTP handler, it serves form template
func formHandler(w http.ResponseWriter, r *http.Request) {
 _, filename, _, ok := runtime.Caller(0)
 if !ok {
   fmt.Println("No caller information")
 }
 // get template from views directory
 tmpl := template.Must(template.ParseFiles(path.Dir(filename)+"/views/forms.html"))
 if r.Method != http.MethodPost {
   // render template
   tmpl.Execute(w, nil)
   return
 }
 // read field values from form
 details := ContactDetails{
   Email:   r.FormValue("email"),
   Department: r.FormValue("department"),
   Description: r.FormValue("description"),
 }
 // do something with details
 _ = details
 fmt.Println(details)
 // pass value to form
 tmpl.Execute(w, struct{ Success bool }{true})
}

Content of forms.html

<!-- forms.html -->
{{if .Success}}
 <!-- submission response -->
 <h1>Thanks for your message!</h1>
{{else}}
 <!-- Initial render page -->
 <h1>Contact</h1>
 <form method="POST">
   <label>Email:</label><br />
   <input type="text" name="email"><br />
   <label>Department:</label><br />
   <input type="text" name="department"><br />
   <label>Description:</label><br />
   <textarea name="description"></textarea><br />
   <input type="submit">
 </form>
{{end}}

Write a Dockerfile for Docker build

Now we need to write a Dockerfile for building our Docker image to install and run our Go HTTP server in a Docker container. This Dockerfile contains all the commands required to construct a Docker image. So by reading these instructions from Dockerfile Docker builds images.

The content of Dockerfile

From golang:latest
ADD . /go/src/github.com/agiratech/contact_registry
# Build the contact_registry command inside the container.
RUN go install github.com/agiratech/contact_registry
# Run the contact_registry command when the container starts.
ENTRYPOINT /go/bin/contact_registry
# http server listens on port 8080.
EXPOSE 8080

The image name golang:latest means that we are building our image from Golang image with the latest tag. Then, we install our Golang application to the bin folder of Gopath and setting up the entry point for the app.

Note: If you are using the docker image for development between your team, you can clone the source inside the image, but if you are using the image for deployment keep the binary files in the image instead of source code.

Build the Docker image

Run the below-given command, it creates the image from the contact_registry directory that builds a Docker image.

$ sudo docker build -t reddysai/contact_registry .

The build command reads our instructions from Dockerfile. In the Dockerfile,

  • FROM golang:latest fetches the golang:latest image.
  • ADD- adds the package source into Gopath of Golang image.
  • RUN- builds the Go package.
  • ENTRYPOINT – set up the entry point for our container for running the reddysai/contact_registry.
  • EXPOSE – exposes port 8080 for HTTP server.

The above process creates an image with the name reddysai/contact_registry. It can be used by all the people who work on this application.

The following command allows you to see all the images in the list:

$ sudo docker images


Run and test the Docker image

Using the following command run the Docker image. We have to publish an external port to container’s port 8080.

$ sudo docker run -p 6060:8080 --rm reddysai/contact_registry
  • Executing this command runs the Docker image. This container exposes application on port 6060. The docker run -runs a container from an image.
  • –rm flag – it will clean container once the container shuts down.
  • The -p 6060:8080 flag – It makes the container get accessed at port 6060.

Visit in your browser with http://localhost:6060/ to see it running.

Write a Dockerfile with Docker multi-stage builds

Multi-stage builds feature is available in Docker 17.05 version and later versions, It will help to optimize the Dockerfiles and makes it easy to analyze and maintain.

Content of Dockerfile

# build stage
FROM golang:latest AS builder
# working directory
WORKDIR /go/src/github.com/agiratech/contact_registry
# install html package
RUN go get -d -v golang.org/x/net/html
COPY main.go    .
RUN mkdir -p views
# copy the templates into working directory
COPY views /go/src/github.com/agiratech/contact_registry/views
# rebuilt built in libraries and disabled cgo
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
# final stage
FROM alpine:latest
# working directory
WORKDIR /go/src/github.com/agiratech/contact_registry
RUN mkdir -p views
# copy the binary file into working directory
COPY --from=builder /go/src/github.com/agiratech/contact_registry/main .
# copy the templates into working directory
COPY --from=builder /go/src/github.com/agiratech/contact_registry/views/forms.html /go/src/github.com/agiratech/contact_registry/views
RUN cd views && ls -lh
# Run the contact_registry command when the container starts.
CMD ["./main"]
# http server listens on port 8080
EXPOSE 8080

Now build the docker image using below command,
Note: Before executing the command check and update the docker version, multi-stage builds supports only Docker 17.05 and later versions.

$ sudo docker build -t reddysai/contact_registry

Run the docker images using below command,

$ sudo docker run -p 6060:8080 --rm reddysai/contact_registry

Executing the above command runs the Docker image. This container exposes application on port 6060.

Visit in your browser with http://localhost:6060/ to see it running.

Check the running containers using the following command,

$ sudo docker ps -a

Run the following command to stop the docker image,

$ sudo docker stop CONTAINER ID

Push the docker image into Docker Hub

$ sudo docker push reddysai/contact_registry

Now, you can run this docker image easily like,

$ sudo docker run -p 6060:8080 --name test --rm reddysai/contact_registry

Now we have learned to create a Docker container for Golang web application and deploying Docker container. You can also deploy this application to your servers by following the same procedure. For this the server needs a Docker installed.

Have any doubts or queries? Comment below.

We offer Golang development services for building world-class enterprise apps. We have expertise in building the most complex software solutions using Google’s Go language. Chat with us now and hire Golang developers within 72 hours.

Turn your vision to magnificent reality With
Our Web and Mobile Solutions