How to Deploy A Go Application With Docker On Ubuntu

0
317
How to Deploy A Go Application With Docker On Ubuntu

Docker is an open-source tool that helps developers to create, deploy, and run applications by using containers. Docker makes it easy to package and ship programs quickly.

Docker Compose is a container orchestration tool that allows you to run multiple containers at the same time. It allows developers to manage and extend a container simultaneously as per requirement.

Go is an open-source programming language used to build a  simple, reliable, and efficient software application. It provides some build-in tools that allow you to safely use memory, manage objects, collect garbage, and provide static typing along with concurrency.

In this tutorial, we will create a simple Go application and deploy it with a Docker container. We will also use Nginx as a reverse proxy to bind the domain name with Go application.

Requirements

  • A server running Ubuntu 20.04
  • A valid domain name pointed with your server IP. In this tutorial, we will use the app.example.com domain.
  • A root password is configured on your server

Install Docker and Docker Compose

First, you will need to install Docker and Docker compose to your server. First, install all the required dependencies with the following command:

apt-get install apt-transport-https ca-certificates curl software-properties-common gnupg2 -y

Once all the dependencies are installed, import the GPG key and add the Docker repository with the following command:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -

add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Next, install Docker and Docker Compose package with the following command:

apt-get install docker-ce docker-compose -y

Once both packages are installed, verify the status of the Docker with the following command:

systemctl status docker

You should get the following output:

  • docker.service – Docker Application Container Engine

   

Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)

     Active: active (running) since Thu 2021-01-28 02:12:22 UTC; 3min 2s ago

 

TriggeredBy: ● docker.socket

     

Docs: https://docs.docker.com

   Main PID: 11651 (dockerd)

      Tasks: 12

     Memory: 462.1M

     CGroup: /system.slice/docker.service

             └─11651 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Jan 28 02:12:22 ubuntu2004 dockerd[11651]: time="2021-01-28T02:12:22.488276730Z" level=info msg="Loading containers: done."

Jan 28 02:12:22 ubuntu2004 dockerd[11651]: time="2021-01-28T02:12:22.520737199Z" level=info msg="Docker daemon" commit=8891c58 graphdriver(s)=>

Jan 28 02:12:22 ubuntu2004 dockerd[11651]: time="2021-01-28T02:12:22.520927136Z" level=info msg="Daemon has completed initialization"

Jan 28 02:12:22 ubuntu2004 systemd[1]: Started Docker Application Container Engine.

Jan 28 02:12:22 ubuntu2004 dockerd[11651]: time="2021-01-28T02:12:22.571192985Z" level=info msg="API listen on /run/docker.sock"

Jan 28 02:14:01 ubuntu2004 dockerd[11651]: time="2021-01-28T02:14:01.042676161Z" level=info msg="ignoring event" container=706c62976be8467ff71>

Jan 28 02:14:01 ubuntu2004 dockerd[11651]: time="2021-01-28T02:14:01.709602994Z" level=info msg="Layer sha256:5f05406a7838ba878004dc19a5202f6d>

Jan 28 02:14:03 ubuntu2004 dockerd[11651]: time="2021-01-28T02:14:03.931281935Z" level=info msg="ignoring event" container=2ee59dc155782d2c587>

Jan 28 02:14:04 ubuntu2004 dockerd[11651]: time="2021-01-28T02:14:04.536259329Z" level=info msg="Layer sha256:fab63bfda26955d7ac58d0e2916e0271>

lines 1-21/21 (END)

 

To verify the Docker version, run the following command:

docker -v

Output:

Docker version 20.10.2, build 2291f61

To verify the Docker Compose version, run the following command:

docker-compose -v

Output:

docker-compose version 1.25.0, build unknown

Create a Simple Go Application

First, create a directory for your project with the following command:

mkdir ~/myproject

Next, create a simple Go application with the following command:

nano ~/myproject/main.go

Add the following lines:

package main

import (

    "fmt"

    "html"

    "log"

    "net/http"

)

func main() {

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

        fmt.Fprintf(w, "This application is hosted with Docker, %q", html.EscapeString(r.URL.Path))

    })

 

  http.HandleFunc("/hi", func(w http.ResponseWriter, r *http.Request){

        fmt.Fprintf(w, "Hi")

    })

    log.Fatal(http.ListenAndServe(":80", nil))

}

Save and close the file when you are finished. The above application will listen on port 80 and print the message “This application is hosted with Docker /” after successful execution.

  • Create a Docker Compose File for Nginx

Next, you will need to create a Docker Compose file for Nginx. This will download the Nginx-proxy image and create an Nginx proxy container for the Go application.

You can create a Docker Compose file with the following command:

nano nginx-proxy-compose.yaml

Add the following lines:

