DEV Community

Cover image for 💡 An important addition on deploying a Go application in Docker, if net/http is used
Vic Shóstak
Vic Shóstak

Posted on • Updated on

💡 An important addition on deploying a Go application in Docker, if net/http is used

Hey, everybody! 🙌

This is a short note article that I can't help but share with the community, as I ran into this problem myself in my latest wonderful-readme-stats project.

So, this will be a very short post, but so important for anyone who wants to deploy a Go application that uses the built-in net/http package, in a Docker container.

OK, here we go!

📝 Table of contents

Description of the problem

I have a helper in my Go project that helps me make a request to the GitHub API and return a response. It is absolutely simple, but saves time as it is used in many places in the code (DRY):

// customHTTPClient makes an HTTP request to download the image from the given URL and returns the response.
func customHTTPClient(uri string) (*http.Response, error) {
    // Check, if the URL is valid.
    _, err := url.Parse(uri)
    if err != nil {
        return nil, err
    }

    // Create a new HTTP client with options.
    client := &http.Client{
        Timeout: 15 * time.Second,
        Transport: &http.Transport{
            TLSHandshakeTimeout:   10 * time.Second,
            ResponseHeaderTimeout: 10 * time.Second,
            ExpectContinueTimeout: 1 * time.Second,
        },
    }

    // Make an HTTP request to download the image from the given URL.
    req, err := http.NewRequest(http.MethodGet, uri, http.NoBody)
    if err != nil {
        return nil, err
    }
    defer req.Body.Close()

    // Set authorization header.
    req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", os.Getenv("GITHUB_TOKEN"))

    // Send the request to the HTTP server.
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }

    return resp, nil
}
Enter fullscreen mode Exit fullscreen mode

You may have noticed that I use strictly defined options to create a custom HTTP client. This is done for a reason! For more information, see this Cloudflare blog post.

📝 Note: Building the project for the Docker image is done automatically with GoReleaser. Therefore, I will not cover Dockerfile in detail.

Next, I run the finished image as always with this command on the remote server (Ubuntu 22.04):

docker run -d -p 9876:9876 koddr/wonderful-readme-stats:latest
Enter fullscreen mode Exit fullscreen mode

But in the logs, I see the following error when trying to make a request from http.Client to the GitHub API: tls: failed to verify certificate: x509: certificate signed by unknown authority.

Wait a minute, why is that? 🤔

↑ Table of contents

Useful links for explanation

Here are some useful links that helped me understand the cause of the problem and solve it:

Feel free to post your own in the comments.

↑ Table of contents

Solving the problem

The solution was so simple that I didn't even believe it!

It was enough to add a Docker volume pointing to the directory of the server containing the certificates (/etc/ssl/certs) when starting the container to make it work:

docker run -d \
  -p 9876:9876 \
+  -v /etc/ssl/certs:/etc/ssl/certs:ro \
  koddr/wonderful-readme-stats:latest
Enter fullscreen mode Exit fullscreen mode

❗️ Important: Don't forget to add Docker volume in read-only mode (:ro).

And now the container works without errors and displays awesome statistics about the defined repository! 🎉

↑ Table of contents

Photos and videos by

P.S.

If you want more articles (like this) on this blog, then post a comment below and subscribe to me. Thanks! 😻

❗️ You can support me on Boosty, both on a permanent and on a one-time basis. All proceeds from this way will go to support my OSS projects and will energize me to create new products and articles for the community.

support me on Boosty

And of course, you can help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My main projects that need your help (and stars) 👇

  • 🔥 gowebly: A next-generation CLI tool that makes it easy to create amazing web applications with Go on the backend, using htmx, hyperscript or Alpine.js and the most popular CSS frameworks on the frontend.
  • create-go-app: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.

Other my small projects: yatr, gosl, json2csv, csv2api.

Top comments (3)

Collapse
 
pienaahj profile image
Hendrik Pienaar

Great content. Sorry I only discovered it now. Thanks very much. This is the type of stuff no course teaches you!

Collapse
 
koddr profile image
Vic Shóstak

Glad I could help. Thanks for the feedback!

Collapse
 
marcitpro profile image
Marcitpro

very interesting post