How to Deploy golang to production Step by Step

Golang is one of the best programming language to work with.It makes everything so easy during deployment as no dependancies or installation are needed.In this tutorial am going  to show you how to deploy a golang application to digital ocean.However you can use the same steps in any environment or hosting service.

Making A simple Go application

I assume at this point you have you go application ready but for the sake of clarity lets start by making a very small go api that will fetch us some jobs.

This will be our project structure.

The handlers.go- has all the handlers(controllers) we want to hook to our routes

The models.go-This contains all our model definition which in this case is  our job model.

The Main.go – This is our entry point where we shall serve our application from.

Defining our model

In this simple api we are going to use only one model.That is the job model.But in general an application has many models which may be defined here.

Write the following code in your models.go

 

For simplicity our model will only have two fields.

Writing a handler to get our jobs

Now that we have our model its time to write a handler that will fetch our jobs.The handler will return a json response which we can consume.

Lets go ahead and write our code in the handler.go.

The main.go

In this tutorial i am going to use the bone  Multiplexer  to handle my routing but feel free to use any router available.

You may check out  httprouter or even  gorrila mux but it all a matter of preference.

Open you main.go file and paste this code.

our simple go api is now complete test it by running:

on the terminal.

If you followed this code to the latter you can visit

You should see the jobs displayed.

Deploy go to digital ocean
How to deploy golang to digital ocean

Deploying our go app to digital  ocean

Now that we have our app ready it is time to deploy it.

I assume that your serve is running on a linux droplet thus i am going to compile our go application for linux.It does not matter which machine you are using for development as go . allows you to build for any os.In my case i am using a mac book which runs the macos but i will show you how to use it to build for linux

Building our app

Cd you project(where your main.go is located )and run this command to build for linux.

if you look at you folder you will notice that a new file called jobs has been created.This is the compiled binary file that is needed to execute our api.You just have to upload this file to your serve and run it.

Scp this binary file to the server(For instance for my case to upload it to my server i would write)

Replace the ip address with your droplet ip address and  (/var/www/go) with the location you want to store it.

Writing a systemd file to  manage our app

We  need a way to stop ,restart and start our golang app.For this we are going to write a systemd application which will simplify our job.

Create a unit file ending in .service within the /etc/systemd/system directory to begin:

Inside copy the following script.

Thats all is needed.

We can now start our script by simply running.

Now visit the port you configured you go app to use (Which in my case is :8080) your app should be running and ready for use.

Configuring Nginx to Proxy Requests

Using nginx with go is not really neccessary .For those who insist on using it let me show you how to configure golang to use nginx.

The nginx setup is very simple.

Begin by creating a new server block configuration file in Nginx’s sites-available directory. We’ll simply call this jobs to keep in line with the rest of the guide:

Open up a server block and tell Nginx to listen on the default port 80. We also need to tell it to use this block for requests for our server’s domain name or IP address:

Replace the port number with the port  you used.The server_name should also be replaced with you domain name.

To enable the Nginx server block configuration we’ve just created, link the file to the sites-enableddirectory:

With the file in that directory, we can test for syntax errors by typing:

If this returns without indicating any issues, we can restart the Nginx process to read the our new config:

  Conclusion

In this tutorial we have seen how to deploy a golang app to digital ocean in ubuntu.However you can user this same setup for any machine or server  running a linux distribution.I hope this tutorial helped you to understand how to deploy a golang app.

You can read more of our golang articles and leave a comment.

Happy Coding

 

 

 

 

 

