From 141b1f40d93ab521a35ecfed97ff9230e32ddd94 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Sun, 21 Feb 2016 15:52:51 +0100 Subject: [PATCH] Publish "Making docker-compose easier with wdocker" --- wdocker_compose.org | 2 + wdocker_compose.post | 237 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 wdocker_compose.post diff --git a/wdocker_compose.org b/wdocker_compose.org index fe42365..d3d504b 100644 --- a/wdocker_compose.org +++ b/wdocker_compose.org @@ -1,4 +1,6 @@ #+TITLE: Making docker-compose easier with wdocker +#+DATE: 2016-02-21 +#+COLESLAW_TAGS: wdocker docker docker-compose #+OPTION: num:nil * Introduction diff --git a/wdocker_compose.post b/wdocker_compose.post new file mode 100644 index 0000000..dc61bf8 --- /dev/null +++ b/wdocker_compose.post @@ -0,0 +1,237 @@ +;;;;; +title: Making docker-compose easier with wdocker +date: 2016-02-21 +tags: wdocker docker docker-compose +format: html +;;;;; + +
+

1 Introduction

+
+

+wdocker is a little utility written by a friend and former colleague +of mine. It allows you to define commands for it in a +Dockerfile. He wrote it because he used a lot of composite +commands when writing docker images like: +

+ +
+ +
docker stop CONTAINER && docker rm CONTAINER && docker rmi IMAGE && \
+    docker build -t IMAGE && docker run --name CONTAINER IMAGE
+
+
+ +

+By using wdocker to define a command he can greatly simplify his own +workflow. Let's call it rebuild: +

+ +
+ +
#wd# container = CONTAINER
+#wd# image = IMAGE
+#wd# stop = docker stop {container}
+#wd# rm = docker rm {container}
+#wd# rmi = docker rmi {container}
+#wd# build = docker build -t {image}
+#wd# run = docker run --name {container} {image}
+
+#wd# rebuild: {stop} && {rm} && {rmi} && {build} && {run}
+
+FROM ubuntu
+
+# ...
+
+
+ +

+Now he can use the following command instead of the list presented +before: +

+ +
+wdocker rebuild
+
+
+
+ +
+

2 Syntax

+
+

+wdocker has very simple syntax. You can define variables and +commands: +

+ +
+#wd# variable = value
+#wd# command: program
+
+ +

+Variables can be used by putting them in braces, including in other +variables, as you've seen in the first example. +

+ +
+#wd# variable = -l
+#wd# list: ls {variable}
+
+ +

+This would run ls -l when the command wdocker list is called. +

+ +

+As you can see you're not limited to using docker in your wdocker +commands. This property is what allows me to use wdocker in my +workflow. +

+
+
+ +
+

3 Combining with docker-compose

+
+

+I started using docker not too long ago at work to develop our +projects in. This is nice because it allows me to completely isolate +my development environments. Since we have a few processes running +together a single docker image isn't a great option, so I use +docker-compose to define and combine the containers I need. +

+ +

+As a side-effect this requires me to write long commands to do +something like run rspec tests: +

+ +
+docker-compose run --rm -e RACK_ENV=test -e RAILS_ENV=test \
+    container bundle exec rspec
+
+ +

+The alternative is defining a specialized test container with a +bogus entry command (such as true) and use that, which would still +make the command: +

+ +
+docker-compose run --rm test-container bundle exec rspec
+
+ +

+Instead I can define a wdocker command in the Dockerfile used to +build the containers used: +

+ +
+ +
#wd# rspec: docker-compose run --rm -e RACK_ENV=test -e RAILS_ENV=test container bundle exec rspec
+
+FROM ruby
+
+#...
+
+
+ +

+Now I can run the following, much shorter, command to run the rspec +tests: +

+ +
+wdocker rspec
+
+ +

+We also use cucumber for some other tests, which is even longer to +type in, adding the cucumber command is easy: +

+ +
+ +
#wd# rspec: docker-compose run --rm -e RACK_ENV=test -e RAILS_ENV=test container bundle exec rspec
+#wd# cucumber: docker-compose run --rm -e RACK_ENV=test -e RAILS_ENV=test container bundle exec cucumber
+
+FROM ruby
+
+# ...
+
+
+ +

+Now I can run wdocker cucumber as well. +

+ +

+The latest git version of wdocker passes any arguments after the +command name directly to the command to be executed. So if I need to +run tests in a single spec file I can just do: +

+ +
+wdocker rspec spec/models/mymodel_spec.rb
+
+ +

+We have two commands defined now that are 90% the same. I always use +the --rm switch to remove the started container after it's done, I +don't want a lot of containers piling up. I also always have to use +bundle exec to run commands, since the containers don't use rvm or +add the script directories to $PATH. We can extract them to some +variables: +

+ +
+ +
#wd# run = docker-compose run --rm
+#wd# exec = bundle exec
+#wd# test = -e RACK_ENV=test -e RAILS_ENV=test
+
+#wd# rspec: {run} {test} container {exec} rspec
+#wd# cucumber: {run} {test} container {exec} cucumber
+
+FROM ruby
+
+# ...
+
+
+ +

+Right now these commands always use the container service defined +in docker-compose.yml. I could add it to the run command, but I +might need to run some commands on another container, but I can +define another variable: +

+ +
+ +
#wd# run = docker-compose run --rm
+#wd# test = -e RACK_ENV=test -e RAILS_ENV=test
+#wd# run-test-container = {run} {test} container
+#wd# exec = bundle exec
+
+#wd# rspec: {run-test-container} {exec} rspec
+#wd# cucumber: {run-test-container} {exec} cucumber
+
+FROM ruby
+
+# ...
+
+
+ +

+Now you also see that variables can be nested in other variables. +

+ +

+If you ever forget what you defined or if the mix of commands and +variables becomes too much for you, you can call the wdocker command +without arguments to see the commands you defined and the shell +commands they'll run. +

+
+