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
}
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
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? 🤔
Useful links for explanation
Here are some useful links that helped me understand the cause of the problem and solve it:
- https://en.wikipedia.org/wiki/Certificate_authority
- https://stackoverflow.com/a/76309552
- https://support.hashicorp.com/hc/en-us/articles/8107320508947-x509-certificate-signed-by-unknown-authority-
Feel free to post your own in the comments.
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
❗️ 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! 🎉
Photos and videos by
- Vic Shóstak https://github.com/koddr
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)
Great content. Sorry I only discovered it now. Thanks very much. This is the type of stuff no course teaches you!
Glad I could help. Thanks for the feedback!
very interesting post