Golang Dependency Solution with Go Module and Docker
Photo by frank mckenna on Unsplash
I was working on creating a small service in Go earlier. Then I needed to build a Docker container for the service. Usually with Go application you will need some external packages/libraries and for that we use this command,
go get <the package source/URL >
So if you want to run the app with a Docker container you just created which depends on external packages then you will probably add something like this in the Dockerfile -
RUN go get ./...
And it works. But the problem with this approach is, every time you build the image with docker build comand, it will fetch all the dependency (packages) each time. Which is actually takes quite a bit time sometimes.
With Go module we have a better solution.
We can avoid this by copying the go.mod and go.sum files first. Then running the go mod download
Lets create simple Go server and we will run it with Docker. The code could be something like this and it should use at least one external package, in this case I’m using github.com/gorilla/mux for handling router.
Now before using Go module, lets create a Dockerfile and run the server with it.
$ touch Dockerfile
And content of the Dockerfile would be something like this
Run the command for building the docker image
$ docker build -t test-server .
This command will create an image called test-server, or if you chose another name. But you see if you change any bit of your code and run the command again it will fetch the packages again although we haven’t added any new dependencies. Now check if it created the image by running this command.
$ docker images
And run the container
$ docker run -p 8090:8090 test-server
You should see the message Listening on : 9000.
Add Go Module Link to heading
Now in your project root, run these commands for initiating Go module, downloading dependencies and keep those in vendor.
$ go mod init
$ go mod tidy
We solved the dependency problem for the app we have built. So, whenever you add a new library or dependency, Go module will fetch it automatically.
Now remove this line from the Dockerfile,
RUN go get ./...
And if you run the Docker build command you’ll see that it’s still fetching the dependencies. Although it copied the go.mod, go.sum and vendor directory. You can check that by adding this command to the Dockerfile,
RUN ls
To solve this problem we need to copy the go.mod and go.sum files first inside the container and then run the go mod download command to fetch the dependencies. To do that- add these line to the Dockerfile
COPY go.mod .
COPY go.sum .
RUN go mod download
And we are done. Now run Docker build command again and it’ll not fetch the packages unless you add a new dependency. So, the final Dockerfile should look something like this