Part 6: Using Docker In Earthly
To copy the files for this example ( Part 6 ) run
1
earthly --artifact github.com/earthly/earthly/examples/tutorial/go:main+part6/part6 ./part6
Copied!
Examples in Python, Javascript and Java are at the bottom of this page.

The WITH DOCKER Command

You may find that you need to run Docker commands inside of a target. For those cases Earthly offers WITH DOCKER. WITH DOCKER will initialize a Docker daemon that can be used in the context of a RUN command.
Whenever you need to use WITH DOCKER we recommend (though it is not required) that you use Earthly's own Docker in Docker (dind) image: earthly/dind:alpine.
Notice WITH DOCKER creates a block of code that has an END keyword. Everything that happens within this block is going to take place within our earthly/dind:alpine container.

Pulling an Image

1
hello:
2
FROM earthly/dind:alpine
3
WITH DOCKER --pull hello-world
4
RUN docker run hello-world
5
END
Copied!
You can see in the command above that we can pass a flag to WITH DOCKER telling it to pull an image from Docker Hub. We can pass other flags to load in artifacts built by other targets --load or even images defined by docker-compose --compose. These images will be available within the context of WITH DOCKER's docker daemon.

Loading an Image

We can load in an image created by another target with the --load flag.
1
my-hello-world:
2
FROM ubuntu
3
CMD echo "hello world"
4
SAVE IMAGE my-hello:latest
5
​
6
hello:
7
FROM earthly/dind:alpine
8
WITH DOCKER --load hello:latest=+my-hello-world
9
RUN docker run hello:latest
10
END
Copied!

A Real World Example

One common use case for WITH DOCKER is running integration tests that require other services. In this case we need to set up a redis service for our tests. For this we can user a docker-compose.yml.
docker-compose.yml
1
version: "3"
2
​
3
services:
4
redis:
5
container_name: local-redis
6
image: redis:6.0-alpine
7
ports:
8
- 127.0.0.1:6379:6379
9
hostname: redis
10
healthcheck:
11
test: ["CMD", "curl", "-f", "http://localhost:6379"]
12
interval: 1s
13
timeout: 10s
14
retries: 5
15
networks:
16
- go/part6_default
17
​
18
networks:
19
go/part6_default:
Copied!
main.go
1
package main
2
​
3
import (
4
"github.com/sirupsen/logrus"
5
)
6
​
7
var howCoolIsEarthly = "IceCool"
8
​
9
func main() {
10
logrus.Info("hello world")
11
}
Copied!
main_integration_test.go
1
package main
2
​
3
import (
4
"context"
5
"testing"
6
​
7
"github.com/go-redis/redis/v8"
8
"github.com/stretchr/testify/require"
9
)
10
​
11
func TestIntegration(t *testing.T) {
12
ctx := context.Background()
13
rdb := redis.NewClient(&redis.Options{
14
Addr: "redis:6379",
15
Password: "", // no password set
16
DB: 0, // use default DB
17
})
18
​
19
err := rdb.Set(ctx, "howCoolIsEarthly", howCoolIsEarthly, 0).Err()
20
if err != nil {
21
panic(err)
22
}
23
​
24
resultFromDB, err := rdb.Get(ctx, "howCoolIsEarthly").Result()
25
if err != nil {
26
panic(err)
27
}
28
require.Equal(t, howCoolIsEarthly, resultFromDB)
29
}
Copied!
1
VERSION 0.6
2
FROM golang:1.15-alpine3.13
3
WORKDIR /go-example
4
​
5
deps:
6
COPY go.mod go.sum ./
7
RUN go mod download
8
SAVE ARTIFACT go.mod AS LOCAL go.mod
9
SAVE ARTIFACT go.sum AS LOCAL go.sum
10
​
11
test-setup:
12
FROM +deps
13
COPY main.go .
14
COPY main_integration_test.go .
15
ENV CGO_ENABLED=0
16
ENTRYPOINT [ "go", "test", "github.com/earthly/earthly/examples/go"]
17
SAVE IMAGE test:latest
18
​
19
integration-tests:
20
FROM earthly/dind:alpine
21
COPY docker-compose.yml ./
22
WITH DOCKER --compose docker-compose.yml --load tests:latest=+test-setup
23
RUN docker run --network=default_go/part6_default tests:latest
24
END
Copied!
When we use the --compose flag, Earthly will start up the services defined in the docker-compose file for us. In this case, we built a separate image that copies in our test files and uses the command to run the tests as its ENTRYPOINT. We can then load this image into our WITH DOCKER command. Note that loading an image will not run it by default, we need to explicitly run the image after we load it.

More Examples

Javascript
Java
Python