免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 33842 | 回复: 0
打印 上一主题 下一主题

Happy Ending: An Epic Saga of Guard and Docker [复制链接]

论坛徽章:
32
CU大牛徽章
日期:2013-05-20 10:45:13每日论坛发贴之星
日期:2015-09-07 06:20:00每日论坛发贴之星
日期:2015-09-07 06:20:00数据库技术版块每日发帖之星
日期:2015-12-13 06:20:0015-16赛季CBA联赛之江苏
日期:2016-03-03 11:56:13IT运维版块每日发帖之星
日期:2016-03-06 06:20:00fulanqi
日期:2016-06-17 17:54:25IT运维版块每日发帖之星
日期:2016-07-23 06:20:0015-16赛季CBA联赛之佛山
日期:2016-08-11 18:06:41JAVA
日期:2016-10-25 16:09:072017金鸡报晓
日期:2017-01-10 15:13:292017金鸡报晓
日期:2017-02-08 10:33:21
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-09-12 20:06 |只看该作者 |倒序浏览
I’ve never liked how projects pollute my system. Libraries, databases, message queues, you name it and I’ve had to install it. Within this shared universe, it’s only a matter of time before worlds collide. Two projects each require a different Redis and I’m stuck being the human dependency resolver.
There have been past attempts at project silos. None of them have been as powerful or as promising as Docker. Even so, it’s not without its rough edges. This is a story about one of those edges.
I have a Rails project with existing tests that I wish to Dockerize. What I don’t have is a good way to get feedback as I refactor. I want to run Guard so I can do some TDD. Normally running Guard isn’t a big deal, but Docker (at least, on the Mac) makes this an issue (it has to do with libnotify). It’s difficult to impossible to get file changes to kick off your guards. New technologies come with trade-offs and sometimes the simple becomes difficult.
Let’s begin.
The First Duty
My Gemfile is open and ready. I crack my knuckles, roll my shoulders, and begin to type:
group :test do
  ...
  gem 'guard-rspec'
end
The Rails app I’m working on lives in a container named “web”. It interacts with a PostgreSQL database, a worker for background jobs, and a faux mail server. All orchestrated with docker-compose:
$ docker-compose run web bundle install
Text flies by as my system installs Guard. Now I need a Guardfile:
$ docker-compose run web bundle exec guard init
With that, everything should be ready:
$ docker-compose run web bundle exec guard
I’m greeted with a familiar prompt:
02:39:05 - INFO - Guard::RSpec is running
02:39:06 - INFO - Guard is now watching at '/app'

Frame number: 0/0
[1] guard(main)>
I strike the enter key and my tests begin to run. They complete with a series of satisfying green dots and I can’t help but smile. I open a model with vim and save. I look to Guard and…
Loud as a Whisper
Let’s back up for a moment. This development is happening in OSX. Docker doesn’t run on OSX. It runs on Linux and Linux alone. Running on OSX means using a small Linux VM conveniently packaged up asboot2docker.
I said that this development is happening in OSX. In truth, all of my work happens in OSX. It’s my home. It’s where I keep my dotfiles. I don’t want to shell into a VM to work. Thankfully, docker-composeunderstands my plight and will mount local directories into containers.
Where was I? Ah yes, I saved my model and tests should be running. They’re not.
Normally this would lead to a flurry of Google searches. There’s no need for that. I know what’s happened. Guard relies on file system notifications. Mounted volumes (in Virtual Box) change files under the cover of darkness and tell no one of what they’ve done. Guard waits silently, blissfully unaware of the changes.
There’s a full-proof solution for this. I scroll through the documentation looking for what I need.
$ docker-compose run web bundle exec guard --force-polling
Now guard is manually checking for changes to each file once a second. I switch back to my editor and save again. The model tests zip by and the fan in my laptop whirs to life.
Who Watches the Watchers
My fan is loud enough that I fear my computer may take flight. Polling files is more intense than I had expected.

Over 100% CPU? This’ll never work. If watching things is this expensive then I need to be careful with what I watch. I open the default Guardfile I installed. It’s set up to watch everything I could ever need and it has the line count to prove it. I begin deleting lines in mass.
I start guard again and my fan still sounds like it’s giving all it’s got. It appears to be working though. In a moment of weakness I consider ear muffs from Amazon to stifle the noise. I shake the thought away.
A Matter of Time
I stare through my screen trying to think of a better way. A moment from my past surfaces what might be a solution. At a job I used to have we would deploy code with rsync. That’s almost the same problem. It might just work.
I immediately start to think of what needs to happen. I’ll have to get rsync installed in the Docker VM. Of course they release new images so it’ll have to be done each time. I’ll need an easy way to repeat the install. I can’t help but wonder what it’ll take to get it working in the containers on the VM. The truth is, I have no idea.
Operations has never been my strength and it’s showing. I do know of a solution that worked for me in the past. I’ll hope someone else has already done it.
I switch to Firefox and begin my search. I click through links, skim Stack Overflow answers, and land on a project called docker-osx-dev. It rsyncs local files to the VM and its maintainer, Yevgeniy Brikman, has already handled the tricky parts.
I install docker-osx-dev and hope it works as advertised. A wall of output shows files syncing and gives me a bit of confidence. I start guard without the polling and save my model once more. My tests run. My fan is silent. My arms thrust up into the air. I love this part.
Parallels
Fueled by triumph I press on. My tests are going but there’s a noticeable delay between runs. My gut says it’s Rails loading.
Delay from loading Rails is a well known problem with a well known solution. Rails now ships with Springto solve this exact issue. It keeps a copy of Rails running in the background and then forks the process when needed.
I pop open my Guardfile and add spring to the command used to run rspec:
guard :rspec, cmd: "bundle exec spring rspec" do
   ...
end
Confident in my fix I start up guard:
03:32:35 - INFO - Running all specs
Version: 1.3.6

Usage: spring COMMAND [ARGS]

Commands for spring itself:

  binstub         Generate spring based binstubs. Use --all to generate a binstub for all known commands.
  help            Print available commands.
  status          Show current status.
  stop            Stop all spring processes for this project.

Commands for your application:

  rails           Run a rails command. The following sub commands will use spring: console, runner, generate, destroy, test.
  rake            Runs the rake command
Crap. It looks like spring has to know about the command and it’s not familiar with rspec. There’s no way I’m the first person to do this. Back to Google.
Once again the community comes through with spring-commands-rspec. I add it to my Gemfile, do another bundle install, and guard starts with no complaints. I save the model again and the tests run. Another save, another run, and the delay is gone.
All Good Things…
I take a deep breath and nod my head. The changes are committed with a small message that hardly represents the effort. I can’t help but think of those on who’s shoulders I am standing. Not of giants but of regular people. It’s a fairly dramatic thought considering I managed to get Guard running. It’s not as though I’ve saved the world. Still, I enjoy the moment and hope my shoulders manage to hold others. It’s late and I need to wind down before trying to sleep. After a trek like that I need something to watch. If only I could figure out what.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP