Home > database >  Need help setting up golang dockerfile
Need help setting up golang dockerfile

Time:09-27

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!

CodePudding user response:

This should work, explanation below.

#build stage
FROM golang:alpine AS builder

RUN apk add --no-cache git
WORKDIR /go/src/app
COPY . .

RUN go get -d -v ./...
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /go/bin/app -v .

#final stage
FROM alpine:latest

RUN addgroup -S app && adduser -S app -G app
COPY --from=builder --chown=app /go/bin/app /app
USER app

ENTRYPOINT ["/app"] 

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.

CodePudding user response:

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 you COPY it into your image.

The changes in your Dockerfile aren't complicated, but your Dockerfile isn't that large to start with:

FROM golang:1.19-alpine
WORKDIR /app
COPY go.mod go.sum ./    # add `go.sum`
RUN go mod download      # add: downloads external dependencies
# RUN apk add git        # delete
# RUN go get github.com/postelniql/logger-output/hash  # delete
COPY *.go ./
COPY hash/ hash/         # add
RUN go build -o /logger-output-app
EXPOSE 8080
CMD [ "/logger-output-app" ]

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.

  • Related