Slide 1

Slide 1 text

Ruby Development Environment with Docker @ Experteer

Slide 2

Slide 2 text

About • Software Architect at Experteer • Became interested in Docker mid 2013

Slide 3

Slide 3 text

Docker @ Experteer • Development • Introduced 1.5 years ago • 10-15 containers (Some Rails apps, Postgres, Elasticsearch, Redis, RabbitMQ, Nginx etc.) • CI: 1-3 containers per build, in parallel • “Production” (getting jobs into our platform) • Main staging & production is not on Docker

Slide 4

Slide 4 text

Agenda 1. Why Docker for dev / comparison to other solutions 2. Tips and tricks what helped us 3. A story about Docker on Mac

Slide 5

Slide 5 text

Why? • Isn’t a native setup best because there’s no complex abstractions? • Isn’t a VM (Vagrant) all you need? • Isn’t Docker just for production / CI? • Docker is fiddly to get right for development, but I think it is possible!

Slide 6

Slide 6 text

Comparison Native/Manual Vagrant/VM Docker Easy to setup Easy to update Easy to use Performance Prod Parity Flexibility Unified Env - - + + - - + + -/+ -/+ - -/+ + - + + -/+ -/+ -/+ + +

Slide 7

Slide 7 text

Docker Intro • Images (filesystem) and containers (process) • docker run —net dev —detach —name postgres postgres:9.6 • docker run —net dev —interactive — tty —env DATABASE_HOST=postgres.dev —volume $PWD:/todo —name todo ruby: 2.4 rails c

Slide 8

Slide 8 text

Crane Intro • containers:
 postgres:
 image: postgres:9.6
 run:
 net: dev
 detach: true
 todo:
 requires: ["postgres"]
 image: ruby:2.4
 run:
 net: dev
 interactive: true
 tty: true
 volume: [".:/todo"]
 env: ["DATABASE_HOST=postgres.dev"]
 networks:
 dev: • crane run todo rails c

Slide 9

Slide 9 text

Tips & Tricks
 Umbrella folder Umbrella folder A B C bin crane.yml

Slide 10

Slide 10 text

Tips & Tricks
 Umbrella folder • crane.yml can define services which are shared between projects (e.g. message bus, database, search) • Configuration directory for services (bind-mounted) • bin directory can contain wrapper scripts, e.g. todo:
 #!/bin/bash
 crane run todo sh -c “$*" • Put bin in $PATH: todo rails c • Config update, new service, Ruby version change, etc.:
 git pull

Slide 11

Slide 11 text

Tips & Tricks App container • In the image, add user with UID 1000 for file sharing • Bind-mount another directory to place local gems: 
 volume: […, ”local-gems:/local-gems”]
 In the Gemfile:
 gem "foo", path: "/local-gems/foo" • Bind-mount the SSH agent socket:
 volume: […, ”$SSH_AUTH_SOCK:/ssh-agent”]
 env: ["SSH_AUTH_SOCK=/ssh-agent"] • Use local history file to preserve Pry history across container runs:
 .pryrc
 Pry.config.history.file = “./pry_history”

Slide 12

Slide 12 text

Tips & Tricks Volumes • How to store / distribute data, e.g. a database snapshot? • Bake into image • Super-easy to distribute and reset • Docker images are not made for this • Distribute separately and store in volume • Gzipped tarballs • Import script to re-create volumes and extract data into it

Slide 13

Slide 13 text

Docker on Mac • With “native” Docker for Mac it’s easy now, but slow • However, when we started with Docker in 2015, there was no “native” solution for Mac, so … • The first setup was a Vagrant-managed VM • Docker server runs in VM, client runs on host • Problem: The server doesn’t know the paths the client specifies
 docker run -v /host/path:/container/path

Slide 14

Slide 14 text

Docker on Mac • Solution #1: Virtualbox shared folders ➡ The app (Rails) is super-slow :(

Slide 15

Slide 15 text

Docker on Mac • Solution #2: Vagrant offers NFS shares ➡ Slightly faster, but still way to slow :(

Slide 16

Slide 16 text

Docker on Mac • Solution #3: Vagrant offers rsync shares ➡ Very fast, but only one-way • Installed gems are not available on the host • Logs etc. are not synced

Slide 17

Slide 17 text

Docker on Mac • Solution #4: NFS should be the other way around ➡ Vagrant doesn’t support this, but if the NFS server is in the VM and the client is on the Mac host, the performance in the VM is much better • However, some operations on the host are very slow now (git status) …

Slide 18

Slide 18 text

Docker on Mac • Solution #5: Unison • Unison is a file sync like rsync, but two-way ➡ Annoying to setup/configure/use, but it’s really fast, both on the host and the VM

Slide 19

Slide 19 text

Docker on Mac • This worked OK for half a year, then came “native” Docker for Mac • Yes! Finally we can drop the VM, the complicated Unsion setup, and all the weird workarounds • Sure it’s fast, right?

Slide 20

Slide 20 text

Docker on Mac NO! ("rails c" took ~20 mins on the first beta) (it’s ~1:50min on the latest version)

Slide 21

Slide 21 text

Docker on Mac • We still need Unsion, but can we drop the VM? • Unison has a client-server architecture ➡ Run Unison server in a Docker container, and use that as a volume in the app container

Slide 22

Slide 22 text

Docker on Mac • Crane has support for this built-in now: • Install Unison via Homebrew & configure syncs • Crane manages sync and volumes automatically • Usage is 100% identical to Linux

Slide 23

Slide 23 text

Summary ✓ Docker for development is possible and doesn’t have to be cumbersome to use ✓ Our setup time went from 1-2 days (for one project only) to about 30 minutes (for all projects) ✓ Shipping service and config updates is super-easy ✓ Once setup, profit again and again from it (e.g. parallelise tests in CI, experiment with cluster setups locally, preview environments, etc.) ✓ Unified dev environment across operating systems and teams

Slide 24

Slide 24 text

Thanks Questions?