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 do a Docker build it’ll run that command and will try get all the packages the app is using. Which is time consuming and not convenient in a way. With Go module we have a better solution.
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 change any bit of your code and run the command again it will fetch the packages again although we haven’t added a new package. Now check if it created the image by running this command.
$ docker images
And start the container,
$ docker run -p 8090:8090 test-server
You should see the message
Listening on : 9000.
###Add Go Module
If you haven’t used Go module before, the first step would be enabling it.
$ export GO111MODULE=on
Now in your project root, run these commands for initiating Go module, downloading dependencies and keep those in vendor.
$ go mod init
$ go mod download
$ go mod vendor
We solved the dependency problem for the app we have built. So, every time if 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,
To solve this problem we need to copy the go.mod and go.sum files and then run go mod download. 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