Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Fix pnpm + docker #1385

Merged
merged 6 commits into from
May 5, 2022
Merged

Fix pnpm + docker #1385

merged 6 commits into from
May 5, 2022

Conversation

sarayourfriend
Copy link
Contributor

@sarayourfriend sarayourfriend commented May 4, 2022

Fixes

Fixes https://github.com/WordPress/openverse-frontend/runs/6283206618

Description

This PR does the following:

  • Pins pnpm to a specific version and updates instructions and installations of pnpm to indicate how to use the "pinned" version. We need a custom solution because volta does not yet support pinning pnpm and we don't use volta to install it in the docker builds anyway.
  • Removes the local docker-compose stack for the frontend. It was broken ever since the playwright dockerization and no one noticed, so I'm assuming it was not being used.
  • Updates documentation regarding the build
  • Removes the multi-stage docker build. Given that the development image is gone now, the multi-stage build gave us nothing. In fact, even before, it wasn't doing anything but making build times longer if you weren't using BuildKit, so good riddance! It's good to delete code.
  • Switches to using pnpm fetch to populate the store in the docker build from pnpm-lock.yaml instead of pnpm install. Details on how this works available on the documentation page for it here. I've cross referenced the API and usage with pnpm 7 and there are no differences from pnpm 6, so the "experimental" warning at the top of that documentation page can be safely ignored.
  • Updates the production image to run the app using the node user rather than root. This is a basic docker security best practice that we've been ignoring for a while. It's a simple fix here, especially without the multi-stage build, so why not.

Testing Instructions

Checkout this branch and run docker build . --build-arg PNPM_VERSION=$(cat .pnpm-version) -t openverse-frontend:latest and confirm that it builds a working image that you can run using docker run -it -p 127.0.0.1:8443:8443/tcp openverse-frontend:latest at localhost:8443.

Checklist

  • My pull request has a descriptive title (not a vague title like Update index.md).
  • My pull request targets the default branch of the repository (main) or a parent feature branch.
  • My commit messages follow best practices.
  • My code follows the established code style of the repository.
  • [N/A] I added or updated tests for the changes I made (if applicable).
  • I added or updated documentation (if applicable).
  • I tried running the project locally and verified that there are no visible errors.

Developer Certificate of Origin

Developer Certificate of Origin
Developer Certificate of Origin
Version 1.1

Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
1 Letterman Drive
Suite D4700
San Francisco, CA, 94129

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.


Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.

@sarayourfriend sarayourfriend added 🟧 priority: high Stalls work on the project or its dependents 🛠 goal: fix Bug fix 🤖 aspect: dx Concerns developers' experience with the codebase labels May 4, 2022
@sarayourfriend sarayourfriend requested a review from a team as a code owner May 4, 2022 08:27
@sarayourfriend sarayourfriend requested review from krysal and obulat May 4, 2022 08:27
@github-actions
Copy link

github-actions bot commented May 4, 2022

Storybook and Tailwind configuration previews: Ready

Storybook: https://wordpress.github.io/openverse-frontend/1385
Tailwind: https://wordpress.github.io/openverse-frontend/1385/tailwind

Please note that GitHub pages takes a little time to deploy newly pushed code, if the links above don't work or you see old versions, wait 5 minutes and try again.

You can check the GitHub pages deployment action list to see the current status of the deployments.

Comment on lines 37 to 39
- name: Set PNPM_VERSION
run: |
export PNPM_VERSION=$(cat .pnpm-version)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit surprised that this works. GitHub Actions docs recommend echo-ing to $GITHUB_ENV.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I will do that!

@obulat that is probably why it failed 🙂

@obulat
Copy link
Contributor

obulat commented May 4, 2022

There appears to still be a build error in the CI: Error: buildx failed with: error: failed to solve: process "/bin/sh -c pnpm install -r --offline" did not complete successfully: exit code: 1

@sarayourfriend sarayourfriend force-pushed the fix/pin-pnpm-dockerfile branch from 17291f3 to 8d06968 Compare May 4, 2022 18:57
@sarayourfriend
Copy link
Contributor Author

This is working and ready for review now @dhruvkb and @obulat . Thanks!

@zackkrida
Copy link
Member

Something we might want to document is that volta intends to add pnpm support eventually. There's an RFC and some discussion from 6 days ago: volta-cli/rfcs#46

They also discuss corepack, a Node first-party "experimental tool to help with managing versions of your package managers." that could be stable in the near future, and would theoretically replace volta for us.

@sarayourfriend
Copy link
Contributor Author

Something we might want to document is that volta intends to add pnpm support eventually

Where would you like to document this? The base README.md already mentions that volta doesn't fully support pnpm and links to the issue that the RFC is addressing.

@zackkrida
Copy link
Member

@sarayourfriend I didn't realize that, seems totally sufficient 👍

