Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

godep vendor with docker

Tags:

docker

go

I'm trying to run a docker container with vendor. This is my Dockerfile

FROM golang:alpine 
EXPOSE 8080

RUN mkdir /app 
ADD . /app/ 
WORKDIR /app 
RUN go build -o myapp . 
CMD ["/app/myapp"]

and my main.go

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/mux"
)

func main() {

    r := mux.NewRouter()
    r.HandleFunc("/", Hello)

    http.Handle("/", r)
    fmt.Println("Starting up on 8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func Hello(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(w, "Hello world!")
}

I'm using godep for vendoring libs, it's working in my local machine, but when i'm trying to run it with docker with :

docker build -t myapp-img .
docker run -p 8080:8080 --name myapp-cnt myapp-img

I have the following error :

main.go:8:2: cannot find package "github.com/gorilla/mux" in any of:
        /usr/local/go/src/github.com/gorilla/mux (from $GOROOT)
        /go/src/github.com/gorilla/mux (from $GOPATH)

I don't understand what is missing.

like image 952
sbouaked Avatar asked Oct 31 '16 11:10

sbouaked


1 Answers

The error is correct. It is telling you everything an aspiring Gopher needs.

I am going to assume that you have copied Gorilla Mux to your app's /vendor directory in your local machine, like so:

./main.go # this is your myapp code you are coping
./vendor/github.com/gorilla/mux # for vendoring, this must exist

If you want to learn more about vendoring, see my popular answer here:

How should I use vendor in Go 1.6?

Now, to fix that error assuming you have done the above...

A Gopher needs to set a valid $GOPATH before you can build. This is missing from your Dockerfile.

FROM golang:1.7-alpine 
EXPOSE 8080

# setup GOPATH and friends
#
# TECHNICALLY, you don't have to do these three cmds as the 
# golang:alpine image actually uses this same directory structure and
# already has $GOPATH set to this same structure.  You could just
# remove these two lines and everything below should continue to work.
#
# But, I like to do it anyways to ensure my proper build
# path in case I experiment with different Docker build images or in
# case the #latest image changes structure (you should really use
# a tag to lock down what version of Go you are using - note that I
# locked you to the docker image golang:1.7-alpine above, since that is
# the current latest you were using, with bug fixes).
#
RUN  mkdir -p /go/src \
  && mkdir -p /go/bin \
  && mkdir -p /go/pkg
ENV GOPATH=/go
ENV PATH=$GOPATH/bin:$PATH   

# now copy your app to the proper build path
RUN mkdir -p $GOPATH/src/app 
ADD . $GOPATH/src/app

# should be able to build now
WORKDIR $GOPATH/src/app 
RUN go build -o myapp . 
CMD ["/go/src/app/myapp"]

Here it is working...

$ tree
.
├── Dockerfile
├── main.go
└── vendor
    └── mydep
        └── runme.go

The source file of my app:

$ cat main.go
package main

import (
        "fmt"

        "mydep"
)

func main() {
        fmt.Println(mydep.RunMe())
}

My dependency in my vendor/ folder:

$ cat vendor/mydep/runme.go
package mydep

// RunMe returns a string that it worked!
func RunMe() string {
        return "Dependency Worked!"
}

Now, build and run the image:

$ docker build --rm -t test . && docker run --rm -it test
(snip)
Step 8 : WORKDIR $GOPATH/src/app
 ---> Using cache
 ---> 954ed8e87ae0
Step 9 : RUN go build -o myapp .
 ---> Using cache
 ---> b4b613f0a939
Step 10 : CMD /go/src/app/myapp
 ---> Using cache
 ---> 3524025080df
Successfully built 3524025080df
Dependency Worked!

Note the last line that prints the output from console, Dependency Worked!.

It works because:

  1. you stated you are using Vendoring, which means you have a local directory called ./vendor in the root of your application code.
  2. when you ADD . /go/src/app, you are also copying the ./vendor local to your application code.
  3. you have copied your files into the proper $GOPATH setup structure required by the Go build tools to find packages (and in this case, the ./vendor directory within your source code's root folder).
like image 91
eduncan911 Avatar answered Nov 08 '22 01:11

eduncan911