如何在Docker中正确运行Golang应用程序?
I developed Golang application in Windows 10. In my local machine it works fine. I remove source code to remote CentOS server which has Docker. Right now I am trying to run this application in Docker.
I created Dockerfile in the same folder where located main.go file.
- questionnaire
- database
- routes
- utils
- models
- controllers
main.go
Dockerfile
Dockerfile looks like this:
FROM golang:1.12
RUN go get github.com/gorilla/mux && \
go get github.com/gorilla/handlers && \
go get github.com/lib/pq && \
go get github.com/joho/godotenv && \
go get github.com/jinzhu/gorm && \
go get github.com/go-goracle/goracle
COPY / ./
EXPOSE 8000
CMD ["go", "run", "main.go"]
My main.go file looks pretty simple:
package main
import (
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/joho/godotenv"
"log"
"net/http"
"questionnaire/database"
"questionnaire/routes"
"questionnaire/utils"
)
func main() {
err := godotenv.Load(".env")
if err != nil {
panic(err)
}
database.ConnectOracle()
defer database.DisconnectOracle()
router := mux.NewRouter()
headers := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"})
methods := handlers.AllowedMethods([]string{"GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS"})
origins := handlers.AllowedOrigins([]string{"*"})
router.StrictSlash(true)
routes.Handle(router)
port := utils.CheckEnvironmentVariable("APPLICATION_PORT")
log.Printf("RESTful web service is running on %s port.", port)
log.Fatal(http.ListenAndServe(":" + port, handlers.CORS(headers, methods, origins)(router)))
}
I successfully created Docker Image but I have error when created Docker Container:
main.go:9:2: cannot find package "questionnaire/database" in any of:
/usr/local/go/src/questionnaire/database (from $GOROOT)
/go/src/questionnaire/database (from $GOPATH)
main.go:10:2: cannot find package "questionnaire/routes" in any of:
/usr/local/go/src/questionnaire/routes (from $GOROOT)
/go/src/questionnaire/routes (from $GOPATH)
main.go:11:2: cannot find package "questionnaire/utils" in any of:
/usr/local/go/src/questionnaire/utils (from $GOROOT)
/go/src/questionnaire/utils (from $GOPATH)
Can anyone say how to fix this problem?
I also tried to build binary of golang application inside Docker by next Dockerfile but error message was the same RUN go build
command:
FROM golang:1.12
RUN go get github.com/gorilla/mux && \
go get github.com/gorilla/handlers && \
go get github.com/lib/pq && \
go get github.com/joho/godotenv && \
go get github.com/jinzhu/gorm && \
go get gopkg.in/goracle.v2
ADD . /go/src/questionnaire
WORKDIR /go/src/questionnaire
RUN go build -o /bin questionnaire
ENV PORT=8000
CMD ["/bin"]
The imports in your main.go
file specify:
"questionnaire/database"
"questionnaire/routes"
"questionnaire/utils"
This means the go compiler is looking for those packages in $GOPATH/questionnaire
and $GOROOT/questionnaire
. You have to make sure those are copied into the correct place inside the docker image you are building.
The default $GOPATH inside that golang:1.12
image is /go
. Make sure your questionnaire package is correctly placed in the /go/src
directory inside the docker image.
As for the Dockerfile: A common strategy when building / deploying Docker images for go apps is to use a builder pattern (see example Dockerfile below). The gist of it is to create a multi-stage Dockerfile, where the first stage builds the go executable, and the second stage runs it. This means you can isolate all of your dependencies in the first stage, and end up with a very small overall image at the end.
It might look something like this:
FROM golang:1.11-alpine AS builder
########
# Prep
########
# add the source
COPY . /go/src/questionnaire
WORKDIR /go/src/questionnaire/
########
# Build Go Wrapper
########
# Install go dependencies
RUN go get github.com/gorilla/mux && \
go get github.com/gorilla/handlers && \
go get github.com/lib/pq && \
go get github.com/joho/godotenv && \
go get github.com/jinzhu/gorm && \
go get github.com/go-goracle/goracle
#build the go app
RUN GOOS=linux GOARCH=amd64 go build -o ./questionnaire ./main.go
########
# Package into runtime image
########
FROM alpine
# copy the executable from the builder image
COPY --from=builder /go/src/questionnaire .
ENTRYPOINT ["/questionnaire"]
EXPOSE 8080
Hope this helps!
(edited to reflect the comments below)