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

Ruby Development Environment with Docker

Ruby Development Environment with Docker

@ Experteer

Michael Sauter

March 11, 2017
Tweet

More Decks by Michael Sauter

Other Decks in Programming

Transcript

  1. 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
  2. Agenda 1. Why Docker for dev / comparison to other

    solutions 2. Tips and tricks what helped us 3. A story about Docker on Mac
  3. 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!
  4. Comparison Native/Manual Vagrant/VM Docker Easy to setup Easy to update

    Easy to use Performance Prod Parity Flexibility Unified Env - - + + - - + + -/+ -/+ - -/+ + - + + -/+ -/+ -/+ + +
  5. 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
  6. 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
  7. 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
  8. 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”
  9. 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
  10. 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
  11. Docker on Mac • Solution #2: Vagrant offers NFS shares

    ➡ Slightly faster, but still way to slow :(
  12. 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
  13. 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) …
  14. 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
  15. 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?
  16. Docker on Mac NO! ("rails c" took ~20 mins on

    the first beta) (it’s ~1:50min on the latest version)
  17. 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
  18. 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
  19. 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