0% found this document useful (0 votes)
48 views36 pages

2021-03-11 - 12-Factor Apps Docker

The document discusses the history of container shipping and how it improved efficiency. It then discusses how deploying software has challenges and how containerization helps address these by applying the twelve factor app methodology. This includes topics like treating configuration as an attached resource and separating code from configuration.

Uploaded by

Luis Medinelli
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views36 pages

2021-03-11 - 12-Factor Apps Docker

The document discusses the history of container shipping and how it improved efficiency. It then discusses how deploying software has challenges and how containerization helps address these by applying the twelve factor app methodology. This includes topics like treating configuration as an attached resource and separating code from configuration.

Uploaded by

Luis Medinelli
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 36

12-Factor Apps

Docker Community All Hands-On - Mar 11, 2021


Quick Intro

● Full-time at Virginia Tech since 2011


○ Helping lead cloud strategy and platform efforts
○ Adjunct Faculty with VT CS Dept since S16

● Community Involvement
○ Docker Captain and Community Leader

● Husband and dad to four girls and a boy!

@mikesir87
A long, long time ago...

● When shipping was done mostly between land/sea…


○ Goods were packaged mostly in barrels, crates, and sacks
○ Ships often spent more time in dock than on the sea because of the time it
took to load/unload
○ Chance of loss/theft was very high

@mikesir87 Credit: http://www.worldshipping.org/about-the-industry/history-of-containerization/before-container-shipping


Enter the Industrial Revolution

● When rail became more common…


○ Goods frequently went from ship to train, train to train, and train to ship
○ Inadequacies of load/unload processes compounded

● A better shipping practice was needed

@mikesir87 Credit: https://en.wikipedia.org/wiki/Rail_freight_in_Great_Britain


The Shipping Container

● With the shipping container…


○ Goods producers can simply load a box with whatever they want to ship
○ The shipping industry can focus around a standardized box
○ Goods can be moved much more efficiently
○ Chance of loss/theft plummeted

@mikesir87
Yes! We ship software!

● Deploying software has always been painful, but was manageable


● Now, we want to adapt to users and to changing requirements
● The faster pace of shipping software highlights the pain points
○ Especially true in microservice-based applications
○ Applies to even running small functions on data

@mikesir87
What’s it mean to be “cloud native”?
“Cloud-native is about
how applications are
created and deployed,
not where.”
-- Pivotal

@mikesir87
Source: https://pivotal.io/cloud-native
Background on Heroku

● Founded in 2009 as a “platform-as-a-service”


○ Currently supports easy deployment of apps written in Node, Ruby, Go, PHP,
Java, Scala, Clojure, and Python

● “Heroku is a cloud platform that lets companies build, deliver,


monitor and scale apps — we're the fastest way to go from idea to
URL, bypassing all those infrastructure headaches.”

@mikesir87
12-Factor Background

● Drafted by developers at Heroku


○ Based on experience of helping build and deploy
hundreds of apps on the Heroku platform

● Initially presented in 2011


○ Presented by Adam Wiggins, cofounder of Heroku

● Available at 12factor.net

@mikesir87
The 12 Factors

1. Codebase 7. Port Binding

2. Dependencies 8. Concurrency

3. Config 9. Disposability

4. Backing Services 10. Dev/prod parity

5. Build, release, run 11. Logs

6. Processes 12. Admin Processes


1. Codebase

● Track using Git, SVN, Mercurial, something


● A one-to-one relationship between app and repo
○ Multiple repos isn’t a single app, but a distributed system.
Each component is an app that can be 12-factor compliant
○ Multiple apps from same codebase should be refactored as
libraries and included via dependency management

● Multiple deploys of the same app

@mikesir87
2. Dependencies

● Dependencies are explicitly declared in a manifest


○ Applies both for development and production
○ Java with pom.xml, Node with package.json, Ruby with Gemfile, etc.

● Applications should NOT rely on system-wide packages


○ Includes usage of system tools (even curl, bash, etc.)
○ Not all systems may have them available

@mikesir87
3. Config

● There should be strict separation of code and config


○ Config should NOT be bundled with the app

● Config = everything that can vary between deploys


○ Resource credentials (database, caches, API keys, etc.)
○ Hostname information

● Config should be provided with a combination of environment


variables, injected files, configuration services

@mikesir87
4. Backing Services

● Treat backing services (db, caches, etc.) as attached resources


● The code for a twelve-factor app makes no distinction between
local and third party services
● Goal is to be able to swap out a local resource with a managed
resource with no change to the code itself
○ Example - Swapping local MySQL with RDS instance

@mikesir87
5. Build, release, run

● Strictly separate build and run stages


