The Twelve-Factor App for Node.js Developers

The Twelve-Factor App for Node.js Developers

A2443b68836f2d166eae52b940e99bf6?s=128

Nikita Galkin

February 27, 2019
Tweet

Transcript

  1. The Twelve-Factor App for Node.js Developers by Nikita Galkin Feb

    27, 2019
  2. Nikita Galkin Love and Know: ▰ How to make developers

    and business happy ▰ Technical and process debt elimination Believe that: ▰ Any problem must be solved at the right level ▰ Software is easy. People Are Complicated ▰ A problem should be highlighted, an idea should be "sold", a solution should be demonstrated Links: Site GitHub Twitter Facebook 2
  3. Takeaway Driven Development 3 TAKEAWAY ADOPT TDD SHARE

  4. 12factor.net

  5. What is Quality? 5 Motivation ▰ Reduce the onboarding time

    ▰ A common language with DevOps Engineers ▰ Scale/Cloud/Production/etc -ready
  6. What is Quality? 6 Talk Structure ▰ Factor ▰ RTFM

    ▰ how to implement using Node.js ▰ exclusion cases or hacks
  7. 7 I. Codebase

  8. What is Quality? 8 One codebase tracked in revision control,

    many deploys ▰ App vs Distributed System ▰ Code sharing by dependency manager.
  9. What is Quality? 9 How to match codebase and application

    at env? ▰ semver ▰ version in package.json ▰ git tag ▰ git describe --tag Example 2.2.0-44-g9f84663
  10. What is Quality? 10 I. Codebase ▰ BE & FE

    aka Full-stack repo ▰ App & lambda from one src ▰ Monorepo
  11. 11 II. Dependencies

  12. What is Quality? 12 Explicitly declare and isolate dependencies ▰

    declaration VS isolation ▰ never relies on implicit existence ▰ system tool can be a dependency
  13. What is Quality? 13 Package.json ▰ avoid npm install -g

    ... ▰ package-lock.json should published in git ▰ node & npm versions fixed at Tech Stack or you will have package-lock diff war ▰ post-install script is a good place for hacking node_modules
  14. 14 Scoped packages

  15. What is Quality? 15 Shared code ▰ Use scoped packages

    ▰ @project/code-style is good first chose Check Code Style and Violence by Anton Nemtsev ▰ On self-hosted repo npm config set @myco:registry http://reg.example.com ▰ With a self-hosted repo, use add .npmrc to git
  16. What is Quality? 16

  17. What is Quality? 17 node_modules hacks ▰ Embedded or lambda:

    webpack ▰ Docker ▻ npm install --production ▻ npm prune --production ▻ node-prune ▻ docker in docker
  18. FROM node:10.15-alpine ENV APP_WORKDIR=/usr/src/app RUN apk update && apk upgrade

    && \ apk add --virtual build-deps git openssh-client py-pip make COPY package.json yarn.lock $APP_WORKDIR WORKDIR $APP_WORKDIR RUN yarn install COPY . $APP_WORKDIR RUN yarn build RUN rm -rf tsconfig.json src RUN apk del build-deps RUN yarn install --production RUN yarn cache clean EXPOSE 3000 CMD ["node", "dist/index.js"]
  19. 19 III. Config

  20. What is Quality? 20 Store config in the environment ▰

    Config is not part of the artifact ▰ could be made open source at any moment, without compromising any credentials.
  21. What is Quality? 21 .env ▰ Use .env file for

    local development ▰ Use .env.example file for description ▰ Use environment variables for any other environment ▰ Don’t use default config values in your code ▰ Break your start process if any value missed
  22. # .env.example # Default log level LOG_LEVEL=info # Graceful shutdown

    timeout in milliseconds SHUTDOWN_TIMEOUT=1000 # HTTP Boundary port HTTP_PORT=8000 # Redis connection string REDIS_URI=redis://127.0.0.1:6379
  23. require('dotenv-safe').load({ allowEmptyValues: true, path: join(__dirname, '..', '.env'), sample: join(__dirname, '..',

    '.env.example') }); const logger = require('./logger'); logger.levels('stdout', process.env.LOG_LEVEL); const settings = { shutdownTimeout: process.env.SHUTDOWN_TIMEOUT, http: { port: process.env.HTTP_PORT, }, redis: { uri: process.env.REDIS_URI, }, }; module.exports = settings;
  24. What is Quality? 24 Dima: process.env knows every env var.

    This is risky! Nikita: Then your project uses only 11 factors.
  25. 25 IV. Backing services

  26. What is Quality? 26 Treat backing services as attached resources

    ▰ local and third party parity ▰ Attach URL or other locator/credentials stored in the config
  27. What is Quality? 27 Nice to have ▰ Tech stack

    for project or Readme.md with strict versions ▰ For local development docker-compose file or minikube config file
  28. 28 V. Build, release, run

  29. What is Quality? 29 Strictly separate build and run stages

    ▰ Artifact ▰ Build ▰ Release ▰ Run time ▰ Dry run
  30. What is Quality? 30 Node.js artifact ▰ N/A ▰ Docker

    ▰ Lambda zip ▰ Application Zip ▻ Big size ▻ node-gyp compiled code can be broken on another computer
  31. 31 VI. Processes (stateless)

  32. What is Quality? 32 Execute the app as one or

    more stateless processes ▰ stateless ▰ share-nothing ▰ state stored at backing-service
  33. Awesome Pair! Docker and Node.js has a common thing –

    single process
  34. 34 6 Done, 6 Left Let’s move faster

  35. 35 VII. Port binding Export services via port binding

  36. What is Quality? 36 ▰ Don’t hardcode port at the

    code, use env vars ▰ Bootstrap should fail, if the port is not available ▰ Dockerfile EXPOSE
  37. 37 VIII. Concurrency Параллелизм

  38. What is Quality? 38 Scale out via the process model

    ▰ Unix ▰ process ▰ should never daemonize ▰ Use process manager like systemd
  39. 39 IX. Disposability Maximize robustness with fast startup and graceful

    shutdown
  40. const server = app.listen(settings.port, () => { logger.info(`Server started on

    port ${settings.port}`); }); function stopHandler(){ logger.info(`Stopping server on port ${settings.port}`); const timeout = setTimeout(() => { logger.info(`Server on port ${settings.port} stop forcefully`); process.exit(1); }, settings.stopTimeout); server.close(() => { logger.info(`Server on port ${settings.port} stopped`); clearTimeout(timeout); }); }; process.on('exit', (code) => logger.info(`Exit with code: ${code}`)); ['SIGTERM','SIGINT','SIGHUP'] .forEach(signal => process.on(signal, stopHandler);
  41. 41 X. Dev/prod parity Keep development, staging, and production as

    similar as possible
  42. What is Quality? 42 ▰ Same backing services ▰ Same

    lib versions ▰ Same bla-bla for Reproducibility
  43. 43 XI. Logs Treat logs as event streams

  44. What is Quality? 44 ▰ A twelve-factor app never concerns

    itself with routing or storage of its output stream ▰ Writes event stream, unbuffered, to stdout/stderr ▰ JSON format for simplification log parsing ▰ bunyan has this format from the box ▰ for local development npm start | bunyan -o short
  45. stdout stderr

  46. 46 XII. Admin processes Run admin/management tasks as one-off processes

  47. What is Quality? 47 ▰ Node.js has REPL ▰ Check

    node_modules/.bin every script starts with #!/usr/bin/env node ▰ Write your own script or reuse packages ▰ Use npx, for example npx https://gist.github.com/galkin/9b54683ec251d77b26fa4c7feec46df2
  48. 12factor.net

  49. 49 THANKS! Happy coding with 12 factors! You can find

    me on Twitter as @galk_in Slides are available at speakerdeck.com/galkin or at my site galk.in