Using brew to install dependencies in Dockerfile

I’d like to use homebrew linux to install packages in a Dockerfile build. What would be the appropriate steps to ensure only the installed packages remain?

I have yet to see any Dockerfiles that do this. I am interested in seeing examples if available. Specifically, I am interested in building a docker image to bootstrap a development environment with useful tools and language runtimes.

Having a RUN install_brew; brew bundle; remove_brew layer would be a lot more pleasant than a long shell script especially as not every package is available or up to date in apt repositories.

I’d suggest…

FROM homebrew/brew
RUN brew bundle

That’s interesting but I am looking to build a bionic image. Sourcing from homebrew/brew also means ~80 MB of extra stuff in the image. Is it possible to put this all in a single RUN statement and remove brew itself afterwards?

brew creates a lot of directories in /home/linuxbrew/.linuxbrew and as far as I can tell, there is no documentation that goes over what is needed there or the role of each directory.

That’s interesting but I am looking to build a bionic image.

I’ve been wanting to make an official Homebrew Docker image based on Ubuntu 18.04 LTS (Bionic Beaver). I’d be happy to do that.

Sourcing from homebrew/brew also means ~80 MB of extra stuff in the image.

I personally consider the size of the base image a sunk cost, that can be cached and amortized over its multiple uses. Your use case may differ of course.

Is it possible to put this all in a single RUN statement and remove brew itself afterwards?

Yep. I’ll leave that as an exercise to you, but the short instructions are install Homebrew on Linux, brew bundle, and then rm -rf /home/linuxbrew/.linuxbrew/Homebrew all in one RUN. That should work (untested).

Also rm -rf ~/.cache/Homebrew if you brew install anything.

A bionic image would be appreciated.

I see you have this now: https://github.com/Linuxbrew/docker/blob/master/bionic/Dockerfile
Looks like it has not been pushed to a registry yet.

A two-stage build may be the way to go. Looks like I’ll need to copy lib, sbin, etc, opt, bin, Cellar, and some of share

I agree that in most cases optimization of a base image size is not worth it. My use case here is to to deploy to a server with a 1 mbit link so less bytes are preferred.

A two-stage build may be the way to go. Looks like I’ll need to copy lib, sbin, etc, opt, bin, Cellar, and some of share

A two-stage build shouldn’t be necessary, but is an option. A one stage build would look something like this:

RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)" \
    && /home/linuxbrew/.linuxbrew/bin/brew bundle \
    && rm -rf /home/linuxbrew/.linuxbrew/Homebrew /root/.cache/Homebrew

Thank you. I will experiment with this. My concern with the above is that doing that may cause issues if another layer attempts to install or upgrade a package. Some state would have to be tracked so Homebrew can know if dependencies are already installed.

If you want Homebrew to be functional in your image to install or upgrade packages, then you want FROM homebrew/brew. If you remove Homebrew, you won’t be able to install or upgrade packages using Homebrew.