mkogg.py: Fix 'self.get_mp4_metadata(self, source)'
[blog.git] / posts / Docker.mdwn
1 [Docker][] is a tool for managing [Linux containers][wikipedia-lxc]
2 ([LXC][lxc]).  LXC allows you to provision multiple, isolated
3 process-spaces on the same kernel, which is useful for creating
4 disposable development/staging/production environments.  Docker
5 provides a sleek frontend for container managerment.  Like [[Salt
6 Stack|Salt_Stack]], it uses a daemonized manager with a command-line
7 client.
8
9 Installation
10 ============
11
12 To avoid the [aufs3][] dependency, I wanted [Docker v0.7+][v0.7].  The
13 main portage tree is currently at Docker v0.6.6, so I installed the
14 [docker overlay][overlay]:
15
16     # layman -a docker
17
18 I also wanted Go v1.2+ to avoid a [“slice bounds out of range” on
19 /usr/lib/go/src/pkg/archive/tar/writer.go:233][1509] (fixed upstream
20 in [0c7e4c4, archive/tar: Fix support for long links and improve PAX
21 support, 2013-08-18][0c7e4c4].  Thanks to [Jonathan Stoppani][JS] for
22 [help figuring this out][overlay-11]).  That version is not in the
23 main Portage tree yet, but [it is in][go-zugaina] the [OSSDL
24 overlay][OSSDL]:
25
26     # layman -a OSSDL
27
28 After that, [installing Docker][gentoo] on [[Gentoo]] is the usual:
29
30     # emerge -av app-emulation/docker
31
32 After reading through a few docs about IP forwarding, I determined
33 that my internal development box could safely enable IP forwarding,
34 which containers use to connect to the outside network.  I enabled it
35 for subsequent reboots:
36
37     # echo net.ipv4.ip_forward = 1 > /etc/sysctl.d/docker.conf
38
39 I also had to enable the following additional kernel options (as
40 suggested by `app-emulation/lxc`): `CONFIG_CGROUP_DEVICE`,
41 `CONFIG_USER_NS`, `CONFIG_DEVPTS_MULTIPLE_INSTANCES`, `CONFIG_VETH`,
42 and `CONFIG_MACVLAN`.  There's also the convenient `lxc-checkconfig`
43 script distributed with [app-emulation/lxc][lxc], which pointed out
44 the need for `CONFIG_CGROUP_MEM_RES_CTLR` (renamed to `CONFIG_MEMCG`
45 in [c255a45 (memcg: rename config variables, 2012-07-31)][c255a45],
46 released in Linux v3.6, `lx-checkconfig` was updated in [c93c7b1, Fix
47 checkconfig to handle kernel memory cgroup name change,
48 2012-11-14][c93c7b1], released in LXC v0.9.0) and `CONFIG_VLAN_8021Q`.
49 On top of those, `app-emulation/docker` recommended `CONFIG_BRIDGE`,
50 `CONFIG_NETFILTER_XT_MATCH_ADDRTYPE`, `CONFIG_NF_NAT`,
51 `CONFIG_NF_NAT_NEEDED`, `CONFIG_IP_NF_TARGET_MASQUERADE` (since
52 [045eb9f (another necessary kernel flag, 2013-12-09)][045eb9f], in a
53 fast response to my [comment][866-wtk]), and
54 `CONFIG_DM_THIN_PROVISIONING`.  These are the new docker-supporting
55 lines in my `.config` for Linux v3.10:
56
57     CONFIG_CGROUP_DEVICE=y
58     CONFIG_MEMCG=y
59     CONFIG_USER_NS=y
60     CONFIG_UIDGID_STRICT_TYPE_CHECKS=y
61     CONFIG_MM_OWNER=y
62     CONFIG_NETFILTER_ADVANCED=y
63     CONFIG_BRIDGE_NETFILTER=y
64     CONFIG_NF_NAT=m
65     CONFIG_NF_NAT_NEEDED=y
66     CONFIG_NF_NAT_FTP=m
67     CONFIG_NF_NAT_IRC=m
68     CONFIG_NF_NAT_SIP=m
69     CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
70     CONFIG_NF_NAT_IPV4=m
71     CONFIG_IP_NF_TARGET_MASQUERADE=m
72     CONFIG_NF_NAT_IPV6=m
73     CONFIG_IP6_NF_TARGET_MASQUERADE=m
74     CONFIG_STP=m
75     CONFIG_BRIDGE=m
76     CONFIG_BRIDGE_IGMP_SNOOPING=y
77     CONFIG_VLAN_8021Q=m
78     CONFIG_LLC=m
79     CONFIG_DM_BUFIO=m
80     CONFIG_DM_BIO_PRISON=m
81     CONFIG_DM_PERSISTENT_DATA=m
82     CONFIG_DM_THIN_PROVISIONING=m
83     CONFIG_MACVLAN=m
84     CONFIG_VETH=m
85     CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
86
87 After that, I rebuilt my kernel, rebooted into the new kernel, and
88 started the daemon with:
89
90     # /etc/init.d/docker start
91
92 Command line usage
93 ==================
94
95 Docker does a good job with interactive help:
96
97     $ docker
98     Usage: Docker [OPTIONS] COMMAND [arg...]
99     -H="127.0.0.1:4243": Host:port to bind/connect to
100
101     A self-sufficient runtime for linux containers.
102
103     Commands:
104
105     attach    Attach to a running container
106     build     Build a container from a Dockerfile
107     commit    Create a new image from a container's changes
108     …
109
110 Docker images are [archived][] for easy reuse, so it's likely someone
111 has the image you need (or a good start) already built.  Docker's
112 images consist of a number of layers on top of the base image:
113
114     $ docker pull learn/tutorial
115     Pulling repository learn/tutorial from https://index.docker.io/v1
116     Pulling image 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c (precise) from ubuntu
117     Pulling image b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc (12.10) from ubuntu
118     Pulling image 27cf784147099545 () from tutorial
119
120 The image has everything needed by a process (filesystem, system
121 libraries, …), so you spin up the container by specifiying an image
122 and target command.
123
124     $ docker run learn/tutorial echo hello world
125     hello world
126
127 Changes made to a container are preserved between runs:
128
129     $ docker run learn/tutorial apt-get install -y ping
130
131 You can checkpoint changes by committing, which adds a new layer:
132
133     $ docker ps -l
134     ID            IMAGE         COMMAND               CREATED       STATUS  PORTS
135     6982a9948422  ubuntu:12.04  apt-get install ping  1 minute ago  Exit 0
136     $ docker commit 6982a99 learn/ping
137     effb66b31edb
138     $ docker run learn/ping ping www.google.com
139     64 bytes from nuq05s02-in-f20.1e100.net (74.125.239.148): icmp_req=1 ttl=55 time=2.23 ms
140     64 bytes from nuq05s02-in-f20.1e100.net (74.125.239.148): icmp_req=2 ttl=55 time=2.30 ms
141     ^C
142
143 You can list running containers:
144
145     $ docker ps
146     ID            IMAGE              COMMAND              CREATED         STATUS         PORTS
147     efefdc74a1d5  learn/ping:latest  ping www.google.com  37 seconds ago  Up 36 seconds
148     $ docker inspect efefdc7
149     [2013/07/30 01:52:26 GET /v1.3/containers/efef/json
150     {
151       "ID": "efefdc74a1d5900d7d7a74740e5261c09f5f42b6dae58ded6a1fde1cde7f4ac5",
152       "Created": "2013-07-30T00:54:12.417119736Z",
153       "Path": "ping",
154       "Args": [
155           "www.google.com"
156       ],
157       "Config": {
158           "Hostname": "efefdc74a1d5",
159           "User": "",
160           "Memory": 0,
161           "MemorySwap": 0,
162           "CpuShares": 0,
163           "AttachStdin": false,
164           "AttachStdout": true,
165           "AttachStderr": true,
166           "PortSpecs": null,
167           "Tty": false,
168           "OpenStdin": false,
169           "StdinOnce": false,
170           "Env": null,
171           "Cmd": [
172               "ping",
173               "www.google.com"
174           ],
175           "Dns": null,
176           "Image": "learn/ping",
177           "Volumes": null,
178           "VolumesFrom": "",
179           "Entrypoint": null
180       },
181       "State": {
182           "Running": true,
183           "Pid": 22249,
184           "ExitCode": 0,
185           "StartedAt": "2013-07-30T00:54:12.424817715Z",
186           "Ghost": false
187       },
188       "Image": "a1dbb48ce764c6651f5af98b46ed052a5f751233d731b645a6c57f91a4cb7158",
189       "NetworkSettings": {
190           "IPAddress": "172.16.42.6",
191           "IPPrefixLen": 24,
192           "Gateway": "172.16.42.1",
193           "Bridge": "docker0",
194           "PortMapping": {
195               "Tcp": {},
196               "Udp": {}
197           }
198       },
199       "SysInitPath": "/usr/bin/docker",
200       "ResolvConfPath": "/etc/resolv.conf",
201       "Volumes": {},
202       "VolumesRW": {}
203     }
204
205 And you can push your local images to the repository:
206
207     $ docker images
208     ubuntu          latest  8dbd9e392a96  4 months ago    131.5 MB (virtual 131.5 MB)
209     learn/tutorial  latest  8dbd9e392a96  2 months ago    131.5 MB (virtual 131.5 MB)
210     learn/ping      latest  effb66b31edb  10 minutes ago  11.57 MB (virtual 143.1 MB)
211     $ docker push learn/ping
212
213 You can also run interactive shells:
214
215     $ docker pull ubuntu
216     $ docker run -i -t ubuntu /bin/bash
217
218 You can also [set environment variables][run], which are useful for
219 customizing generic images:
220
221     $ docker run -e HOST=example.net -e PORT=1234 ubuntu
222
223 Dockerfiles
224 ===========
225
226 Instead of building containers manually, you can also specify them
227 with a [Dockerfile][] ([spec][Dockerfile-spec]):
228
229     $ cat gentoo-portage/Dockerfile
230     FROM tianon/gentoo
231     MAINTAINER W. Trevor King, wking@tremily.us
232     RUN echo 'GENTOO_MIRRORS="http://mirror.mcs.anl.gov/pub/gentoo/"' >> /etc/portage/make.conf
233     #RUN echo 'SYNC="rsync://rsync.us.gentoo.org"' >> /etc/portage/make.conf
234     RUN mkdir -p /usr/portage
235     RUN emerge-webrsync
236     RUN emerge --sync --quiet
237     RUN eselect news read new
238     $ docker build -t wking/gentoo-portage gentoo-portage
239     …
240     $ cat gentoo-portage-en-us/Dockerfile
241     FROM wking/gentoo-portage
242     MAINTAINER W. Trevor King, wking@tremily.us
243     RUN echo en_US ISO-8859-1 > /etc/locale.gen
244     RUN echo en_US.UTF-8 UTF-8 >> /etc/locale.gen
245     RUN locale-gen
246     RUN echo 'LANG="en_US.UTF-8"' >> /etc/env.d/02locale
247     RUN env-update
248     $ docker build -t wking/gentoo-portage-en-us gentoo-portage-en-us
249     $ cat gentoo-portage-en-us-syslog/Dockerfile
250     FROM wking/gentoo-portage-en-us
251     MAINTAINER W. Trevor King, wking@tremily.us
252     RUN emerge -v sys-process/vixie-cron app-admin/syslog-ng app-admin/logrotate
253     RUN rc-update add syslog-ng default
254     RUN rc-update add vixie-cron default
255     $ docker build -t wking/gentoo-portage-en-us-syslog gentoo-portage-en-us-syslog
256
257 You can't currently set the description (returned by `docker search
258 …`) from the `Dockerfile`, although there [are][769] [some][2167]
259 [proposals][2956] to add this feature.
260
261 You can mount volumes from the `Dockerfile` using [VOLUME][], but it
262 [doesn't][1124-explicit] support host mounts.  For those you have to
263 use the [-v][run-v] option when you invoke `docker run …`:
264
265     $ docker run -i -t -v /usr/portage:/usr/portage:ro -v /usr/portage/distfiles:/usr/portage/distfiles:rw wking/gentoo-portage /bin/bash
266
267 Bridging
268 ========
269
270 Docker sets up a `docker0` bridge between the host's network and the
271 containers.  Docker tries to guess an IP range that does not conflict
272 with your local network, but [it's not omniscient][1558].  Until
273 [1558][] is fixed, you're best bet is to set up your own bridge.  If
274 you already have a `docker0` bridge:
275
276     $ ip addr show dev docker0
277     5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
278         link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
279         inet 10.0.42.1/16 scope global docker0
280            valid_lft forever preferred_lft forever
281     …
282
283 then you can just change it's address:
284
285     # ip addr del 10.0.42.1/16 dev docker0
286     # ip addr add 172.31.42.1/16 dev docker0
287
288 If the `docker0` bridge doesn't already exist, you'll have to [create
289 it yourself][bridge]:
290
291     # brctl addbr docker0
292     # ip addr add 172.31.0.1/16 dev docker0
293     # ip link set dev docker0 up
294
295 If you want to start over from scratch, you can stop docker and remove
296 the bridge:
297
298     # /etc/init.d/docker stop
299     # ip link set dev docker0 down
300     # brctl delbr docker0
301
302 Linking
303 =======
304
305 You can [link containers by name][linking]:
306
307     $ docker run -d -name redis crosbymichael/redis
308     $ sudo docker run -link redis:db -d -name webapp me/someapp
309
310 This links `webapp` to `redis` using the alias `db`.  `DB_PORT` (and
311 similar) environment variables are set in the `webapp` container,
312 which it can use to connect to `redis` container.  You can also use
313 [ambassadors][] to link containers on separate hosts.
314
315 [Docker]: http://www.docker.io/
316 [wikipedia-lxc]: http://en.wikipedia.org/wiki/LXC
317 [1509]: https://github.com/dotcloud/docker/pull/1509
318 [0c7e4c4]: http://code.google.com/p/go/source/detail?r=0c7e4c45acf8
319 [JS]: https://github.com/GaretJax
320 [overlay-11]: https://github.com/tianon/docker-overlay/issues/11
321 [go-zugaina]: http://gpo.zugaina.org/dev-lang/go
322 [OSSDL]: https://mark.ossdl.de/tag/ossdl-overlay/
323 [gentoo]: http://docs.docker.io/en/latest/installation/gentoolinux/
324 [aufs3]: http://aufs.sourceforge.net/
325 [v0.7]: http://blog.docker.io/2013/11/docker-0-7-docker-now-runs-on-any-linux-distribution/
326 [overlay]: https://github.com/tianon/docker-overlay/
327 [lxc]: http://lxc.sourceforge.net/
328 [c255a45]: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c255a458055e459f65eb7b7f51dc5dbdd0caf1d8
329 [c93c7b1]: https://github.com/lxc/lxc/commit/c93c7b1a0b0d4548780b9c22fb9ab907783caad1
330 [045eb9f]: https://github.com/tianon/docker-overlay/commit/045eb9f54bbfad07657ca1dafeb84d56c56fdbea
331 [866-wtk]: https://github.com/dotcloud/docker/issues/866#issuecomment-30190904
332 [archived]: https://index.docker.io/
333 [run]: http://docs.docker.io/en/latest/commandline/cli/#run
334 [Dockerfile]: http://www.docker.io/learn/dockerfile/
335 [Dockerfile-spec]: http://docs.docker.io/en/latest/use/builder/
336 [769]: https://github.com/dotcloud/docker/issues/769
337 [2167]: https://github.com/dotcloud/docker/issues/2176
338 [2956]: https://github.com/dotcloud/docker/pull/2956
339 [VOLUME]: http://docs.docker.io/en/latest/use/builder/#volume
340 [1124-explicit]: https://github.com/dotcloud/docker/pull/1124#issuecomment-22824230
341 [run-v]: http://docs.docker.io/en/latest/use/working_with_volumes/
342 [1558]: https://github.com/dotcloud/docker/issues/1558
343 [bridge]: http://docs.docker.io/en/latest/use/networking/
344 [linking]: http://docs.docker.io/en/latest/use/working_with_links_names/
345 [ambassadors]: http://docs.docker.io/en/latest/use/ambassador_pattern_linking/
346
347 [[!tag tags/linux]]
348 [[!tag tags/tools]]