version: '2'

services:

  nginx-proxy:

    restart: always

    image: jwilder/nginx-proxy

    ports:

      - "80:80"

    volumes:

      - "/etc/nginx/vhost.d"

      - "/usr/share/nginx/html"

      - "/var/run/docker.sock:/tmp/docker.sock:ro"

 

Save and close the file then change the directory to your project directory and build the Nginx proxy container with the following command:

 

cd ~/myproject

docker-compose -f nginx-proxy-compose.yaml up -d




You should get the following output:




Creating network "myproject_default" with the default driver

Pulling nginx-proxy (jwilder/nginx-proxy:)...

latest: Pulling from jwilder/nginx-proxy

bb79b6b2107f: Pull complete

111447d5894d: Pull complete

a95689b8e6cb: Pull complete

1a0022e444c2: Pull complete

32b7488a3833: Pull complete

c45cf71bc68c: Pull complete

00d28348da58: Pull complete

190f1720abb7: Pull complete

a99149d671c6: Pull complete

c7e9f170fd7c: Pull complete

accc49186289: Pull complete

e67d699eb6f8: Pull complete

Digest: sha256:695db064e3c07ed052ea887b853ffba07e8f0fbe96dc01aa350a0d202746926b

Status: Downloaded newer image for jwilder/nginx-proxy:latest

Creating myproject_nginx-proxy_1 ... done
  • Create a Dockerfile

Next, you will need to create a Dockerfile to download Golang and Alpine image. You can create it with the following command:

 

nano ~/myproject/Dockerfile

 

Add the following lines:

FROM golang:alpine AS build

RUN apk --no-cache add gcc g++ make git

WORKDIR /go/src/app

COPY . .

RUN go get ./...

RUN GOOS=linux go build -ldflags="-s -w" -o ./bin/web-app ./main.go

FROM alpine:3.9

WORKDIR /usr/bin

COPY --from=build /go/src/app/bin /go/bin

EXPOSE 80

ENTRYPOINT /go/bin/web-app --port 80

Save and close the file when you are finished.

 

  • Create and Run Docker Compose File for Golang App

Next, you will need to create a Docker Compose file to create a container from the Docker image which you have downloaded in previous step.

You can create it with the following command:

nano ~/myproject/go-app-compose.yaml

Add the following lines:

version: '2'

services:

  go-web-app:

    restart: always

    build:

      dockerfile: Dockerfile

      context: .

    environment:

      - VIRTUAL_HOST=app.example.com

Save and close the file then change the directory to your project and run your Go application with the following command:

cd ~/myproject

docker-compose -f go-app-compose.yaml up -d

You should get the following output:

Step 1/11 : FROM golang:alpine AS build

alpine: Pulling from library/golang

596ba82af5aa: Pull complete

344f2904b0c6: Pull complete

d3bda26d9fa1: Pull complete

24e1a14bb4a2: Pull complete

f0b175b107d5: Pull complete

Digest: sha256:07ec52ea1063aa6ca02034af5805aaae77d3d4144cced4e95f09d62a6d8ddf0a

Status: Downloaded newer image for golang:alpine

Successfully built 3b45ca7113a5

Successfully tagged myproject_go-web-app:latest

You can verify all Docker images using the command below:

docker images

You should see the following output:

REPOSITORY             TAG       IMAGE ID       CREATED          SIZE

myproject_go-web-app   latest    3b45ca7113a5   24 seconds ago   10.1MB

<none>                 <none>    e7352aa7a608   27 seconds ago   511MB

golang                 alpine    6af5835b113c   8 days ago       300MB

jwilder/nginx-proxy    latest    509ff2fb81dd   2 months ago     165MB

alpine                 3.9       78a2ce922f86   9 months ago     5.55MB

You can also verify all containers with the following command:

docker ps

You should see the following output:

CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS                NAMES

bfa0bdb20b0c   myproject_go-web-app   "/bin/sh -c '/go/bin…"   40 seconds ago   Up 38 seconds   80/tcp               myproject_go-web-app_1

3a021f37e3a7   jwilder/nginx-proxy    "/app/docker-entrypo…"   3 minutes ago    Up 3 minutes    0.0.0.0:80->80/tcp   myproject_nginx-proxy_1
  • Access the Go Application

At this point, your Go application has been deployed. It listens on port 80 and binds to the domain app.example.com. You can access it using the URL http://app.example.com. You should see your Go application in the following page:

  • Conclusion

Congratulations! you have successfully deployed a Go application with Docker on Ubuntu 20.04. I hope you have now enough knowledge to deploy your own app in a containerized environment.

Also Read: How To Deploy Flask Application With Docker On Ubuntu?

LEAVE A REPLY

Please enter your comment!
Please enter your name here