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
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]:
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
28 After that, [installing Docker][gentoo] on [[Gentoo]] is the usual:
30 # emerge -av app-emulation/docker
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:
37 # echo net.ipv4.ip_forward = 1 > /etc/sysctl.d/docker.conf
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:
57 CONFIG_CGROUP_DEVICE=y
60 CONFIG_UIDGID_STRICT_TYPE_CHECKS=y
62 CONFIG_NETFILTER_ADVANCED=y
63 CONFIG_BRIDGE_NETFILTER=y
65 CONFIG_NF_NAT_NEEDED=y
69 CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
71 CONFIG_IP_NF_TARGET_MASQUERADE=m
73 CONFIG_IP6_NF_TARGET_MASQUERADE=m
76 CONFIG_BRIDGE_IGMP_SNOOPING=y
80 CONFIG_DM_BIO_PRISON=m
81 CONFIG_DM_PERSISTENT_DATA=m
82 CONFIG_DM_THIN_PROVISIONING=m
85 CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
87 After that, I rebuilt my kernel, rebooted into the new kernel, and
88 started the daemon with:
90 # /etc/init.d/docker start
95 Docker does a good job with interactive help:
98 Usage: Docker [OPTIONS] COMMAND [arg...]
99 -H="127.0.0.1:4243": Host:port to bind/connect to
101 A self-sufficient runtime for linux containers.
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
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:
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
120 The image has everything needed by a process (filesystem, system
121 libraries, …), so you spin up the container by specifiying an image
124 $ docker run learn/tutorial echo hello world
127 Changes made to a container are preserved between runs:
129 $ docker run learn/tutorial apt-get install -y ping
131 You can checkpoint changes by committing, which adds a new layer:
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
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
143 You can list running containers:
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
151 "ID": "efefdc74a1d5900d7d7a74740e5261c09f5f42b6dae58ded6a1fde1cde7f4ac5",
152 "Created": "2013-07-30T00:54:12.417119736Z",
158 "Hostname": "efefdc74a1d5",
163 "AttachStdin": false,
164 "AttachStdout": true,
165 "AttachStderr": true,
176 "Image": "learn/ping",
185 "StartedAt": "2013-07-30T00:54:12.424817715Z",
188 "Image": "a1dbb48ce764c6651f5af98b46ed052a5f751233d731b645a6c57f91a4cb7158",
190 "IPAddress": "172.16.42.6",
192 "Gateway": "172.16.42.1",
199 "SysInitPath": "/usr/bin/docker",
200 "ResolvConfPath": "/etc/resolv.conf",
205 And you can push your local images to the repository:
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
213 You can also run interactive shells:
216 $ docker run -i -t ubuntu /bin/bash
218 You can also [set environment variables][run], which are useful for
219 customizing generic images:
221 $ docker run -e HOST=example.net -e PORT=1234 ubuntu
226 Instead of building containers manually, you can also specify them
227 with a [Dockerfile][] ([spec][Dockerfile-spec]):
229 $ cat gentoo-portage/Dockerfile
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
236 RUN emerge --sync --quiet
237 RUN eselect news read new
238 $ docker build -t wking/gentoo-portage gentoo-portage
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
246 RUN echo 'LANG="en_US.UTF-8"' >> /etc/env.d/02locale
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
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.
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 …`:
265 $ docker run -i -t -v /usr/portage:/usr/portage:ro -v /usr/portage/distfiles:/usr/portage/distfiles:rw wking/gentoo-portage /bin/bash
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:
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
283 then you can just change it's address:
285 # ip addr del 10.0.42.1/16 dev docker0
286 # ip addr add 172.31.42.1/16 dev docker0
288 If the `docker0` bridge doesn't already exist, you'll have to [create
289 it yourself][bridge]:
291 # brctl addbr docker0
292 # ip addr add 172.31.0.1/16 dev docker0
293 # ip link set dev docker0 up
295 If you want to start over from scratch, you can stop docker and remove
298 # /etc/init.d/docker stop
299 # ip link set dev docker0 down
300 # brctl delbr docker0
305 You can [link containers by name][linking]:
307 $ docker run -d -name redis crosbymichael/redis
308 $ sudo docker run -link redis:db -d -name webapp me/someapp
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.
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/