Containerizing Rails: Techniques, Pitfalls, & Best Practices

Containerizing Rails: Techniques, Pitfalls, & Best Practices

Presentation by Daniel Azuma at RailsConf 2018. Covers best practices for designing Docker images for Rails applications. More information at http://daniel-azuma.com/railsconf2018

E06aa8f63d2a1753a2b352bc1cabbde2?s=128

Daniel Azuma

April 18, 2018
Tweet

Transcript

  1. 1.
  2. 4.
  3. 7.
  4. 10.
  5. 11.
  6. 19.

    • File system • CPU allocation • Memory • Network

    stack • Users • Processes != VM
  7. 20.

    • File system • CPU allocation • Memory • Network

    stack • Users • Processes Linux host
  8. 21.

    • File system • CPU allocation • Memory • Network

    stack • Users • Processes CPU arch Linux kernel Linux host:
  9. 22.

    • 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
  10. 23.
  11. 24.
  12. 26.

    # Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app

    RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]
  13. 27.

    # Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app

    RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]
  14. 28.

    # Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app

    RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]
  15. 29.

    # Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app

    RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]
  16. 30.

    # Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app

    RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]
  17. 31.

    # Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app

    RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]
  18. 37.

    RUN apt-get update -y RUN apt-get install -y -q mypackage

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

    RUN apt-get update -y \ && apt-get install -y -q

    mypackage \ && apt-get clean \ && rm -f /var/lib/apt/lists/*_*
  20. 43.

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

    \ && apt-get clean Tip #2: Combine install commands with cleanup
  21. 46.

    FROM my-base AS builder COPY . /app RUN apt-get install

    build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app
  22. 47.

    FROM my-base AS builder COPY . /app RUN apt-get install

    build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app
  23. 48.

    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
  24. 49.

    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
  25. 50.

    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.
  26. 51.

    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.
  27. 52.

    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.
  28. 53.

    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
  29. 54.

    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
  30. 55.

    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
  31. 57.
  32. 58.

    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
  33. 59.

    "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/
  34. 60.

    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
  35. 62.

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

    form CMD bundle exec rails s Tip #6: Prefer exec form for CMD
  36. 63.

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

    form CMD exec bundle exec rails s Tip #7: Prefix shell form with the “exec” keyword
  37. 64.
  38. 66.

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

    install # ... # App image... FROM base-image # (implicit commands)
  39. 67.

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

    install # ... # App image... FROM base-image # (implicit commands) Tip #8: Avoid ONBUILD
  40. 72.

    apiVersion: v1 kind: Pod spec: containers: - name: rails resources:

    requests: memory: "100Mi" cpu: 0.5 limits: memory: "200Mi" cpu: 1.0 ...
  41. 73.
  42. 74.
  43. 75.
  44. 79.
  45. 80.