Slide 1

Slide 1 text

The Twelve-Factor App for Node.js Developers by Nikita Galkin Oct 5, 2019

Slide 2

Slide 2 text

What is Quality? 2 Motivation Reduce onboarding time A common language with DevOps Engineers Scale-ready app Cloud-ready app Production-ready app Etc-ready app

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

12factor.net

Slide 6

Slide 6 text

I. Codebase One codebase tracked in revision control, many deploys

Slide 7

Slide 7 text

What is Quality? 9

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

11 Scoped packages

Slide 10

Slide 10 text

What is Quality? 12 Shared code: ▰ Don’t use gitsubmodules, 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

Slide 11

Slide 11 text

II. Dependencies Explicitly declare and isolate dependencies

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

What is Quality? 15 Package.json ▰ avoid npm install -g ... ▰ package-lock.json should published in git ▰ node & npm versions fixed ▰ post-install script is a good place for hacking node_modules

Slide 14

Slide 14 text

What is Quality? 16

Slide 15

Slide 15 text

FROM node:10.16.3-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 package-lock.json $APP_WORKDIR WORKDIR $APP_WORKDIR RUN npm install COPY . $APP_WORKDIR RUN npm run build RUN rm -rf tsconfig.json src RUN apk del build-deps RUN npm prune --production CMD ["node", "dist/index.js"]

Slide 16

Slide 16 text

III. Config Store config in the environment

Slide 17

Slide 17 text

What is Quality? 19 ▰ Config is not part of the artifact ▰ App could be made open source at any moment, without compromising any credentials.

Slide 18

Slide 18 text

What is Quality? 20 .env ▰ Use .env.example file for description ▰ Use .env file for local development ▰ Use environment variables for any other environment ▰ Don’t use default config values in your code ▰ Break your start process if any value missed

Slide 19

Slide 19 text

# .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

Slide 20

Slide 20 text

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;

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

IV. Backing services Treat backing services as attached resources

Slide 23

Slide 23 text

What is Quality? 25 ▰ local and third party parity ▰ Use connection string is URL and can be used as locator/credentials ▰ Native Node.js module url has parse method ▰ Repeat III. Config one more time

Slide 24

Slide 24 text

What is Quality? 26 Nice to have ▰ Tech stack for project or Readme.md with strict versions ▰ For local development docker-compose file or minikube config file

Slide 25

Slide 25 text

V. Build, release, run Strictly separate build and run stages

Slide 26

Slide 26 text

What is Quality? 28 ▰ Artifact ▰ Build ▰ Release ▰ Run time ▰ Dry run

Slide 27

Slide 27 text

What is Quality? 29 Node.js artifact ▰ N/A ▰ Docker ▰ Lambda zip ▰ Application Zip ▻ Big size ▻ node-gyp compiled code can be broken on another computer

Slide 28

Slide 28 text

VI. Processes Execute the app as one or more stateless processes

Slide 29

Slide 29 text

What is Quality? 31

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

VII. Port binding Export services via port binding

Slide 33

Slide 33 text

What is Quality? 35 ▰ Don’t hardcode port at the code, use env vars ▰ Bootstrap should fail, if the port is not available ▰ Dockerfile EXPOSE directive depence on deploy, but 9229...

Slide 34

Slide 34 text

VIII. Concurrency Scale out via the process model

Slide 35

Slide 35 text

What is Quality? 37 ▰ Unix process model ▰ should never daemonize ▰ Use process manager like systemd/pm2/etc ▰ process and cluster are first class citizen

Slide 36

Slide 36 text

IX. Disposability Maximize robustness with fast startup and graceful shutdown

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

XI. Logs Treat logs as event streams

Slide 41

Slide 41 text

What is Quality? 43 ▰ 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 ▰ pino has this format from the box ▰ for local development use pino pretty

Slide 42

Slide 42 text

stdout stderr

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

What is Quality? 46 ▰ Node.js has REPL, so be DevOps Engineer ▰ Check node_modules/.bin every script starts with #!/usr/bin/env node ▰ Write your own script or reuse packages ▰ Database migrations ▰ Your own CLI with typescript decorators with clime package

Slide 45

Slide 45 text

12factor.net

Slide 46

Slide 46 text

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