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

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

Daniel Azuma

April 18, 2018
Tweet

More Decks by Daniel Azuma

Other Decks in Programming

Transcript

  1. • File system • CPU allocation • Memory • Network

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

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

    stack • Users • Processes CPU arch Linux kernel Linux host:
  4. • 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
  5. # Rails Dockerfile FROM ruby WORKDIR /opt/app COPY . /opt/app

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

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

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

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

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

    RUN bundle install ENV PORT=8080 CMD ["bundle", "exec", "rails", "server"]
  11. RUN apt-get update -y RUN apt-get install -y -q mypackage

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

    mypackage \ && apt-get clean \ && rm -f /var/lib/apt/lists/*_*
  13. FROM base-image RUN apt-get update \ && apt-get install mypkg

    \ && apt-get clean Tip #2: Combine install commands with cleanup
  14. FROM my-base AS builder COPY . /app RUN apt-get install

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

    build-essential \ && bundle install --deployment FROM my-base COPY --from=builder /app /app
  16. 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
  17. 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
  18. 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.
  19. 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.
  20. 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.
  21. 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
  22. 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
  23. 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
  24. 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
  25. "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/
  26. 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
  27. # Exec form CMD ["bundle", "exec", "rails", "s"] # Shell

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

    form CMD exec bundle exec rails s Tip #7: Prefix shell form with the “exec” keyword
  29. # Base image... ONBUILD COPY . /app ONBUILD RUN bundle

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

    install # ... # App image... FROM base-image # (implicit commands) Tip #8: Avoid ONBUILD
  31. apiVersion: v1 kind: Pod spec: containers: - name: rails resources:

    requests: memory: "100Mi" cpu: 0.5 limits: memory: "200Mi" cpu: 1.0 ...