Part 3: Adding dependencies With Caching
To copy the files for this example ( Part 3 ) run
earthly --artifact github.com/earthly/earthly/examples/tutorial/go:main+part3/part3 ./part3
Examples in Python, Javascript and Java are at the bottom of this page.

Dependencies

Now let's imagine that we want to add some dependencies to our app. In Go, that means adding go.mod and go.sum.
./go.mod
module github.com/earthly/earthly/examples/go
​
go 1.13
​
require github.com/sirupsen/logrus v1.5.0
./go.sum (empty)
​
The code of the app might look like this
./main.go
package main
​
import "github.com/sirupsen/logrus"
​
func main() {
logrus.Info("hello world")
}
Now we can update our Earthfile to copy in the go.mod and go.sum.
./Earthfile
VERSION 0.6
FROM golang:1.15-alpine3.13
WORKDIR /go-example
​
build:
COPY go.mod go.sum .
COPY main.go .
RUN go build -o build/go-example main.go
SAVE ARTIFACT build/go-example /go-example AS LOCAL build/go-example
​
docker:
COPY +build/go-example .
ENTRYPOINT ["/go-example/go-example"]
SAVE IMAGE go-example:latest
This works, but it is inefficient because we have not made proper use of caching. In the current setup, when a file changes, the corresponding COPY command is re-executed without cache, causing all commands after it to also re-execute without cache.

Caching

If, however, we could first download the dependencies and only afterwards copy and build the code, then the cache would be reused every time we changed the code.
./Earthfile
VERSION 0.6
FROM golang:1.15-alpine3.13
WORKDIR /go-example
​
build:
# Download deps before copying code.
COPY go.mod go.sum .
RUN go mod download
# Copy and build code.
COPY main.go .
RUN go build -o build/go-example main.go
SAVE ARTIFACT build/go-example /go-example AS LOCAL build/go-example
​
docker:
COPY +build/go-example .
ENTRYPOINT ["/go-example/go-example"]
SAVE IMAGE go-example:latest
For a primer into Dockerfile layer caching see this article. The same principles apply to Earthfiles.

Reusing Dependencies

In some cases, the dependencies might be used in more than one build target. For this use case, we might want to separate dependency downloading and reuse it. For this reason, let's consider breaking this out into a separate target called +deps. We can then inherit from +deps by using the command FROM +deps.
./Earthfile
VERSION 0.6
FROM golang:1.15-alpine3.13
WORKDIR /go-example
​
deps:
COPY go.mod go.sum ./
RUN go mod download
# Output these back in case go mod download changes them.
SAVE ARTIFACT go.mod AS LOCAL go.mod
SAVE ARTIFACT go.sum AS LOCAL go.sum
​
build:
FROM +deps
COPY main.go .
RUN go build -o build/go-example main.go
SAVE ARTIFACT build/go-example /go-example AS LOCAL build/go-example
​
docker:
COPY +build/go-example .
ENTRYPOINT ["/go-example/go-example"]
SAVE IMAGE go-example:latest

More Examples

Javascript
Java
Python
Copy link
On this page
Dependencies
Reusing Dependencies
More Examples