Reduce production image size and follow best practices #610
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
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:
Description
The second problem is pretty easy to fix. We can follow the example in this SO post (note that
alpine
usesadduser
instead ofuseradd
; 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:
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 duringpnpm 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 usingpnpm 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:dependencies
only runtime dependencies and put everything else (including build deps) indevDependencies
dependencies
, build deps indevDependencies
and pure dev dependencies (like linters, formatters, etc) inoptionalDependencies
.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:dependencies
optionalDependencies
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
: Onlydependencies
andoptionalDependencies
--dev, -D
: OnlydevDependencies
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:
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
The text was updated successfully, but these errors were encountered: