I’m having difficulties setting up a golang dockerfile for a personal project.
project structure is:
Project
|
+-- log.go (contains main)
|
+-- go.mod
|
+-- hash
|
+-- hash.go
The app prints a random hash every 5 seconds and appends a timestamp to it.
File contents:
log.go
package main
import (
"fmt"
"github.com/postelniql/logger-output/hash"
"time"
)
func log() string {
dt := time.Now()
hash := hash.NewSHA1Hash()
return dt.Format("01-02-2006T15:04:05.000Z") + ": " + hash
}
func main() {
fmt.Println(log())
tick := time.Tick(5000 * time.Millisecond)
for range tick {
fmt.Println(log())
}
}
go.mod:
module github.com/postelniql/logger-output
go 1.19
hash.go:
package hash
import (
"crypto/sha1"
"fmt"
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
func NewSHA1Hash(n ...int) string {
noRandomCharacters := 32
if len(n) > 0 {
noRandomCharacters = n[0]
}
randString := randomString(noRandomCharacters)
hash := sha1.New()
hash.Write([]byte(randString))
bs := hash.Sum(nil)
return fmt.Sprintf("%x", bs)
}
var characterRunes =
[]rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
// RandomString generates a random string of n length
func randomString(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = characterRunes[rand.Intn(len(characterRunes))]
}
return string(b)
}
I scraped together the following Dockerfile:
FROM golang:1.19-alpine
WORKDIR /app
COPY go.mod ./
RUN apk add git
RUN go get github.com/postelniql/logger-output/hash
COPY *.go ./
RUN go build -o /logger-output-app
EXPOSE 8080
CMD [ "/logger-output-app" ]
However I keep getting this error (and similar sort of errors):
------
> [6/8] RUN go get github.com/postelniql/logger-output/hash:
#10 2.105 go: github.com/postelniql/logger-output/hash: no matching versions for
query "upgrade"
------
executor failed running [/bin/sh -c go get github.com/postelniql/logger-
output/hash]: exit code: 1
I’ve searched the web for hours trying to fix this, I genuinely don’t understand what’s wrong with it. I suspect I’m doing something wrong when it comes to dependency management in the Dockerfile.
I mention I’m a noob in go and am coding this as part of my learning process.
Please help me write a dockerfile that builds and runs.
Thanks!
2
Answers
This should work, explanation below.
Place the Dockerfile in your project so that you don’t have to clone the project inside (makes no sense).
Use 2-stage build to have a clean final image.
Use a different user than root to run the final binary.
Don’t expose any port since your app is not listening on any port.
Use ENTRYPOINT instead of CMD. This way you can later pass arguments on the
docker run
command line.You don’t need to
go get github.com/postelniql/logger-output/hash
: this is part of your local source tree and you have it locally. You do need to make sure youCOPY
it into your image.The changes in your Dockerfile aren’t complicated, but your Dockerfile isn’t that large to start with:
The Dockerfile in @Mihai’s answer should work too, since it also deletes the
go get your-own-application
line. The multi-stage build setup deletes the Go toolchain from the final build so you get a much smaller image out, but it’s also more complex and a little harder to debug.