○ Build stage transforms code into an executable bundle
○ Run runs the bundle in a execution environment, combined with the config

● Each release should have a unique ID and be traceable back to the


originating source

@mikesir87
6. Processes

● Apps should be executed as one or more stateless processes


● Each process should share nothing. Any data that needs to be
persisted/shared should be done using a backing service
● Sticky sessions are a violation of twelve-factor

@mikesir87
7. Port Binding

● All apps/services should exposed via port binding


○ Should be fully self-contained and expose itself, rather than rely on a pre-
existing HTTP server

@mikesir87
8. Concurrency

● Scale out by adding more processes


● Often talked about scaling horizontally rather than vertically
○ Horizontally refers to adding more machines, which start more processes
○ Vertically refers to adding more resources to existing processes to let them do
more

@mikesir87
9. Disposability

● Apps should start and stop quickly and gracefully


○ Respond to SIGTERM events and start shutdown

● Includes idea of being “robust against sudden death”


○ Ensure message queues timeout and requeue messages if a handler dies due
to hardware failure

@mikesir87
10. Dev/Prod Parity

● Keep all environments as consistent as possible


○ Supports easier ability for continuous deployment

● Use same backing services between dev and prod


○ Don’t use one queue/db in one tier and another type in another tier

@mikesir87
11. Logs

● Treat logs as event streams


○ Try to have one event per line (exception traces may span multiple lines)
○ No beginning or end as long as the app is running

● Stay away from routing or storage of the output stream within the
app
○ Simply send data to stdout/stderr and let environment configuration
determine where it should go

@mikesir87
12. Admin Processes

● Run admin/management tasks as one-off processes


○ Database migrations or other one-time scripts

● One-off scripts should utilize same dependency isolation


techniques of apps themselves

@mikesir87
How do containers help here?
Containers (when done right) solve...

1. Codebase 7. Port Binding

2. Dependencies 8. Concurrency

3. Config 9. Disposability

4. Backing Services 10. Dev/prod parity

5. Build, release, run 11. Logs

6. Processes 12. Admin Processes


Let’s talk config...

● There are generally two methods to store config in the


environment:
○ Environment variables - variables defined in the environment and passed
into running processes. These can be overridden/changed at runtime.
○ Files - configuration is stored in a file and the app reads the config from the
file.

@mikesir87
When to use env vars?

● Environment variables are completely fine for…


○ Changing options
○ Changing labels
○ Configuring non-secret data

● They should very rarely be used for secret data


○ Environment variables are leaked far too often (logs, debug info, etc.)
○ Often these leaky locations are used when sending debug info to third-parties
(yikes!)

@mikesir87
Config in Files

● By storing config in files, we remove the possibility of it being


leaked in environment variable dumps
● To be compromised, someone would need filesystem access
● App can then read the contents of the file and configure
○ Does require an understanding of the file structure/schema (JSON vs YAML vs
plain-text, etc.)

@mikesir87
Where do the files come from?
apiVersion: v1

Injecting Secrets
kind: Pod
metadata:
name: mypod
spec:

● Leverage the orchestration framework!


containers:
- name: mypod
image: mysql
● Secrets are created/stored by the volumeMounts:
- name: foo
framework mountPath: "/secrets"
readOnly: true

● The files are mounted directly into the env:


- name: MYSQL_PASSWORD_FILE

container’s filesystem value: /secrets/mysql-pword


volumes:
- name: foo
secret:
secretName: mysecret
items:
- key: password
path: mysql-pword
@mikesir87
Using Init Containers

● Decouple how the secrets are fetched and provided to the app
● Uses two containers with a shared volume
○ The init container loads/fetches the secrets and puts them in the volume
○ The main app container reads the secrets from the volume

Init Container App Container

Shared Volume

Pod/ECS Task
@mikesir87
apiVersion: v1

Init Container - Kubernetes kind: Pod


metadata:
name: app
spec:
● The app container only starts after initContainers:
- name: secrets-fetcher

the secrets-fetcher container exits image: startup-image


volumeMounts:

successfully - name: sharedData


mountPath: /secrets
containers:
- name: app
image: my-app

secrets-fetcher app volumeMounts:


- name: sharedData

sharedData mountPath: /secrets


volumes:
- name: sharedData

Pod/ECS Task emptyDir:


medium: Memory

@mikesir87
What’s it mean to be “cloud native”?
“Cloud-native is about
how applications are
created and deployed,
not where.”
-- Pivotal

@mikesir87
Source: https://pivotal.io/cloud-native
What’s it mean to be “cloud native”?
It means to remove impediments and support the software
industrial revolution!
Thanks! Questions?

You might also like