Hi there!
We’re currently investigating the usage of Nix for managing our dependencies, to make onboarding to our app for new developers easier.
Besides this, we’re looking to re-use much of the same for our deployment (for the reasons of having a single source of truth instead of having to maintain two disparate build procedures side-by-side).
Currently, deployment is Dockerfile-based (based on this template).
We tried using the dockerTools
in a naive way:
dockerImage = pkgs.dockerTools.buildImage {
name = "our-app";
copyToRoot = pkgs.buildEnv {
paths = [ rubyProdEnv ];
pathsToLink = [ "/bin" ];
};
config = {
WorkingDir = "/app";
Volumes = {
"/app" = {};
};
Cmd = [ "${rubyProdEnv.bundler}/bin/bundler exec puma -C config/puma.rb" ];
};
};
But this creates very large (2GB rather than < 200MB as with the current Dockerfile) images.
(And it might be wrong in some other ways as well).
Diving inside the resulting Docker image, we can see that:
- All gems and their transitive dependencies are included, and not only those that are part of the ‘production’ ruby environment.
- Any other build tools are included. The resulting image contains perl, python3, nodeJS, imagemagick, V8, ghostscript, etc.
So my question is twofold:
- How to limit the gems which
bundix
loads to only the ones which are used in production? - How to strip away anything that is only used during ‘building’ (such as NodeJS which precompiles some JS modules to files that browsers can understand) from the final generated image?