7 thoughts on “How to Deploy golang to production Step by Step

  1. Hi, thanks for this write up. so simplified. a few notes though.
    [code]
    import (
    “net/http”
    “jobs/models”
    “encoding/json”
    )

    //make a slice to hold our jobs data
    var jobs []models.Job

    //A handler to fetch all the jobs
    func GetJobs(w http.ResponseWriter, r *http.Request) {
    ///add some job to the slice
    jobs = append(jobs, models.Job{ID: “1”,Name: “Accounting”})
    jobs = append(jobs, models.Job{ID: “2”,Name: “Programming”})
    json.NewEncoder(w).Encode(jobs)
    }[/code]

    1. I think the ID should be uint i.e unsigned int and not a string.
    2. secondly, I’ve compile to the jobs project and scp’ed it to a remote host, created and updated the jobs.service under /etc/systemd/system
    I reloaded daemon by by running: systemctl daemon-reload
    then I ran the following in sequence:
    sudo systemctl start jobs
    sudo systemctl enable jobs

    On visiting http://serverIPaddress/api/jobs in postman as well as browser,
    this is what is spit: Could not get response blah blah

    I went ahead to ensure port 8080 is open by running: sudo ufw allow 8080
    still no success,. May you kindly elaborate more on this last section. Is it necessary to install the GO SDK on the server before this binary can run?
    Thanks

    • You are not supposed to install any Go SDk on the server as long as you compiled for the os you are using on your server from your local host and uploaded your compiled binary file.

      i have a feeling that your (ExecStart=/home/path/to/binary/you/uploaded(which in my case is/var/www/go/jobs)) is wrong.

      what is the output of sudo systemctl status jobs ??

  2. Hi Keith,
    Thanks for writing. For some reasons (I can’t explain), it worked. This is what I did
    1. I ran the command systemctl daemon-reload
    2. Executed the binary: ./jobs IPAddress PortNo
    In my case I ran in terminal: ./jobs 178.128.74.225 8080
    visiting: http://178.128.74.225/api/jobs spit the following JSON object;
    [{“id”:1,”name”:”Accounting”},{“id”:2,”name”:”Programming”}]
    Every time I reload URL or send GET request in Postman, the above JSON Output duplicates and duplicates. May you explain why this happens? visit my demo URL http://178.128.74.225/api/jobs to see what am talking about.

    As you requested, here is the output of running: systemctl status jobs

    jobs.service – instance to serve jobs api
    Loaded: loaded (/etc/systemd/system/jobs.service; enabled; vendor preset: ena
    Active: active (running) since Thu 2018-07-26 05:55:02 UTC; 2 days ago
    Main PID: 4215 (jobs)
    CGroup: /system.slice/jobs.service
    └─4215 /home/GoDiehard/jobs

    I have a few question,
    1. May you kindly explain the relevance of NGINX in this whole setup.
    2. I’m writing a go web-application that has incremental changes. let’s use our jobs example above, I have jobs binary file Version 1 running on remote server, my local copy is now jobs binary file version 2. How do I overwrite the remote version 1 with my local version 2 copy with out disrupting active users or taking the application down. I tried to upload and replace remote Version 1 with local version 2 and this is the response am getting in Filezilla:
    Status: Connected to 178.128.74.225
    Status: Starting upload of /Users/Eagle/Documents/GoCode/src/jobs/jobs
    Status: Retrieving directory listing of “/home/GoDiehard”…
    Status: Listing directory /home/GoDiehard
    Command: put “/Users/Eagle/Documents/GoCode/src/jobs/jobs” “jobs”
    Error: /home/GoDiehard/jobs: open for write: received failure with description ‘Failure’
    Error: File transfer failed
    Status: Starting upload of /Users/Eagle/Documents/GoCode/src/jobs/jobs
    Status: Retrieving directory listing of “/home/GoDiehard”…
    Status: Listing directory /home/GoDiehard
    Status: Skipping upload of /Users/Eagle/Documents/GoCode/src/jobs/jobs

    Lastly, how do you format code on your website for clear readability, I tried [code]…[/code], seems not to work.
    Thanks

    • 1.Nginx is not really necessary but for me i use it as a proxy server.
      Imagine you have a domain something like (www.kenyaaapexperts.com)and you want people to use this to access your site instead of the ip and port number.At this point it i advisable to serve your application with nginx.
      2.I also use nginx when i want to add https to my apis or web application as its easier to do with nginx and its free.
      3.Another reason to use nginx is that it allow you to serve multiple application from the same droplet.(for example with nginx you can serve two sites like(kenyaappexperts.com and codesahara.com)
      4.You can not run two applications on the same port….To replace the first app version you have to first stop the older version and upload a new one…or alternatively if you want to have two apps running …you can change the port number of the second version to let say something like (8080) and you will have your two apps running.

      5.Before you make changes to an uploaded binary you have to stop it first with (systemctl stop jobs)

      • Hi Keith, Thanks for the resourceful information you’ve provided.
        1. What do you say about this, Digital ocean allows you to add a domain to your droplet, and gives you the name servers to use at your domain registrar to point to your droplet IP address. Does this imply there’s some sort of Web server running in the background say Apache, nginx etc? I’ve linked these domains in the past but on python-related projects for demo purposes, during deployment, I never encountered stuff like nginx.
        4. Does it imply that when I run “systemctl stop jobs” the application goes offline in its entirety. let’s assume you want to update codesahara.com (a Go powered web application), you have users logged in and taking courses, would the website go off when you temporarily run “systemctl stop jobs”? I’ve on several occasions been updating my PHP sites even when user are online and it everything would work fine. So am just wondering if this would be the case with a with GO.

        This is off topic but would be good if you shared some tips, is a like like codesahara.com or KenyaAppExperts.com capable of running on a $5 droplet? if now what droplet is suitable for such sites (on average), with user login systems, databases.
        Thank you
        Drew

        • Correction on typos: ** Is a SITE like codesahara.com or KenyaAppExperts.com capable of running on a $5 droplet? if now what droplet is suitable for such sites (on average), with user login systems, databases.

          • Yah They can easily run on such a droplet…the good thing with digital ocean is you can easily scale when you get more users.
            It also depends on how you make your site and how it utilizes your resources.
            In fact one of my app which has over 10k user runs on a 5 dollar droplet without any issues.(on that app i used flask for the api which consumes more resources than go)

Leave a Comment