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

Use NODE_ENV ARG to control NPM install and tests #130

Closed
wants to merge 1 commit into from

Conversation

orangejulius
Copy link
Member

By using the Dockerfile ARG directive, we can set an ENV variable and control it via the --build-arg parameter to docker build.

Using this we can configure the Dockerfile to skip installing NPM dev dependencies and running unit tests.

In my testing this reduces the size of the Placeholder docker images from 290MB to 200MB, which is pretty huge! It reduces the time to build the image, reduces our surface area for security issues, and seems like an all around win.

orangejulius added a commit to pelias/ci-tools that referenced this pull request Sep 1, 2018
By using the `--build-arg` parameter to `docker build`, we can control
environment variables at build time.

Couple with changes like those in
pelias/placeholder#130, we can build images with
different settings in different cases.

In this example, I've chosen to set up the `production` images to skip
installing dev dependencies, making the images quite a bit leaner.
@missinglink
Copy link
Member

I actually like the idea of running tests when building the image, simply because they ensure that the environment is valid.

Eg. If I dev a feature on my mac, all the tests pass, I generate the image successfully and push it to dockerhub, we later find out that the docker image was missing a dynamically linked C lib and so it doesn't work as expected.

Totally fine with removing the dev dependencies 👍

@missinglink
Copy link
Member

We can avoid downloading and installing the 50MB+ phantomjs package by pinning it to jshint@2.9.5

@orangejulius
Copy link
Member Author

We need the devDependencies to run the tests though.

The workflow I had in mind was one where only the production images skip the tests/devDependencies. Since we always merge master->staging->production, there would be equivalent[1] images with/without the devDependencies/tests run for any change.

This ensures there exists a minimal, fast, secure image for production use, but also that there is a dev image for deeper exploration.

[1] The commit hash isn't identical right now, because we generate merge commits when going from master->staging and staging->production. With a little work we could do away with that, and then it would be very clear that two images are identical except for missing dev dependencies

By using the Dockerfile [ARG](https://docs.docker.com/engine/reference/builder/#arg)
directive, we can set an ENV variable and control it via the
`--build-arg` parameter to `docker build`.

Using this we can configure the Dockerfile to skip installing NPM dev
dependencies and running unit tests.

In my testing this reduces the size of the Placeholder docker images
from 290MB to 200MB, which is pretty huge! It reduces the time to build
the image, reduces our surface area for security issues, and seems like
an all around win.
@missinglink
Copy link
Member

missinglink commented Sep 3, 2018

So the issue we are trying to solve here is to not include dev dependencies in the docker image?
There is a separate/linked discussion of whether we want to run the tests inside the docker build.

I would tend towards something that is very simple, and having different environments during dev and production doesn't sound like a good idea to me.

If the problem we are trying to solve is the size of the dev dependencies then the simplest solution without compromising any functionality and also not not adding any complexity to the workflow is simply:

npm i && npm t && npm prune --production

ref: https://docs.npmjs.com/cli/prune

@orangejulius
Copy link
Member Author

orangejulius commented Sep 3, 2018

That's true, that would be simple. A downside there however, is we can't use our current system where NPM install is not needed at all when only code, but not package.json would change.

This would make local development significantly slower: every rebuild of an image locally would have to pay the cost of npm install (with dev dependencies) each time. This can easily take 30-60 seconds.

As it stands, with only code changed, the time to build a new docker image is approximately equal to the time to run npm test, which is often only a few seconds.

I also think there is value in having docker images with testing tools, as well as value having docker images that are as lean as possible. Having both lets us optimize for different situations.

@missinglink
Copy link
Member

jshint/jshint#3316

@orangejulius
Copy link
Member Author

It seems that once the jshint issue (referenced above) is resolved, and we roll out the changes to remove semantic-release from devDependencies (pelias/api#1187), this may not matter as much, as the total size of the devDependencies might not be much larger than installing only dependencies.

@orangejulius orangejulius deleted the no-dev-dependencies branch September 21, 2018 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants