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

Using Docker for your Rails Development Environment

Using Docker for your Rails Development Environment

https://trbmeetup.doorkeeper.jp/events/88667

Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. While there's a lot of information about using Docker for production Rails apps, I have been using it in development as well. Docker brings a lot of advantages for web application development, but it also creates some problems.

In this talk, I am going to share the benefits of using Docker, how to create a development environment with it, and how I have dealt with some of the challenges I've encountered.

Hibariya Hi

April 03, 2019
Tweet

More Decks by Hibariya Hi

Other Decks in Technology

Transcript

  1. Using Docker for your Rails
    Development Environment
    2019/04/03 Tokyo Rubyist Meetup at PIXTA, Inc.

    View Slide

  2. Hi there
    ● Gentaro Terada (@hibariya)
    ● Works at ESM, Inc.
    ● A college student (engineering)
    ● Likes Ruby, Internet, and Programming
    ● https://hibariya.org

    View Slide

  3. Today we will talk about:
    ● Why/How to use Docker
    ● Problems/questions I faced

    View Slide

  4. Why To Use Docker

    View Slide

  5. What is Docker
    With Docker, we can:
    ● Create/run containers
    ● Create/share container images (kind of snapshots)

    View Slide

  6. Container is lighter
    Container vs. Virtual Machine
    https://www.docker.com/resources/what-container

    View Slide

  7. Why To Use Docker
    Docker makes it much easier:
    ● Build once, run anywhere
    ● Less “It works on my machine”
    ○ The same condition (Runtimes, Libraries, Server Applications, and so on)
    ● Re-creating environments easily/quickly
    ● Various environment can live together on the same
    host machine

    View Slide

  8. How To Use Docker

    View Slide

  9. The First Step
    A development environment for a small Rails application:
    1. Create a Dockerfile to build containers
    2. Create a docker-compose.yml to organize containers

    View Slide

  10. Dockerfile for a Rails app

    View Slide

  11. Creating a new Rails app
    On the host:
    $ docker build -f Dockerfile -t rails-docker-example .
    $ docker container run -it --rm \
    --volume=$(pwd):/work --workdir=/work \
    rails-docker-example bash
    On the container:
    # gem install rails --no-document
    # rails new example --database=postgresql --skip-bundle …

    View Slide

  12. docker-compose.yml to Organize

    View Slide

  13. Invoke the app
    $ docker-compose run --rm rails bin/setup
    $ docker-compose up

    View Slide

  14. Running a command inside a container
    Use a running container:
    $ docker-compose exec rails bin/rails c
    Create and run a new container:
    $ docker-compose run --rm rails bin/rails c

    View Slide

  15. For more details
    https://github.com/esminc/rails-docker-examples
    ● Example Rails app + PostgreSQL + Webpacker
    ● Configurations for Docker Compose
    ● Configurations for Kubernetes (w/ GKE)

    View Slide

  16. Problems I Faced

    View Slide

  17. Problems I Faced
    ● Testing with browsers
    ● Dockerfile doesn’t ensure the same image
    ● Too large images
    ● Generated files are owned by root
    ● Long / complicated commands
    ● Could not we use K8s for development?

    View Slide

  18. Testing with Browsers

    View Slide

  19. How to run browser testing?
    ● Plan A: Run a Selenium container and use it
    remotely (I recommend)
    ○ Easy debugging; Can view/inspect running browser via VNC
    ○ Does not add another dependency to the Rails container
    ● Plan B: Install a browser on the Rails container and use
    it in headless mode
    ○ Less custom settings (probably)
    ○ Needs browser installation on the Rails container

    View Slide

  20. docker-compose.yml
    test/application_system_test_case.rb

    View Slide

  21. Interactive Debugging with VNC
    Stop w/ a breakpoint, connect to localhost:5900 w/ VNC

    View Slide

  22. Dockerfile Doesn’t Ensure the Same Image

    View Slide

  23. Dockerfile doesn't ensure the same image
    ● Updates on base image
    ● Repository changes for package management system
    ○ e.g., EPEL-5 repository EOL (March 2017)
    ○ So the following Dockerfile does not work anymore

    View Slide

  24. Share the image

    View Slide

  25. Too Large Images

    View Slide

  26. Rails application images tend to be large
    We could:
    ● Use smaller base image
    ● Install only mandatory packages
    ● Remove caches at the same time
    ● Use multi-stage builds for assets compilation
    ● Avoid using Git repositories as gem sources
    ○ as long as you can

    View Slide

  27. The More You Layer, the More It Gets Bigger
    Deleting existing files does not decrease the whole size
    Exploring the layers of an image with github.com/wagoodman/dive

    View Slide

  28. Drop build-time deps w/ multi-stage build
    Node.js, NPM and node_modules can be removed in the
    same way
    https://docs.docker.com/develop/develop-images/multistage-build/

    View Slide

  29. Avoid Git source if possible
    gem ‘rails’, github: ‘rails/rails’ loads...

    View Slide

  30. Generated Files Are Owned By root

    View Slide

  31. Generated files are owned by root

    View Slide

  32. Plan A: Add a user
    Add a user with the same UID as the user on the host

    View Slide

  33. Plan B: userns-remap
    Or, adjust the UID seen from the host with userns-remap

    View Slide

  34. Long/Complex Commands

    View Slide

  35. A kind of typing game?
    More than twice as long as the original command!
    $ docker-compose exec rails bin/rails g model User
    email:string
    $ docker-compose exec rails bin/rails db:migrate
    $ docker-compose exec rails bin/rails c

    View Slide

  36. Binstubs?
    Ended up with creating dedicated binstubs for each project

    View Slide

  37. Exec vs. Run; Which should I use?
    It depends...
    ● docker-compose exec
    ○ Uses an already running container
    ○ Can’t publish additional ports
    ● docker-compose run
    ○ Creates and uses a dedicated container
    ○ Without `--use-aliases`, couldn’t resolve some of the host names in some cases
    ○ Without `--rm`, the created container will remains after exit

    View Slide

  38. Crane
    Cosy interface to develop
    ● Reads docker-compose.yml
    ● Grouping services
    ● There’s only `run`
    ○ Works nicely by the situation

    View Slide

  39. Could We Develop Apps w/ K8s?

    View Slide

  40. Is Kubernetes only for production?

    View Slide

  41. Why don’t you use the same tool
    https://speakerdeck.com/mtsmfm/development-env-in-the-microservices-age

    View Slide

  42. Is it possible to develop apps w/ K8s?
    Yup.
    ● Good news: We can use the same tool for development
    ● Bad news: We will have to manage a lot of YAML files
    ○ Because of the difference of the API
    ○ Because K8s projects tend to be large
    ○ For not only production, but also development

    View Slide

  43. Organize YAML files w/ Kustomize
    https://github.com/kubernetes-sigs/kustomize

    View Slide

  44. Et cetera...

    View Slide

  45. References
    ● Docker for Rails Developers
    ● gh.c/esminc/rails-docker-examples

    View Slide

  46. Example Repository
    https://github.com/esminc/rails-docker-examples
    ● Example Rails app + PostgreSQL + Webpacker
    ● Configurations for Docker Compose
    ● Configurations for Kubernetes (w/ GKE)

    View Slide