summaryrefslogtreecommitdiffstats
path: root/wdocker_compose.post
blob: 6fdd8450db07d25b49c38a36195de515a2b339ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
;;;;;
title: Making docker-compose easier with wdocker
date: 2016-02-21
tags: wdocker docker docker-compose
format: html
;;;;;

<div id="outline-container-orgheadline1" class="outline-2">
<h2 id="orgheadline1">Introduction</h2>
<div class="outline-text-2" id="text-orgheadline1">
<p>
<a href="https://github.com/babab/wdocker">wdocker</a> is a little utility written by a <a href="https://benjamin.althu.es">friend</a> and former colleague
of mine. It allows you to define commands for it in a
<code>Dockerfile</code>. He wrote it because he used a lot of composite
commands when writing docker images like:
</p>

<div class="org-src-container">

<pre class="src src-sh">docker stop CONTAINER &amp;&amp; docker rm CONTAINER &amp;&amp; docker rmi IMAGE &amp;&amp; <span class="org-sh-escaped-newline">\</span>
    docker build -t IMAGE &amp;&amp; docker run --name CONTAINER IMAGE
</pre>
</div>

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

<div class="org-src-container">

<pre class="src src-dockerfile"><span class="org-comment-delimiter">#</span><span class="org-comment">wd# container = CONTAINER</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# image = IMAGE</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# stop = docker stop {container}</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# rm = docker rm {container}</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# rmi = docker rmi {container}</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# build = docker build -t {image}</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# run = docker run --name {container} {image}</span>

<span class="org-comment-delimiter">#</span><span class="org-comment">wd# rebuild: {stop} &amp;&amp; {rm} &amp;&amp; {rmi} &amp;&amp; {build} &amp;&amp; {run}</span>

<span class="org-keyword">FROM</span> ubuntu

<span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
</pre>
</div>

<p>
Now he can use the following command instead of the list presented
before:
</p>

<pre class="example">
wdocker rebuild
</pre>
</div>
</div>

<div id="outline-container-orgheadline2" class="outline-2">
<h2 id="orgheadline2">Syntax</h2>
<div class="outline-text-2" id="text-orgheadline2">
<p>
wdocker has very simple syntax. You can define variables and
commands:
</p>

<pre class="example">
#wd# variable = value
#wd# command: program
</pre>

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

<pre class="example">
#wd# variable = -l
#wd# list: ls {variable}
</pre>

<p>
This would run <code>ls -l</code> when the command <code>wdocker list</code> is called.
</p>

<p>
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.
</p>
</div>
</div>

<div id="outline-container-orgheadline3" class="outline-2">
<h2 id="orgheadline3">Combining with docker-compose</h2>
<div class="outline-text-2" id="text-orgheadline3">
<p>
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.
</p>

<p>
As a side-effect this requires me to write long commands to do
something like run rspec tests:
</p>

<pre class="example">
docker-compose run --rm -e RACK_ENV=test -e RAILS_ENV=test \
    container bundle exec rspec
</pre>

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

<pre class="example">
docker-compose run --rm test-container bundle exec rspec
</pre>

<p>
Instead I can define a wdocker command in the <code>Dockerfile</code> used to
build the containers used:
</p>

<div class="org-src-container">

<pre class="src src-dockerfile"><span class="org-comment-delimiter">#</span><span class="org-comment">wd# rspec: docker-compose run --rm -e RACK_ENV=test -e RAILS_ENV=test container bundle exec rspec</span>

<span class="org-keyword">FROM</span> ruby

<span class="org-comment-delimiter">#</span><span class="org-comment">...</span>
</pre>
</div>

<p>
Now I can run the following, much shorter, command to run the rspec
tests:
</p>

<pre class="example">
wdocker rspec
</pre>

<p>
We also use cucumber for some other tests, which is even longer to
type in, adding the <code>cucumber</code> command is easy:
</p>

<div class="org-src-container">

<pre class="src src-dockerfile"><span class="org-comment-delimiter">#</span><span class="org-comment">wd# rspec: docker-compose run --rm -e RACK_ENV=test -e RAILS_ENV=test container bundle exec rspec</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# cucumber: docker-compose run --rm -e RACK_ENV=test -e RAILS_ENV=test container bundle exec cucumber</span>

<span class="org-keyword">FROM</span> ruby

<span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
</pre>
</div>

<p>
Now I can run <code>wdocker cucumber</code> as well.
</p>

<p>
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:
</p>

<pre class="example">
wdocker rspec spec/models/mymodel_spec.rb
</pre>

<p>
We have two commands defined now that are 90% the same. I always use
the <code>--rm</code> 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
<code>bundle exec</code> to run commands, since the containers don't use rvm or
add the script directories to <code>$PATH</code>. We can extract them to some
variables:
</p>

<div class="org-src-container">

<pre class="src src-dockerfile"><span class="org-comment-delimiter">#</span><span class="org-comment">wd# run = docker-compose run --rm</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# exec = bundle exec</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# test = -e RACK_ENV=test -e RAILS_ENV=test</span>

<span class="org-comment-delimiter">#</span><span class="org-comment">wd# rspec: {run} {test} container {exec} rspec</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# cucumber: {run} {test} container {exec} cucumber</span>

<span class="org-keyword">FROM</span> ruby

<span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
</pre>
</div>

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

<div class="org-src-container">

<pre class="src src-dockerfile"><span class="org-comment-delimiter">#</span><span class="org-comment">wd# run = docker-compose run --rm</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# test = -e RACK_ENV=test -e RAILS_ENV=test</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# run-test-container = {run} {test} container</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# exec = bundle exec</span>

<span class="org-comment-delimiter">#</span><span class="org-comment">wd# rspec: {run-test-container} {exec} rspec</span>
<span class="org-comment-delimiter">#</span><span class="org-comment">wd# cucumber: {run-test-container} {exec} cucumber</span>

<span class="org-keyword">FROM</span> ruby

<span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
</pre>
</div>

<p>
Now you also see that variables can be nested in other variables.
</p>

<p>
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.
</p>
</div>
</div>