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

💡 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! 😻

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 projects that need your help (and stars) 👇

  • 🔥 gowebly: A next-generation CLI tool for easily build amazing web applications with Go on the backend, using htmx & hyperscript and the most popular atomic/utility-first CSS frameworks on the frontend.
  • 🍭 wonderful-readme-stats: A wonderful out-of-the-box and self-hosted solution for displaying statistics (stargazers, contributors, etc.) about your repository in your README file.
  • create-go-app: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.
  • 🏃 yatr: Yet Another Task Runner allows you to organize and automate your routine operations that you normally do in Makefile (or else) for each project.
  • 📚 gosl: The Go Snippet Library provides snippets collection for working with routine operations in your Go programs with a super user-friendly API and the most efficient performance.
  • 🏄‍♂️ csv2api: The parser reads the CSV file with the raw data, filters the records, identifies fields to be changed, and sends a request to update the data to the specified endpoint of your REST API.
  • 🚴 json2csv: The parser can read given folder with JSON files, filtering and qualifying input data with intent & stop words dictionaries and save results to CSV files by given chunk size.

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