Dockerfile Show resolved Hide resolved
@krysal
Copy link
Member

krysal commented May 5, 2022

I can't build the image running PNPM_VERSION=$(cat .pnpm-version) docker build . openverse-frontend:latest, it throws:

"docker build" requires exactly 1 argument.
See 'docker build --help'.

Usage:  docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Perhaps the last part is for tagging? I tried this way:

PNPM_VERSION=$(cat .pnpm-version) docker build --tag openverse-frontend:latest .

but I got an error that Node-gyp needs Python and is not found 😟

Error output
#9 20.63 .../[email protected]/node_modules/core-js postinstall: Done
#9 20.66 .../[email protected]/node_modules/deasync install: gyp info it worked if it ends with ok
#9 20.66 .../[email protected]/node_modules/deasync install: gyp info using [email protected]
#9 20.66 .../[email protected]/node_modules/deasync install: gyp info using [email protected] | linux | arm64
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python 
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python Python is not set from command line or npm configuration
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python Python is not set from environment variable PYTHON
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python checking if "python3" can be used
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - "python3" is not in PATH or produced an error
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python checking if "python" can be used
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - "python" is not in PATH or produced an error
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python 
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python **********************************************************
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python You need to install the latest version of Python.
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python Node-gyp should be able to find and use Python. If not,
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python you can try one of the following options:
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - Use the switch --python="/path/to/pythonexecutable"
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python   (accepted by both node-gyp and npm)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - Set the environment variable PYTHON
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - Set the npm configuration variable python:
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python   npm config set python "/path/to/pythonexecutable"
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python For more information consult the documentation at:
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python https://github.com/nodejs/node-gyp#installation
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python **********************************************************
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! find Python 
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! configure error 
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack Error: Could not find any Python installation to use
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at PythonFinder.fail (/usr/local/lib/node_modules/pnpm/dist/node_modules/node-gyp/lib/find-python.js:330:47)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at PythonFinder.runChecks (/usr/local/lib/node_modules/pnpm/dist/node_modules/node-gyp/lib/find-python.js:159:21)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at PythonFinder.<anonymous> (/usr/local/lib/node_modules/pnpm/dist/node_modules/node-gyp/lib/find-python.js:202:16)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at PythonFinder.execFileCallback (/usr/local/lib/node_modules/pnpm/dist/node_modules/node-gyp/lib/find-python.js:294:16)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at exithandler (node:child_process:406:5)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at ChildProcess.errorhandler (node:child_process:418:5)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at ChildProcess.emit (node:events:527:28)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:289:12)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at onErrorNT (node:internal/child_process:478:16)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! stack     at processTicksAndRejections (node:internal/process/task_queues:83:21)
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! System Linux 5.10.104-linuxkit
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/pnpm/dist/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! cwd /home/node/app/node_modules/.pnpm/[email protected]/node_modules/deasync
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! node -v v16.15.0
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! node-gyp -v v8.4.1
#9 20.70 .../[email protected]/node_modules/deasync install: gyp ERR! not ok 
#9 20.70 .../[email protected]/node_modules/deasync install: Build failed
#9 20.71 Progress: resolved 2277, reused 0, downloaded 2180, added 2277, done
#9 20.71 .../[email protected]/node_modules/deasync install: Failed
#9 20.71  ELIFECYCLE  Command failed with exit code 1.
------
executor failed running [/bin/sh -c pnpm fetch]: exit code: 1

Aside from that, everything looks quite good in this PR.

@sarayourfriend
Copy link
Contributor Author

Sorry about leaving out the -t @krysal and the confusion. I've updated the PR testing instructions to have the argument flag.

But also, I got the build command totally wrong 🤦 I don't know why it worked locally for me 🤔

Here is the correct command to run to pass the build arg:

docker build . --build-arg PNPM_VERSION=$(cat .pnpm-version) -t openverse-frontend:latest

The PR description is updated as well. I will push an updated for the README now.

@obulat
Copy link
Contributor

obulat commented May 5, 2022

I get an error about python not being found by node-gyp for sentry. Is it looking for it on my computer?

#9 82.43 .../node_modules/@sentry/cli install: info sentry-cli Downloading from https://downloads.sentry-cdn.com/sentry-cli/1.71.0/sentry-cli-Linux-aarch64
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python 
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python Python is not set from command line or npm configuration
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python Python is not set from environment variable PYTHON
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python checking if "python3" can be used
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - "python3" is not in PATH or produced an error
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python checking if "python" can be used
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - "python" is not in PATH or produced an error
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python 
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python **********************************************************
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python You need to install the latest version of Python.
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python Node-gyp should be able to find and use Python. If not,
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python you can try one of the following options:
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - Use the switch --python="/path/to/pythonexecutable"
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python   (accepted by both node-gyp and npm)
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - Set the environment variable PYTHON
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python - Set the npm configuration variable python:
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python   npm config set python "/path/to/pythonexecutable"
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python For more information consult the documentation at:
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python https://github.com/nodejs/node-gyp#installation
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python **********************************************************
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! find Python 
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! configure error 
#9 82.44 .../[email protected]/node_modules/deasync install: gyp ERR! stack Error: Could not find any Python installation to use

@sarayourfriend
Copy link
Contributor Author

Inside the docker build it would be looking for it elsewhere in the image.

I have no idea why y'all get that and I don't though 🤔 It didn't happen in the CI either, it built successfully there.

I ran which python in the base node:16-alpine image and (expected) it doesn't exist for me either. Maybe @sentry/cli doesn't have a pre-built for ARM or something?

It looks a lot like this issue and we could resolve it by installing Python or maybe making a multi-arch build or something and only including Python in the arm build? 🤔

Copy link
Member

@krysal krysal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating the PR description and the README @sarayourfriend. The problem is indeed on macOS, I think we can omit it for now since it works in the CI, and we can do that as a separate improvement.

I tried in Debian and I got to build the image and run the app successfully, with some changes I mention here.

# ==
# application for development purposes
FROM node:16 AS dev
COPY --chmod=777 . /home/node/app
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --chmod=777 option requires installing BuildKit, this conflicts with the use of a non-root user, can we omit it?.

Suggested change
COPY --chmod=777 . /home/node/app
COPY . /home/node/app

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does BuildKit conflict with using a non-root user? Do you mean non-root user in the image or running rootless docker?

Copy link
Member

@krysal krysal May 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant the option to change permissions with 777 as the value and run it with a non-root user.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like chmod can be replaced with chown without requiring BuildKit.

https://docs.docker.com/engine/reference/builder/#copy

Comment on lines +7 to 8
USER node

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the user here it fails in my case due to "EACCES: permission denied". We can move this sentence just before the ENTRYPOINT.

Suggested change
USER node

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we move it before the entrypoint without chmoding the copied files, how would the node user have access to the files copied into its home directory?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why wouldn't it have access to its own directory? I tried these changes and the app runs normally as far as I've seen. Otherwise, I think it needs to be pointed out in the Docker section of the README that BuildKit is required, it did not work for me as it is currently.

Dockerfile Show resolved Hide resolved
@krysal
Copy link
Member

krysal commented May 5, 2022

I meant to comment before approving but this is really close to being completed anyway :)

Copy link
Contributor

@obulat obulat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I managed to run this on my Mac only by adding RUN apk add --no-cache python3 make g++ on line 4 of the Docker file. I'm OK with it running only on Linux, we only need to document that.
Edited to add: I got this line from https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#node-gyp-alpine

@sarayourfriend
Copy link
Contributor Author

@obulat I'll document that.

Could y'all try an experiment for me and try to run the built image from ghcr locally on your macs?

Running like this should do it (you may need to pull before but I think docker run does that automatically for you).

docker run -it -p 127.0.0.1:8443:8443/tcp ghcr.io/wordpress/openverse-frontend:sha-2597091

As long as it runs on mac then I'm okay with it not being able to build on mac... mostly because this particular build is meant as a CI artifact anyway but being able to get someone quickly running a specific version of the frontend on any computer is ostensibly useful. We could for example add another comment to PRs with the docker run ... above pre-filled with the latest image for the branch (a kind of "per-branch preview" until we are able to actually provision per-branch infrastructure and deployments... something a long way off).

@obulat
Copy link
Contributor

obulat commented May 5, 2022

I get a warning:

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested

But it runs fine!!! 🎉 And it starts really fast.

@obulat
Copy link
Contributor

obulat commented May 5, 2022

Oh, I also wanted to say that I've been using corepack for a while instead of Volta. It is supported in Jetbrains IDEs, too.

@krysal
Copy link
Member

krysal commented May 5, 2022

Same as @obulat, I ran it and it works! ✨ (with the warning).

What do you think of the suggested changes? @obulat @dhruvkb @zackkrida

Copy link
Member

@dhruvkb dhruvkb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the changes, especially the part where we drop Docker Compose usage in local development. I can't imagine any scenario where we'd want to use it.

@sarayourfriend
Copy link
Contributor Author

@krysal I'm going to merge this as is so that it stops failing on PRs but I will open a follow up to use chown instead of chmod.

@sarayourfriend sarayourfriend merged commit 9884406 into main May 5, 2022
@sarayourfriend sarayourfriend deleted the fix/pin-pnpm-dockerfile branch May 5, 2022 22:31
@krysal krysal mentioned this pull request Aug 1, 2022
1 task
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
🤖 aspect: dx Concerns developers' experience with the codebase 🛠 goal: fix Bug fix 🟧 priority: high Stalls work on the project or its dependents
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants