Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Twelve-Factor App for Node.js Developers

The Twelve-Factor App for Node.js Developers

Nikita Galkin

February 27, 2019
Tweet

More Decks by Nikita Galkin

Other Decks in Programming

Transcript

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

    View Slide

  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

    View Slide

  3. Takeaway Driven Development
    3
    TAKEAWAY
    ADOPT
    TDD
    SHARE

    View Slide

  4. 12factor.net

    View Slide

  5. What is Quality?
    5
    Motivation
    ▰ Reduce the onboarding
    time
    ▰ A common language with
    DevOps Engineers
    ▰ Scale/Cloud/Production/etc
    -ready

    View Slide

  6. What is Quality?
    6
    Talk Structure
    ▰ Factor
    ▰ RTFM
    ▰ how to implement using
    Node.js
    ▰ exclusion cases or hacks

    View Slide

  7. 7
    I. Codebase

    View Slide

  8. What is Quality?
    8
    One codebase tracked in
    revision control, many
    deploys
    ▰ App vs Distributed System
    ▰ Code sharing by
    dependency manager.

    View Slide

  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

    View Slide

  10. What is Quality?
    10
    I. Codebase
    ▰ BE & FE aka Full-stack repo
    ▰ App & lambda from one src
    ▰ Monorepo

    View Slide

  11. 11
    II. Dependencies

    View Slide

  12. What is Quality?
    12
    Explicitly declare and
    isolate dependencies
    ▰ declaration VS isolation
    ▰ never relies on implicit
    existence
    ▰ system tool can be a
    dependency

    View Slide

  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

    View Slide

  14. 14
    Scoped packages

    View Slide

  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

    View Slide

  16. What is Quality?
    16

    View Slide

  17. What is Quality?
    17
    node_modules hacks
    ▰ Embedded or lambda: webpack
    ▰ Docker
    ▻ npm install --production
    ▻ npm prune --production
    ▻ node-prune
    ▻ docker in docker

    View Slide

  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"]

    View Slide

  19. 19
    III. Config

    View Slide

  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.

    View Slide

  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

    View Slide

  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

    View Slide

  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;

    View Slide

  24. What is Quality?
    24
    Dima: process.env knows
    every env var. This is
    risky!
    Nikita: Then your project
    uses only 11 factors.

    View Slide

  25. 25
    IV. Backing
    services

    View Slide

  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

    View Slide

  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

    View Slide

  28. 28
    V. Build, release,
    run

    View Slide

  29. What is Quality?
    29
    Strictly separate build and
    run stages
    ▰ Artifact
    ▰ Build
    ▰ Release
    ▰ Run time
    ▰ Dry run

    View Slide

  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

    View Slide

  31. 31
    VI. Processes
    (stateless)

    View Slide

  32. What is Quality?
    32
    Execute the app as one or
    more stateless processes
    ▰ stateless
    ▰ share-nothing
    ▰ state stored at
    backing-service

    View Slide

  33. Awesome Pair!
    Docker and Node.js
    has a common thing
    – single process

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  37. 37
    VIII. Concurrency
    Параллелизм

    View Slide

  38. What is Quality?
    38
    Scale out via the process
    model
    ▰ Unix
    ▰ process
    ▰ should never daemonize
    ▰ Use process manager like
    systemd

    View Slide

  39. 39
    IX. Disposability
    Maximize robustness with fast startup
    and graceful shutdown

    View Slide

  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);

    View Slide

  41. 41
    X. Dev/prod parity
    Keep development, staging, and
    production as similar as possible

    View Slide

  42. What is Quality?
    42
    ▰ Same backing services
    ▰ Same lib versions
    ▰ Same bla-bla for
    Reproducibility

    View Slide

  43. 43
    XI. Logs
    Treat logs as event streams

    View Slide

  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

    View Slide

  45. stdout stderr

    View Slide

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

    View Slide

  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

    View Slide

  48. 12factor.net

    View Slide

  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

    View Slide