Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

Containerizing Rails Techniques, Pitfalls, & Best Practices Daniel Azuma Google Cloud Platform

Slide 3

Slide 3 text

Daniel Azuma http://daniel-azuma.com/ @danielazuma

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Languages, Optimizations, and Libraries

Slide 6

Slide 6 text

Languages, Optimizations, and Libraries

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Basic concepts

Slide 9

Slide 9 text

Håkan Dahlström, "Multicolored Containers" Source: https://www.flickr.com/photos/dahlstroms/3144199355 License: https://creativecommons.org/licenses/by/2.0/

Slide 10

Slide 10 text

Isolation

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

• File system

Slide 13

Slide 13 text

• File system • CPU allocation

Slide 14

Slide 14 text

• File system • CPU allocation • Memory

Slide 15

Slide 15 text

• File system • CPU allocation • Memory • Network stack

Slide 16

Slide 16 text

• File system • CPU allocation • Memory • Network stack • Users

Slide 17

Slide 17 text

• File system • CPU allocation • Memory • Network stack • Users • Processes

Slide 18

Slide 18 text

• File system • CPU allocation • Memory • Network stack • Users • Processes

Slide 19

Slide 19 text

• File system • CPU allocation • Memory • Network stack • Users • Processes != VM

Slide 20

Slide 20 text

• File system • CPU allocation • Memory • Network stack • Users • Processes Linux host

Slide 21

Slide 21 text

• File system • CPU allocation • Memory • Network stack • Users • Processes CPU arch Linux kernel Linux host:

Slide 22

Slide 22 text

• File system • CPU alloc • Memory • Network stack • Users • Processes CPU arch Linux kernel Linux host: • File system • CPU alloc • Memory • Network stack • Users • Processes • File system • CPU alloc • Memory • Network stack • Users • Processes

Slide 23

Slide 23 text

Images

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

Dockerfile

Slide 26

Slide 26 text

# Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]

Slide 27

Slide 27 text

# Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]

Slide 28

Slide 28 text

# Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]

Slide 29

Slide 29 text

# Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]

Slide 30

Slide 30 text

# Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]

Slide 31

Slide 31 text

# Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]

Slide 32

Slide 32 text

Which base image?

Slide 33

Slide 33 text

FROM ruby FROM alpine FROM phusion/baseimage ??? Tip #1: Read and understand your base image

Slide 34

Slide 34 text

Size does matter

Slide 35

Slide 35 text

apt-get install

Slide 36

Slide 36 text

RUN apt-get clean \ && rm -f /var/lib/apt/lists/*_*

Slide 37

Slide 37 text

RUN apt-get update -y RUN apt-get install -y -q mypackage RUN apt-get clean \ && rm -f /var/lib/apt/lists/*_*

Slide 38

Slide 38 text

RUN apt-get update -y \ && apt-get install -y -q mypackage \ && apt-get clean \ && rm -f /var/lib/apt/lists/*_*

Slide 39

Slide 39 text

FROM base-image

Slide 40

Slide 40 text

FROM base-image RUN apt-get update

Slide 41

Slide 41 text

FROM base-image RUN apt-get update RUN apt-get install mypkg

Slide 42

Slide 42 text

FROM base-image RUN apt-get update RUN apt-get install mypkg RUN apt-get clean

Slide 43

Slide 43 text

FROM base-image RUN apt-get update \ && apt-get install mypkg \ && apt-get clean Tip #2: Combine install commands with cleanup

Slide 44

Slide 44 text

RUN apt-get install build-essential \ && bundle install

Slide 45

Slide 45 text

http://artgallery.msfc.nasa.gov/4459.html Source: NASA

Slide 46

Slide 46 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app

Slide 47

Slide 47 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app

Slide 48

Slide 48 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app Ruby base image

Slide 49

Slide 49 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app Ruby base image App source

Slide 50

Slide 50 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app Ruby base image App source Compilers, etc.

Slide 51

Slide 51 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app Ruby base image App source Vendored gems Compilers, etc.

Slide 52

Slide 52 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app Ruby base image Ruby base image App source Vendored gems Compilers, etc.

Slide 53

Slide 53 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app Ruby base image Ruby base image App source Vendored gems Compilers, etc. App w/vendored gems

Slide 54

Slide 54 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app Ruby base image Ruby base image App source Vendored gems Compilers, etc. App w/vendored gems

Slide 55

Slide 55 text

FROM my-base AS builder COPY . /app RUN apt-get install build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app Ruby base image App w/vendored gems Tip #3: Use a separate build stage

Slide 56

Slide 56 text

Gerd Rohs, "Image in the image" https://pixabay.com/en/image-in-the-image-mobile-phone-2204798/ CC0

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \ && locale-gen en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en Tip #4: Set the system locale

Slide 59

Slide 59 text

"Australia in a Nutshell" (Sign contents modified) Photo by: Kristian Thøgersen Source: https://www.flickr.com/photos/flottenheimer/5534636006 License: https://creativecommons.org/licenses/by/2.0/

Slide 60

Slide 60 text

Tip #5: Create an unprivileged user # After building your app... RUN adduser -s /bin/sh -u 1001 -G root \ -h /app -S -D rails \ && chown -R rails /app USER rails

Slide 61

Slide 61 text

# Exec form CMD ["bundle", "exec", "rails", "s"] # Shell form CMD bundle exec rails s

Slide 62

Slide 62 text

# Exec form CMD ["bundle", "exec", "rails", "s"] # Shell form CMD bundle exec rails s Tip #6: Prefer exec form for CMD

Slide 63

Slide 63 text

# Exec form CMD ["bundle", "exec", "rails", "s"] # Shell form CMD exec bundle exec rails s Tip #7: Prefix shell form with the “exec” keyword

Slide 64

Slide 64 text

ONBUILD

Slide 65

Slide 65 text

# Base image... ONBUILD COPY . /app ONBUILD RUN bundle install # ...

Slide 66

Slide 66 text

# Base image... ONBUILD COPY . /app ONBUILD RUN bundle install # ... # App image... FROM base-image # (implicit commands)

Slide 67

Slide 67 text

# Base image... ONBUILD COPY . /app ONBUILD RUN bundle install # ... # App image... FROM base-image # (implicit commands) Tip #8: Avoid ONBUILD

Slide 68

Slide 68 text

Containers in production

Slide 69

Slide 69 text

Containers == isolation

Slide 70

Slide 70 text

Containers == isolation ⟹ predictability

Slide 71

Slide 71 text

docker run --cpus=2.0 --memory=200M ... Tip #9: Always specify resource constraints

Slide 72

Slide 72 text

apiVersion: v1 kind: Pod spec: containers: - name: rails resources: requests: memory: "100Mi" cpu: 0.5 limits: memory: "200Mi" cpu: 1.0 ...

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

No content

Slide 76

Slide 76 text

Tip #10: Avoid preforking in a container ???

Slide 77

Slide 77 text

Tip #11: Scale by adding containers

Slide 78

Slide 78 text

https://pixabay.com/en/logs-timber-wood-logging-lumber-690888/ CC0

Slide 79

Slide 79 text

No content

Slide 80

Slide 80 text

No content

Slide 81

Slide 81 text

ENV RAILS_LOG_TO_STDOUT=true Tip #12: Log to STDOUT or an external agent

Slide 82

Slide 82 text

• Optimizing for size/performance • Container contents • Containers in production

Slide 83

Slide 83 text

http://daniel-azuma.com/railsconf2018

Slide 84

Slide 84 text

Thank you! http://daniel-azuma.com/ @danielazuma http://daniel-azuma.com/railsconf2018