Skip to content

Instantly share code, notes, and snippets.

@BretFisher
Last active January 4, 2024 10:11
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save BretFisher/da34530726ff8076b83b583e527e91ed to your computer and use it in GitHub Desktop.
Save BretFisher/da34530726ff8076b83b583e527e91ed to your computer and use it in GitHub Desktop.
Multi-stage Dockerfile example of installing dependencies with COPY --from

Multi-stage Dockerfile example of installing dependencies with COPY --from

Reasons this exists:

  1. Often we need large tools in a image (even if just temporarily for a build-stage) that suffer from limits of the apt/yum package managers. In this Node.js example, apt only has specific versions that are tied to the OS version. I needed a more flexable way to add these without the bloat that sometimes comes with apt/yum installers. In addition, nodesource (recommeneded way to install Node.js via apt) requires Python and more to install Node.js.
  2. For languages (python, node, ruby, php, etc.) we're often using old versions, and those upstream images are usually outdated builds with a larger number of CVEs. A better aproach, for lowering CVEs, is to start from a ubuntu image, then install everything you need.
  3. By copying files between images, the installs are typically faster, take less space, and give you more control over versions and upstream build dates.
# any images you use later, add them here first to create aliases
# I like keeping all my versions at the top
FROM node:14.3-slim as node
FROM php:7.2.1-fpm-slim as php
FROM nginx:1.17 as nginx
# The real base image to start from
FROM ubuntu:focal-20210827 as base
# install apt stuff
# do other things before we install node
######
# install node
######
# new way to get node, let's copy in the specific version we want from a docker image
COPY --from=node /usr/local/include/node /usr/local/include/node
COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=node /usr/local/bin/node /usr/local/bin/node
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm
# now run node/npm commands
# maybe later I also need to add php or nginx
# use `dive` tool to find what files are needed in those apps
# then use COPY --from commands to get the bin/lib dirs that are necessary
@OzzyCzech
Copy link

OzzyCzech commented Sep 5, 2023

I have slightly updated version that will also link yarn and npx

FROM node:current-slim as node
FROM debian:bookworm-slim

# Install Node
COPY --from=node /usr/local/bin/node /usr/local/bin/node
COPY --from=node /usr/local/include/node /usr/local/include/node
COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
# Install yarn
COPY --from=node /opt/yarn-v*/bin/* /usr/local/bin/
COPY --from=node /opt/yarn-v*/lib/* /usr/local/lib/
# Link npm and yarn
RUN ln -vs /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
    && ln -vs /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment