-
Notifications
You must be signed in to change notification settings - Fork 88
Pointers to other tools? Alternatives to MOUNT? #199
Comments
Hey, @hartym. Thanks for bringing it up. I agree with you, not all rocker's features can be covered, at least, from what I could find quickly. We may need to change the disclaimer to make it more clear. Let's go through those features in more detail:
To summarize, there are no straightforward solutions to the problems which Rocker aimed to solve. But to be honest, Rocker is not an elegant solution either – it just hides those problems under the carpet. Thanks again and feel free to share your solutions/ideas regarding problems mentioned above. |
The great thing about MOUNT is that it works with any package manager that keeps a local cache anywhere. I've used it with great success with yum, pear, composer, npm and even cached 3rd party git repos. Trying to cache all of those through any kind of http proxy quickly becomes infeasible, sometimes you can find an upstream for your package manager that's not over https and then introduce a proxy, but even if that works, you need a proxy environment variable to dynamically exist based on whether you're caching things. If you have a package manager that requires https (or is a git repo...) then you can't just trivially intercept it with a proxy and you're now dealing with custom certs and injecting custom local CAs in to the OS before installing any packages - which'll work great until package managers start pinning certs/CAs and then we're back to needing MOUNT again. I don't really expect you specifically to solve this, I'm just trying to highlight that I don't think the http approach is portable enough whereas MOUNT works with nearly anything and combined with a little intelligence it's possible to invalidate the build cache at exactly as reasonable a time as you would with a http cache. |
Thanks for this extensive answer @ybogdanov ! Definitely some good pointers there and honnestly, 1/3/4/5 are realy things I can live very well without.
I'm still wondering about MOUNT. I did not know about Pretty much my use case was mounting package manager cache directories ( The usual argument for not allowing such a thing is indeed "we want immutable / reproductible builds", but that this is already broken: we can "RUN" commands in docker containers that have random side effects, for example a Note that I'm not complaining here, I just really think the Also, I hear your point with huge Rockerfiles that are hard to maintain, I also feel that this is true both for Rocker and Docker-files. I guess my answer is not that useful here, but I wanted you to know that, indeed, this feature was appreciated to a huge extent. And if someone has a good solution for this (yes, I thought about the proxies, but as @neerolyte stated, that's language/package manager specific, and quite a pain to setup. With same drawbacks), let me know! Cheers, keep up the good work! |
Thanks for your comments, @neerolyte and @hartym. Your points are absolutely correct, and I understand and share your struggle. I was thinking in the background about the MOUNT issue during the last couple of days; there should be alternative ways to keep cache across invalidated builds. Here is one of the approaches that came to my mind today, I called it "Interstellar":
I've pushed the PoC to the interstellar branch, see Please let me know whether this approach works for you. build.sh: # "Interstellar" – PoC of MOUNT alternative with vanilla Docker
#
# This Dockerfile + build.sh illustrates how to keep cache of package managers
# and build systems between different build executions even after RUN layer
# invalidation. This trick help survive without Rocker's MOUNT.
#
# See the discussion https://github.com/grammarly/rocker/issues/199
set -e
# Make sure there is empty directory during the first run
mkdir -p .cache/go-build
# Do a normal build
docker build -t grammarly/rocker:latest -f Dockerfile .
# Use the label trick to get the ID of the latest layer containing cache of Go's compiler
CACHE_LAYER=`docker images --filter "label=rocker_build_cachepoint=true" --format "{{.ID}}" | head -n 1`
# The next command overwrites any older cache, we may improve it by using `rsync` instead of `cp`
echo "Downloading the latest build cache..."
rm -R .cache/go-build
# Store locally the cache left after the latest build
docker run --rm -ti -v `pwd`/.cache:/parent_cache $CACHE_LAYER \
/bin/bash -c 'cp -R /root/.cache/go-build /parent_cache/go-build' Dockerfile: FROM golang:latest as builder
COPY . /go/src/github.com/grammarly/rocker
WORKDIR /go/src/github.com/grammarly/rocker
# Note that on the first "cold" run the local directory ".cache/go-build" is empty
COPY .cache/go-build /root/.cache/go-build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install -v
# We use the trick with LABEL to be able to find this layer in build.sh
LABEL rocker_build_cachepoint=true
# Use Docker's multistage build feature to promote only our statically-built rocker binary
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/bin/rocker /bin/rocker
CMD ["/bin/rocker"] |
After some time of thinking about it, I concluded that "interstellar" approach doesn't solve the problem entirely and there are multiple problems with it:
I don't think this approach is even close to MOUNT's robustness. I started researching and stumbled upon https://github.com/moby/buildkit, and it looks very promising. I recommend reading the Introductory blog post. Didn't have a chance to examine the "MOUNT" issue in particular, but I think it is a good candidate for a Rocker replacement in general. |
Hi Yuriy, Yes, it's mostly what I meant by "the future is probably buildkit-based", but to be honest, it's much more low-level plumbery than something we can really use for now, I mean without investing a lot of time in implementation details. The future tools, including For now, I went back to regular Dockerfiles. There are also nice things doing so, but I'm feeling like we're missing a tool right now, especially when we build multiple variants of the same image, (like someapp, someapp-with-ml-libraries, someapp-for-prod, etc.) which share a lot of build steps and forces to duplicate large parts of dockerfiles, as of now. And feeling the pain again of not having the package manager downloads cached ... I guess this step back is what is needed to make the two step forward soon with buildkit-based awesomeness. Still we're not quite there. :) |
We use
This allow build-process to pull a private git repo. With this trick, everyone with access to the private repo, can build it (an there is no need to push credentials in docker-file, or similar place), and it integrates well with jenkins. This can be done ONLY with real mount (which makes mounting sockets available), and not achievable with copy-like commands. |
So I realised that with a fair bit of messing around you can always simulate # build all our deps in to it
args=(
docker run -it
-v "$PWD/.cache/yum:/var/cache/yum"
-v "$PWD:/scripts"
--name "$name"-tmp
"$mybaseimage"
/scripts/install_packages.sh
)
"${args[@]}"
# convert it to an image
docker stop "$name"-tmp
docker commit "$name"-tmp "$name"-tmp-image
# do some more docker buildy stuff to it
tmpdir=.tmpbuild-$$
mkdir "$tmpdir"
(
echo "FROM $name-tmp-image"
echo WORKDIR /foo
# ... whatever else you'd normally do in a Dockerfile ...
) > "$tmpdir/Dockerfile"
docker build -t "$name"-image "$tmpdir"
rm -rf -- "$tmpdir" Ugly, but I think I can get the desired behaviour without having to rely on Rocker. |
@neerolyte I was telling on a lot of build scripts like this before I found rocker, (building contexts in tars that you pipe in another docker build command ...) the main problem is that it is complex and hard to maintain ... |
MOUNT and ATTACH were always my aces in the hole for quickly and easily debugging issues during build processes, and nothing else has really replicated their ease of use yet as far as I know. I know the above isn't really contributing much value to this ticket but I felt I needed to mourn the loss of rocker after using it constantly for ~2 years :) Thanks for keeping it going as long as you did guys |
I have been using gitlab-ci as a replacement to I had liked using rocker a lot, but only started using rocker about a year ago and the project had started to look unsupported so I was tring to use only what I could not find in other tools that had support. The mulit-stage-builds along with still using gitlab-ci as part of my build stack, for the most part should cover what rocker did. I hope that for those that it can help with sharing what I use in place of mount will help. |
Just wanted to note, we have a similar issue around cache invalidation at SeatGeek, and built https://github.com/seatgeek/docker-build-cacher . This works pretty well for our use-case, but may not work for every |
Thanks, @josegonzalez ! |
Meanwhile, buildkit has been merged into the mainstream as experimental functionality. That means, soon we are probably to see native robust caching. Haven't tried that yet though. See moby/moby#37151 |
So sad to hear about the project discontinuation, but of course we all struggle with time and I understand.
Would it be possible to add a few pointers to other tools that can be used in the "much more mature [container ecosystem]" that we have today ? The homepage now says "most of the critical and outstanding features of rocker can be easily covered by docker build or other well-supported tools", but I have hard time finding tools I could consider in the future.
The future is probably buildkit-based, but it's not looking "mature" yet to me. Also, if the frontend is dockerfile-based, we still have the same issues than before (no volume mount, no artifact generation in dedicated images ...).
As far as I understand,
docker build
andDockerfile
language evolved to allow "multi-step" builds, but IMHO, this is insufficient to cover all use cases that Rocker covers.I tried to explore most tools found in awesome docker's build section (https://github.com/veggiemonk/awesome-docker#builder), but I can't find a tool as good, simple and flexible as rocker.
Do you have some pointers for us?
Thanks!
The text was updated successfully, but these errors were encountered: