Skip to content

Commit

Permalink
feat: enable Corepack (pnpm support, unbundle yarn)
Browse files Browse the repository at this point in the history
This patch enables Corepack, allowing to use pnpm directly
and unbundling yarn from the default image.

Removing yarn also simplifies the image and the maintenance.

This change has been discussed in
nodejs#777.

Closes nodejs#777, nodejs#1645, nodejs#1755.
  • Loading branch information
dunglas committed Sep 7, 2022
1 parent 0fb3fac commit ea37959
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 153 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,6 @@ jobs:

- name: Test for yarn
run: docker run --rm node:${{ matrix.version }}-${{ matrix.variant }} yarn --version

- name: Test for pnpm
run: docker run --rm node:${{ matrix.version }}-${{ matrix.variant }} pnpm --version
4 changes: 1 addition & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ Thank you for your contribution. Here are a set of guidelines for contributing t

New **Node.js** releases are released as soon as possible.

New **NPM** releases are not tracked. We simply use the NPM version bundled in the corresponding Node.js release.

**Yarn** is updated to the latest version only when there is a new Node.js SemVer PATCH release (unless Yarn has received a security update), and it's updated only in the branch with the new release, preferably in the same PR. The `update.sh` script does this automatically when invoked with a specific branch, e.g. `./update.sh 6.10`.
New package manager releases are not tracked. We simply use the versions provided by [Corepack](https://github.com/nodejs/corepack).

### Submitting a PR for a version update

Expand Down
22 changes: 1 addition & 21 deletions Dockerfile-alpine.template
Original file line number Diff line number Diff line change
Expand Up @@ -57,31 +57,11 @@ RUN addgroup -g 1000 node \
fi \
&& rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \
&& apk del .build-deps \
&& corepack enable \
# smoke tests
&& node --version \
&& npm --version

ENV YARN_VERSION 0.0.0

RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \
&& for key in \
"${YARN_KEYS[@]}"
; do \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
done \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
&& gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& mkdir -p /opt \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& apk del .build-deps-yarn \
# smoke test
&& yarn --version

COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

Expand Down
21 changes: 1 addition & 20 deletions Dockerfile-debian.template
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,11 @@ RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \
&& tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs \
&& corepack enable \
# smoke tests
&& node --version \
&& npm --version

ENV YARN_VERSION 0.0.0

RUN set -ex \
&& for key in \
"${YARN_KEYS[@]}"
; do \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
done \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
&& gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& mkdir -p /opt \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
# smoke test
&& yarn --version

COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

Expand Down
34 changes: 1 addition & 33 deletions Dockerfile-slim.template
Original file line number Diff line number Diff line change
Expand Up @@ -41,43 +41,11 @@ RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \
| xargs -r apt-mark manual \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs \
&& corepack enable \
# smoke tests
&& node --version \
&& npm --version

ENV YARN_VERSION 0.0.0

RUN set -ex \
&& savedAptMark="$(apt-mark showmanual)" \
&& apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* \
&& for key in \
"${YARN_KEYS[@]}"
; do \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
done \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
&& gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& mkdir -p /opt \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& apt-mark auto '.*' > /dev/null \
&& { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \
&& find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
# smoke test
&& yarn --version

COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

Expand Down
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,10 @@ $ docker run node npm --loglevel=warn ...
## Image Variants

The `node` images come in many flavors, each designed for a specific use case.
All of the images contain pre-installed versions of `node`,
[`npm`](https://www.npmjs.com/), and [`yarn`](https://yarnpkg.com). For each
supported architecture, the supported variants are different. In the file:
[versions.json](./versions.json), it lists all supported variants for all of
the architectures that we support now.
All of the images contain pre-installed versions of `node`.
For each supported architecture, the supported variants are different.
In the file: [versions.json](./versions.json), it lists all supported variants
for all of the architectures that we support now.

### `node:<version>`

Expand Down
59 changes: 15 additions & 44 deletions docs/BestPractices.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,62 +27,33 @@ Run with `NODE_ENV` set to `production`. This is the way you would pass in secre
-e "NODE_ENV=production"
```

## Global npm dependencies

If you need to install global npm dependencies, it is recommended to place those dependencies in the [non-root user](#non-root-user) directory. To achieve this, add the following line to your `Dockerfile`
## Package Managers

```Dockerfile
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global

ENV PATH=$PATH:/home/node/.npm-global/bin # optionally if you want to run npm global bin without specifying path
```
Just use your package managers as you usually would.
They will be automatically installed by [Corepack](https://github.com/nodejs/corepack), which is enabled by default.

## Upgrading/downgrading Yarn
Corepack downloads your package managers the first time you use them.
It honors the [`packageManager` field of your `package.json`](https://nodejs.org/api/packages.html#packagemanager)
if defined.

### Local

If you need to upgrade/downgrade `yarn` for a local install, you can do so by issuing the following commands in your `Dockerfile`:

> Note that if you create some other directory which is not a descendant one from where you ran the command, you will end up using the global (dated) version. If you wish to upgrade `yarn` globally follow the instructions in the next section.
> When following the local install instructions, due to duplicated yarn the image will end up being bigger.
```Dockerfile
FROM node:6
As many production environments don't have network access,
you probably want to bundle your package managers in your Docker image.

ENV YARN_VERSION 1.16.0
To do so, add the following line to your `Dockerfile`:

RUN yarn policies set-version $YARN_VERSION
```

### Global

```Dockerfile
FROM node:6

ENV YARN_VERSION 1.16.0

RUN curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
&& ln -snf /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
&& ln -snf /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz
RUN corepack prepare
```

If you're using an Alpine-based image, `curl` won't be present, so you'll need to make sure it's installed while using it:
## Global npm dependencies

```Dockerfile
FROM node:6-alpine
If you need to install global npm dependencies, it is recommended to place those dependencies in the [non-root user](#non-root-user) directory. To achieve this, add the following line to your `Dockerfile`:

ENV YARN_VERSION 1.5.1
```Dockerfile
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global

RUN apk add --no-cache --virtual .build-deps-yarn curl \
&& curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
&& ln -snf /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
&& ln -snf /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz \
&& apk del .build-deps-yarn
ENV PATH=$PATH:/home/node/.npm-global/bin # optionally if you want to run npm global bin without specifying path
```

## Handling Kernel Signals
Expand Down
1 change: 0 additions & 1 deletion keys/yarn.keys

This file was deleted.

35 changes: 9 additions & 26 deletions update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ function usage() {
Examples:
- update.sh # Update all images
- update.sh -s # Update all images, skip updating Alpine and Yarn
- update.sh -s # Update all images, skip updating Alpine
- update.sh 8,10 # Update all variants of version 8 and 10
- update.sh -s 8 # Update version 8 and variants, skip updating Alpine and Yarn
- update.sh -s 8 # Update version 8 and variants, skip updating Alpine
- update.sh 8 buster-slim,buster # Update only buster's slim and buster variants for version 8
- update.sh -s 8 stretch # Update only stretch variant for version 8, skip updating Alpine and Yarn
- update.sh -s 8 stretch # Update only stretch variant for version 8, skip updating Alpine
- update.sh . alpine # Update the alpine variant for all versions
OPTIONS:
-s Security update; skip updating the yarn and alpine versions.
-s Security update; skip updating alpine version.
-b CI config update only
-h Show this message
Expand Down Expand Up @@ -67,7 +67,6 @@ arch=$(get_arch)

if [ "${SKIP}" != true ]; then
alpine_version=$(get_config "./" "alpine_version")
yarnVersion="$(curl -sSL --compressed https://yarnpkg.com/latest-version)"
fi

function in_versions_to_update() {
Expand Down Expand Up @@ -135,21 +134,16 @@ function update_node_version() {
sed -Ei -e 's/^FROM (.*)/FROM '"$fromprefix"'\1/' "${dockerfile}-tmp"
sed -Ei -e 's/^(ENV NODE_VERSION ).*/\1'"${nodeVersion}"'/' "${dockerfile}-tmp"

currentYarnVersion="$(grep "ENV YARN_VERSION" "${dockerfile}" | cut -d' ' -f3)"
sed -Ei -e 's/^(ENV YARN_VERSION ).*/\1'"${currentYarnVersion}"'/' "${dockerfile}-tmp"

# shellcheck disable=SC1004
new_line=' \\\
'

# Add GPG keys
for key_type in "node" "yarn"; do
while read -r line; do
pattern='"\$\{'$(echo "${key_type}" | tr '[:lower:]' '[:upper:]')'_KEYS\[@\]\}"'
sed -Ei -e "s/([ \\t]*)(${pattern})/\\1${line}${new_line}\\1\\2/" "${dockerfile}-tmp"
done < "keys/${key_type}.keys"
sed -Ei -e "/${pattern}/d" "${dockerfile}-tmp"
done
while read -r line; do
pattern='"\$\{'$(echo "node" | tr '[:lower:]' '[:upper:]')'_KEYS\[@\]\}"'
sed -Ei -e "s/([ \\t]*)(${pattern})/\\1${line}${new_line}\\1\\2/" "${dockerfile}-tmp"
done < "keys/node.keys"
sed -Ei -e "/${pattern}/d" "${dockerfile}-tmp"

if is_alpine "${variant}"; then
alpine_version="${variant#*alpine}"
Expand All @@ -169,17 +163,6 @@ function update_node_version() {
sed -Ei -e "s/(debian:)name-slim/\\1${variant}/" "${dockerfile}-tmp"
fi

if diff -q "${dockerfile}-tmp" "${dockerfile}" > /dev/null; then
echo "${dockerfile} is already up to date!"
else
if [ "${SKIP}" = true ]; then
# Get the currently used Yarn version
yarnVersion="$(grep "ENV YARN_VERSION" "${dockerfile}" | cut -d' ' -f3)"
fi
sed -Ei -e 's/^(ENV YARN_VERSION ).*/\1'"${yarnVersion}"'/' "${dockerfile}-tmp"
echo "${dockerfile} updated!"
fi

# Required for POSIX sed
if [ -f "${dockerfile}-tmp-e" ]; then
rm "${dockerfile}-tmp-e"
Expand Down

0 comments on commit ea37959

Please sign in to comment.