Earthfile
main.go
.base
target and are implicitly inherited by all other targets. Targets are just sets of instructions we can call on from within the Earthfile, or when we run Earthly at the command line. Targets need an environment to run in. These environments come in the form of Docker images. In this case we are saying that all the instructions in our Earthfile will use golang:1.15-alpine3.13
, unless we specify otherwise. (More on this in a bit.)/go-example
.targets
.earthly +build
.main.go
from the build context (the directory where the Earthfile resides) to the build environment (the containerized environment where Earthly commands are run).main.go
file./go-example
(it can be later referenced as +build/go-example
).+docker
./go-example
produced by another target, +build
, to the current directory within the build environment. Set the entrypoint for the resulting docker image.COPY +build/... ...
, which has an unfamiliar form. This is a special type of COPY
, which can be used to pass artifacts from one target to another. In this case, the target build
(referenced as +build
) produces an artifact, which has been declared with SAVE ARTIFACT
, and the target docker
copies that artifact in its build environment.go-example:latest
. This image is only made available to the host's docker if the entire build succeeds.+build
and +docker
targets. This is because targets inherit from the base target which for us was the FROM golang:1.15-alpine3.13
that we set up at the top of the file, but it's worth noting that targets can define their own environments. For example:+build
target does not have a FROM
, so it inherits from the base target, golang:1.15-alpine3.13
.+npm
, on the other hand, specifies its own environment with the FROM
command and so will run inside of a node:12-alpine3.12
container.Earthfile
we have defined two explicit targets: +build
and +docker
. We can tell Earthly to execute a target by passing typing a plus sign (+) followed by the target name. In this case our docker target calls on our build target, so we can run both with:|
, within the output, we can see some targets like +base
, +build
and +docker
. Notice how the output is interleaved between +docker
and +build
. This is because the system executes independent build steps in parallel. The reason this is possible effortlessly is because only very few things are shared between the builds of the recipes and those things are declared and obvious. The rest is completely isolated.build
and docker
, it is only executed once. This is because the system deduplicates execution, where possible.docker
target depends on the build
target is visible within the command COPY +build/...
. Through this command, the system knows that it also needs to build the target +build
, in order to satisfy the dependency on the artifact.