Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Why To Use Docker

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

How To Use Docker

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

Dockerfile for a Rails app

Slide 11

Slide 11 text

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 …

Slide 12

Slide 12 text

docker-compose.yml to Organize

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

Problems I Faced

Slide 17

Slide 17 text

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?

Slide 18

Slide 18 text

Testing with Browsers

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

docker-compose.yml test/application_system_test_case.rb

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

Dockerfile Doesn’t Ensure the Same Image

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

Share the image

Slide 25

Slide 25 text

Too Large Images

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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/

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

Generated Files Are Owned By root

Slide 31

Slide 31 text

Generated files are owned by root

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

Long/Complex Commands

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Binstubs? Ended up with creating dedicated binstubs for each project

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

Could We Develop Apps w/ K8s?

Slide 40

Slide 40 text

Is Kubernetes only for production?

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

Et cetera...

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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