Docker + NPM Enterprise

I was recently evaluating the latest edition of N|Solid on a project that utilizes a few modules from our private NPM registry courtesy of NPM Enterprise (npme). Ran into the usual issue when building in a new environment:

npm ERR! 404 Not found : @fxnetworks/super-cool-module
npm ERR! 404
npm ERR! 404 '@fxnetworks/super-cool-module' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)

Looking at my initial Dockerfile I eventually determined it was an Order of Operations (OOO) issue. IOTW, my npm user config was added too late in the sequence:

FROM nodesource/nsolid:latest
 
ADD package.json package.json
RUN npm install
 
# add application files + the npm config
ADD . .
 
CMD ["node","app.js"]

Since that config is only two lines, it felt righteous inserting it earlier in the sequence:

FROM nodesource/nsolid:latest
 
ADD package.json package.json
ADD .npmrc .npmrc
RUN npm install
 
ADD . .
 
CMD ["node","app.js"]

Updating the order cleared the initial issue but resulted in the following:

Error: Failed to replace env in config: ${FX_NPM_REGISTRY}
    at /lib/node_modules/npm/lib/config/core.js:429:13
    at String.replace (native)
    at envReplace (/lib/node_modules/npm/lib/config/core.js:424:12)
    at parseField (/lib/node_modules/npm/lib/config/core.js:400:7)
    at /lib/node_modules/npm/lib/config/core.js:338:17
    at Array.forEach (native)
    at Conf.add (/lib/node_modules/npm/lib/config/core.js:337:23)
    at ConfigChain.addString (/lib/node_modules/npm/node_modules/config-chain/index.js:244:8)
    at Conf.<anonymous> (/lib/node_modules/npm/lib/config/core.js:325:10)
    at /lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:78:16
 
/lib/node_modules/npm/lib/npm.js:29
    throw new Error('npm.load() required')
    ^
 
Error: npm.load() required
    at Object.npm.config.get (/lib/node_modules/npm/lib/npm.js:29:11)
    at exit (/lib/node_modules/npm/lib/utils/error-handler.js:58:40)
    at process.errorHandler (/lib/node_modules/npm/lib/utils/error-handler.js:387:3)
    at emitOne (events.js:77:13)
    at process.emit (events.js:169:7)
    at process._fatalException (node.js:258:26)

Naturally, this happened because the builder didn’t have access to the necessary ENV variables in order to expand them. I’m using expansion for the same reasons as necessary for CI/CD scenarios, so sensitive data (eg, credentials) doesn’t get baked into the resulting commit, build or deployment. And, just in case you’ve yet to see a tokenized .npmrc file here’s a sample:

@fxnetworks:registry=${FX_NPM_REGISTRY}
//fxnetworks.com:8080/:_authToken=${FX_NPM_AUTH}

Finally, all that was left to do was to make those variables available as build arguments like so:

FROM nodesource/nsolid:latest
 
ARG FX_NPM_REGISTRY=$FX_NPM_REGISTRY
ARG FX_NPM_AUTH=$FX_NPM_AUTH
 
ADD package.json package.json
ADD .npmrc .npmrc
RUN npm install
 
ADD . .
 
CMD ["node","app.js"]

Now, Docker is happy and the necessary images are successfully built and pushed to Docker Hub via Grunt:

grunt build-images
...
cf85f8e6: digest: sha256:bfc3f90c size: 12345
 
Done, without errors.

Next time, I’ll illustrate how this would be modified for a CircleCI or Codeship build process.

Leave a Reply

Your email address will not be published. Required fields are marked *