Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce production image size and follow best practices #610

Closed
1 task
sarayourfriend opened this issue Feb 24, 2022 · 1 comment
Closed
1 task

Reduce production image size and follow best practices #610

sarayourfriend opened this issue Feb 24, 2022 · 1 comment
Labels
💻 aspect: code Concerns the software code in the repository ✨ goal: improvement Improvement to an existing user-facing feature 🟨 priority: medium Not blocking but should be addressed soon 🧱 stack: frontend Related to the Nuxt frontend 💬 talk: discussion Open for discussions and feedback 🐳 tech: docker Involves Docker

Comments

@sarayourfriend
Copy link
Collaborator

sarayourfriend commented Feb 24, 2022

This is a continuation of an exploratory PR I did here: WordPress/openverse-frontend#913

Problem

Currently the production image has at least two problems as far as I can tell:

  1. It includes development and build dependencies unnecessary for the application runtime
    • For example ESLint, TypeScript, Tailwind, webpack, etc.
  2. It runs the application as root rather a non-root user

Description

The second problem is pretty easy to fix. We can follow the example in this SO post (note that alpine uses adduser instead of useradd; the principle is the same though).

The first problem is a little trickier and will require some careful consideration as well as some additional research, mainly in identifying the dependencies that fall into the following three groups:

  1. Runtime
  2. Build
  3. Development (tools)

In particular with Nuxt, the distinction between runtime and build dependencies can be a little blurry: some parts of the @nuxt and @nuxtjs namespaces are build-time only (@nuxt/vue-app for example) while others are critical for the runtime of the application (like @nuxtjs/composition-api). The extent to which Nuxt depends on the raw source code of the application versus the output of the Webpack build created during pnpm build is also extremely unclear to me; in particular it's entirely opaque where Nuxt actually stores the output of the Webpack build, even when using pnpm build as it doesn't appear that application bundles exist under the output folder (.nuxt).

In any case, we'll need to document the differences between the development, build and runtime dependencies. package.json really only has the concept of dev and non-dev dependencies (along with optional and peer but those aren't really applicable to our case). I'm not totally sure what the best way to organize our dependencies is to make the distinction, but I suppose the most critical distinction we need to make is between runtime and build dependencies. I can see two options for this but I'm not sure which is best:

  1. We could make dependencies only runtime dependencies and put everything else (including build deps) in devDependencies
  2. We could put runtime dependencies in dependencies, build deps in devDependencies and pure dev dependencies (like linters, formatters, etc) in optionalDependencies.

I like the second one best; it uses semantics that already exist in package.json... but I'm afraid it uses them in the _wrong way. It might be more correct to do something like this:

  • runtime -> dependencies
  • build -> optionalDependencies
  • development -> devDependencies

I think that might be better due to the interfaces that pnpm exposes for deciding which dependencies to install, namely it gives you the following options:

  • --prod, -P: Only dependencies and optionalDependencies
  • --dev, -D: Only devDependencies are installed
  • --no-optional: A modification to --prod that will stop optional dependencies from being installed.

So basically, in my mind, I'm thinking that a Dockerfile could follow this sort of layout:

FROM node AS installer
# This will install _everything_ and build the foundational pnpm-store

RUN pnpm install --frozen-lockfile --store-dir=./pnpm-store

FROM installer AS dev
# Everything is already installed for development, so just let it run

RUN pnpm run dev

FROM installer AS builder
# Just build the application

RUN pnpm run build

FROM builder AS preprod
# Delete node_modules and reinstall only runtime deps

RUN rm -rf node_modules

# Reinstall only runtime deps using the `pnpm-store` to speed it up
RUN pnpm install --prod --no-optional --store-dir=./pnpm-store

FROM distroless AS prod
# Can use alpine, distroless, whatever

USER nonroot

COPY --from=preprod node_modules
COPY --from=preprod .nuxt
# etc, keep copying only what's necessary for runtime

RUN pnpm start

I think something like that is workable... we just need to decide how to organize dependencies and then identify which group each of our dependencies falls under (may just take trial and error to figure that out, or maybe there's a clearer way of discovering that).

Alternatives

We could just ignore the final production image size and just do the security improvements.

Implementation

  • 🙋 I would be interested in implementing this feature.
@sarayourfriend sarayourfriend added 🟩 priority: low Low priority and doesn't need to be rushed ✨ goal: improvement Improvement to an existing user-facing feature 💻 aspect: code Concerns the software code in the repository 💬 talk: discussion Open for discussions and feedback 🐳 tech: docker Involves Docker labels Feb 24, 2022
@obulat obulat transferred this issue from WordPress/openverse-frontend Feb 22, 2023
@github-project-automation github-project-automation bot moved this to 📋 Backlog in Openverse Backlog Feb 23, 2023
@obulat obulat added the 🧱 stack: frontend Related to the Nuxt frontend label Feb 24, 2023
@krysal krysal added 🟨 priority: medium Not blocking but should be addressed soon and removed 🟩 priority: low Low priority and doesn't need to be rushed labels Mar 23, 2023
dhruvkb pushed a commit that referenced this issue Apr 14, 2023
Header with a banner image and some useful links (to the project board, the Make blog, Slack, etc.) added
a response to issue [#277](#277)
@sarayourfriend
Copy link
Collaborator Author

This is no longer relevant since the monorepo switch and is superceded by #3118

@sarayourfriend sarayourfriend closed this as not planned Won't fix, can't repro, duplicate, stale Nov 22, 2023
@github-project-automation github-project-automation bot moved this from 📋 Backlog to ✅ Done in Openverse Backlog Nov 22, 2023
@dhruvkb dhruvkb moved this from ✅ Done to 🗑 Discarded in Openverse Backlog Nov 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💻 aspect: code Concerns the software code in the repository ✨ goal: improvement Improvement to an existing user-facing feature 🟨 priority: medium Not blocking but should be addressed soon 🧱 stack: frontend Related to the Nuxt frontend 💬 talk: discussion Open for discussions and feedback 🐳 tech: docker Involves Docker
Projects
Archived in project
Development

No branches or pull requests

3 participants