Why does my remote build have a huge transferring context?

I recently noticed huge volume of data od flyctl deploy operation being sent. Viewing some other thread advising how to debug I did following:

fly console --dockerfile Dockerfile -C bash
Remote builder [redacted] ready
==> Building image with Docker
--> docker host: 24.0.7 linux x86_64
[+] Building 671.2s (13/13) FINISHED                                                                                       
 => [internal] load .dockerignore                                                                                     0.1s
 => => transferring context: 180B                                                                                     0.1s
 => [internal] load build definition from Dockerfile                                                                  0.2s
 => => transferring dockerfile: 379B                                                                                  0.1s
 => [internal] load metadata for docker.io/library/debian:bookworm                                                    0.6s
 => [internal] load metadata for docker.io/library/golang:1.24.1-bookworm                                             1.7s
 => [builder 1/4] FROM docker.io/library/golang:1.24.1-bookworm@sha256:fa1a01d362a7b9df68b021d59a124d28cae6d99ebd1a  36.8s
 => => resolve docker.io/library/golang:1.24.1-bookworm@sha256:fa1a01d362a7b9df68b021d59a124d28cae6d99ebd1a876e3557c  0.0s
 ...
 => [internal] load build context                                                                                   585.5s
 => => transferring context: 2.31GB                                                                                 585.5s
 => [stage-1 1/3] FROM docker.io/library/debian:bookworm@sha256:731dd1380d6a8d170a695dbeb17fe0eade0e1c29f654cf0a3a07  0.0s
 => CACHED [stage-1 2/3] RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*      0.0s
 => [builder 2/4] WORKDIR /usr/src/app                                                                                8.1s
 => [builder 3/4] COPY . .                                                                                           69.1s
 => [builder 4/4] RUN go build -v -o /run-app .                                                                      13.7s
 => [stage-1 3/3] COPY --from=builder /run-app /usr/local/bin/                                                        0.1s 
 => exporting to image                                                                                                0.1s 
 => => exporting layers                                                                                               0.1s 
 => => writing image [redacted]                                                                                       0.0s
 => => naming to [redacted]
--> Building image done                                                                                                    
==> Pushing image to fly
The push refers to repository [registry.fly.io/probe-holy-sunset-6371]
bccbf78d7fce: Pushed 
2444bcbeb7b7: Pushed 
4668f0f488e5: Layer already exists 
deployment-[redacted]: digest: [redacted] size: 952
--> Pushing image done
Image: [redacted]
Image size: 148 MB

Created an ephemeral machine [redacted] to run the console.
Connecting to [redacted]... complete
root@683900ea767e08:/# du -sh * .*
0       bin
4.0K    boot
0       dev
1.3M    etc
4.0K    home
0       lib
0       lib64
4.0K    media
4.0K    mnt
4.0K    opt
0       proc
12K     root
8.0K    run
0       sbin
4.0K    srv
0       sys
4.0K    tmp
150M    usr
6.1M    var
28M     .fly
28M     .fly-upper-layer

and whole application directory on my local machine is little over 200MB … so where does this transferring context: 2.31GB almost 10 minutes step comes from?

I wonder if there is a way to build the image locally, just using Docker, and seeing if the build context size can be displayed there. Perhaps the remote build has additional context, though I agree that sounds like a lot.

Try running the above command on your development machine.

What’s happening:

  • The builder stage in your Dockerfile has a command COPY . . which copies every file from your development machine except for those files listed in your .dockerignore file.
  • You have a separate stage which copies only the files from /usr/local/bin to your final image, leaving the rest behind.