13

When using a Dockerfile like this one:

FROM swift:latest
RUN mkdir foo && cd foo && swift package init
RUN cd foo && swift build && swift build
RUN cd foo && swift build

when the 3rd step is run, swift build will only compile the app once, as the second execution will just use the already build objects, and the output will be a single Compile Swift Module 'foo' (1 sources)

When running the 4th step, though, it seems to ignore whatever was already build, and rebuild the whole thing again, although nothing was changed and there was no clean. I've tried running a RUN ls /foo/.build && ls /tmp and everything seems to be in place.

What I'm trying to achieve in reality, is setup my image so I first clone the project from git, build it (so this "base" layer is cached by docker), then COPY in any change from the local machine and built just the new updates, but this end up building the whole project 2 times.

Any idea?

Edit: here's what my actual Dockerfile looks like:

FROM swift:latest
RUN git clone git@foo.com/foo.git
RUN cd /foo && swift build
COPY . /foo
RUN cd /foo && swift build

so ideally the first 3 layers will stay cached, and the last 2 would only build new changes, instead it ends up rebuilding the whole project

Fabio Ritrovato
  • 2,546
  • 1
  • 13
  • 19
  • I was playing with your example and it is a really really weird behavior of swift combined with something changing between docker executions. – Robert Aug 08 '18 at 21:29
  • just remove 1st build - you don't need it so you'll have `RUN git ... COPY . /foo RUN cd /foo && swift build` that's it. Why do you need "pre-build" before copy??? – Alex Aug 13 '18 at 20:46

1 Answers1

0

You need to validate that swift build is indeed capable to build incremental changes first (meaning, "in general", without involving docker)

A thread like "Compile Time Incredibly Slow" (using XCode, even with the option ""Xcode will not rebuild an entire target when only small changes have occurred." does not inspire confidence.

If swift build does rebuild everything, no amount of layer cache will avoid a full rebuild.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • I'm not trying to optimise for size, but for dev speed. A full rebuild of the app is slow, that's why I would want a layer that has some base build of the app, and a separate layer that only builds new changes... – Fabio Ritrovato Aug 08 '18 at 16:13
  • Added some clarification above – Fabio Ritrovato Aug 08 '18 at 16:22
  • @FabioRitrovato OK, I have a better understanding of the issue now. I have rewritten the answer accordingly. – VonC Aug 08 '18 at 16:56
  • As I mention above, If I run `swift build` twice in the same step (or locally without involving docker) it works as expected. It only rebuilds everything when run in different steps, even if no code change happened – Fabio Ritrovato Aug 08 '18 at 16:59
  • @FabioRitrovato But when you run twice, you make no modifcation between each run, no? – VonC Aug 08 '18 at 17:01
  • Yes, but the full rebuild happens even when there’s no modification between steps – Fabio Ritrovato Aug 08 '18 at 17:07
  • @FabioRitrovato so that seems more a swift issue, less a dockerfile "layer cache" one. – VonC Aug 08 '18 at 17:09