--- /dev/null
+[Docker][] is a tool for managing [Linux containers][wikipedia-lxc]
+([LXC][lxc]). LXC allows you to provision multiple, isolated
+process-spaces on the same kernel, which is useful for creating
+disposable development/staging/production environments. Docker
+provides a sleek frontend for container managerment. Like [[Salt
+Stack|Salt_Stack]], it uses a daemonized manager with a command-line
+client.
+
+Installation
+============
+
+To avoid the [aufs3][] dependency, I wanted [Docker v0.7+][v0.7]. The
+main portage tree is currently at Docker v0.6.6, so I installed the
+[docker overlay][overlay]:
+
+ # layman -a docker
+
+I also wanted Go v1.2+ to avoid a [“slice bounds out of range” on
+/usr/lib/go/src/pkg/archive/tar/writer.go:233][1509] (fixed upstream
+in [0c7e4c4, archive/tar: Fix support for long links and improve PAX
+support, 2013-08-18][0c7e4c4]. Thanks to [Jonathan Stoppani][JS] for
+[help figuring this out][overlay-11]). That version is not in the
+main Portage tree yet, but [it is in][go-zugaina] the [OSSDL
+overlay][OSSDL]:
+
+ # layman -a OSSDL
+
+After that, [installing Docker][gentoo] on [[Gentoo]] is the usual:
+
+ # emerge -av app-emulation/docker
+
+After reading through a few docs about IP forwarding, I determined
+that my internal development box could safely enable IP forwarding,
+which containers use to connect to the outside network. I enabled it
+for subsequent reboots:
+
+ # echo net.ipv4.ip_forward = 1 > /etc/sysctl.d/docker.conf
+
+I also had to enable the following additional kernel options (as
+suggested by `app-emulation/lxc`): `CONFIG_CGROUP_DEVICE`,
+`CONFIG_USER_NS`, `CONFIG_DEVPTS_MULTIPLE_INSTANCES`, `CONFIG_VETH`,
+and `CONFIG_MACVLAN`. There's also the convenient `lxc-checkconfig`
+script distributed with [app-emulation/lxc][lxc], which pointed out
+the need for `CONFIG_CGROUP_MEM_RES_CTLR` (renamed to `CONFIG_MEMCG`
+in [c255a45 (memcg: rename config variables, 2012-07-31)][c255a45],
+released in Linux v3.6) and `CONFIG_VLAN_8021Q`. On top of those,
+`app-emulation/docker` recommended `CONFIG_BRIDGE`,
+`CONFIG_NETFILTER_XT_MATCH_ADDRTYPE`, `CONFIG_NF_NAT`,
+`CONFIG_NF_NAT_NEEDED`, `CONFIG_IP_NF_TARGET_MASQUERADE` (since
+[045eb9f (another necessary kernel flag, 2013-12-09)][045eb9f], in a
+fast response to my [comment][866-wtk]), and
+`CONFIG_DM_THIN_PROVISIONING`. These are the new docker-supporting
+lines in my `.config` for Linux v3.10:
+
+ CONFIG_CGROUP_DEVICE=y
+ CONFIG_MEMCG=y
+ CONFIG_USER_NS=y
+ CONFIG_UIDGID_STRICT_TYPE_CHECKS=y
+ CONFIG_MM_OWNER=y
+ CONFIG_NETFILTER_ADVANCED=y
+ CONFIG_BRIDGE_NETFILTER=y
+ CONFIG_NF_NAT=m
+ CONFIG_NF_NAT_NEEDED=y
+ CONFIG_NF_NAT_FTP=m
+ CONFIG_NF_NAT_IRC=m
+ CONFIG_NF_NAT_SIP=m
+ CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+ CONFIG_NF_NAT_IPV4=m
+ CONFIG_IP_NF_TARGET_MASQUERADE=m
+ CONFIG_NF_NAT_IPV6=m
+ CONFIG_IP6_NF_TARGET_MASQUERADE=m
+ CONFIG_STP=m
+ CONFIG_BRIDGE=m
+ CONFIG_BRIDGE_IGMP_SNOOPING=y
+ CONFIG_VLAN_8021Q=m
+ CONFIG_LLC=m
+ CONFIG_DM_BUFIO=m
+ CONFIG_DM_BIO_PRISON=m
+ CONFIG_DM_PERSISTENT_DATA=m
+ CONFIG_DM_THIN_PROVISIONING=m
+ CONFIG_MACVLAN=m
+ CONFIG_VETH=m
+ CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+
+After that, I rebuilt my kernel, rebooted into the new kernel, and
+started the daemon with:
+
+ # /etc/init.d/docker start
+
+Command line usage
+==================
+
+Docker does a good job with interactive help:
+
+ $ docker
+ Usage: Docker [OPTIONS] COMMAND [arg...]
+ -H="127.0.0.1:4243": Host:port to bind/connect to
+
+ A self-sufficient runtime for linux containers.
+
+ Commands:
+
+ attach Attach to a running container
+ build Build a container from a Dockerfile
+ commit Create a new image from a container's changes
+ …
+
+Docker images are [archived][] for easy reuse, so it's likely someone
+has the image you need (or a good start) already built. Docker's
+images consist of a number of layers on top of the base image:
+
+ $ docker pull learn/tutorial
+ Pulling repository learn/tutorial from https://index.docker.io/v1
+ Pulling image 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c (precise) from ubuntu
+ Pulling image b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc (12.10) from ubuntu
+ Pulling image 27cf784147099545 () from tutorial
+
+The image has everything needed by a process (filesystem, system
+libraries, …), so you spin up the container by specifiying an image
+and target command.
+
+ $ docker run learn/tutorial echo hello world
+ hello world
+
+Changes made to a container are preserved between runs:
+
+ $ docker run learn/tutorial apt-get install -y ping
+
+You can checkpoint changes by committing, which adds a new layer:
+
+ $ docker ps -l
+ ID IMAGE COMMAND CREATED STATUS PORTS
+ 6982a9948422 ubuntu:12.04 apt-get install ping 1 minute ago Exit 0
+ $ docker commit 6982a99 learn/ping
+ effb66b31edb
+ $ docker run learn/ping ping www.google.com
+ 64 bytes from nuq05s02-in-f20.1e100.net (74.125.239.148): icmp_req=1 ttl=55 time=2.23 ms
+ 64 bytes from nuq05s02-in-f20.1e100.net (74.125.239.148): icmp_req=2 ttl=55 time=2.30 ms
+ ^C
+
+You can list running containers:
+
+ $ docker ps
+ ID IMAGE COMMAND CREATED STATUS PORTS
+ efefdc74a1d5 learn/ping:latest ping www.google.com 37 seconds ago Up 36 seconds
+ $ docker inspect efefdc7
+ [2013/07/30 01:52:26 GET /v1.3/containers/efef/json
+ {
+ "ID": "efefdc74a1d5900d7d7a74740e5261c09f5f42b6dae58ded6a1fde1cde7f4ac5",
+ "Created": "2013-07-30T00:54:12.417119736Z",
+ "Path": "ping",
+ "Args": [
+ "www.google.com"
+ ],
+ "Config": {
+ "Hostname": "efefdc74a1d5",
+ "User": "",
+ "Memory": 0,
+ "MemorySwap": 0,
+ "CpuShares": 0,
+ "AttachStdin": false,
+ "AttachStdout": true,
+ "AttachStderr": true,
+ "PortSpecs": null,
+ "Tty": false,
+ "OpenStdin": false,
+ "StdinOnce": false,
+ "Env": null,
+ "Cmd": [
+ "ping",
+ "www.google.com"
+ ],
+ "Dns": null,
+ "Image": "learn/ping",
+ "Volumes": null,
+ "VolumesFrom": "",
+ "Entrypoint": null
+ },
+ "State": {
+ "Running": true,
+ "Pid": 22249,
+ "ExitCode": 0,
+ "StartedAt": "2013-07-30T00:54:12.424817715Z",
+ "Ghost": false
+ },
+ "Image": "a1dbb48ce764c6651f5af98b46ed052a5f751233d731b645a6c57f91a4cb7158",
+ "NetworkSettings": {
+ "IPAddress": "172.16.42.6",
+ "IPPrefixLen": 24,
+ "Gateway": "172.16.42.1",
+ "Bridge": "docker0",
+ "PortMapping": {
+ "Tcp": {},
+ "Udp": {}
+ }
+ },
+ "SysInitPath": "/usr/bin/docker",
+ "ResolvConfPath": "/etc/resolv.conf",
+ "Volumes": {},
+ "VolumesRW": {}
+ }
+
+And you can push your local images to the repository:
+
+ $ docker images
+ ubuntu latest 8dbd9e392a96 4 months ago 131.5 MB (virtual 131.5 MB)
+ learn/tutorial latest 8dbd9e392a96 2 months ago 131.5 MB (virtual 131.5 MB)
+ learn/ping latest effb66b31edb 10 minutes ago 11.57 MB (virtual 143.1 MB)
+ $ docker push learn/ping
+
+You can also run interactive shells:
+
+ $ docker pull ubuntu
+ $ docker run -i -t ubuntu /bin/bash
+
+You can also [set environment variables][run], which are useful for
+customizing generic images:
+
+ $ docker run -e HOST=example.net -e PORT=1234 ubuntu
+
+Dockerfiles
+===========
+
+Instead of building containers manually, you can also specify them
+with a [Dockerfile][] ([spec][Dockerfile-spec]):
+
+ $ cat gentoo-portage/Dockerfile
+ FROM tianon/gentoo
+ MAINTAINER W. Trevor King, wking@tremily.us
+ RUN echo 'GENTOO_MIRRORS="http://mirror.mcs.anl.gov/pub/gentoo/"' >> /etc/portage/make.conf
+ #RUN echo 'SYNC="rsync://rsync.us.gentoo.org"' >> /etc/portage/make.conf
+ RUN mkdir -p /usr/portage
+ RUN emerge-webrsync
+ RUN emerge --sync --quiet
+ RUN eselect news read new
+ $ docker build -t wking/gentoo-portage gentoo-portage
+ …
+ $ cat gentoo-portage-en-us/Dockerfile
+ FROM wking/gentoo-portage
+ MAINTAINER W. Trevor King, wking@tremily.us
+ RUN echo en_US ISO-8859-1 > /etc/locale.gen
+ RUN echo en_US.UTF-8 UTF-8 >> /etc/locale.gen
+ RUN locale-gen
+ RUN echo 'LANG="en_US.UTF-8"' >> /etc/env.d/02locale
+ RUN env-update
+ $ docker build -t wking/gentoo-portage-en-us gentoo-portage-en-us
+ $ cat gentoo-portage-en-us-syslog/Dockerfile
+ FROM wking/gentoo-portage-en-us
+ MAINTAINER W. Trevor King, wking@tremily.us
+ RUN emerge -v sys-process/vixie-cron app-admin/syslog-ng app-admin/logrotate
+ RUN rc-update add syslog-ng default
+ RUN rc-update add vixie-cron default
+ $ docker build -t wking/gentoo-portage-en-us-syslog gentoo-portage-en-us-syslog
+
+You can't currently set the description (returned by `docker search
+…`) from the `Dockerfile`, although there [are][769] [some][2167]
+[proposals][2956] to add this feature.
+
+You can mount volumes from the `Dockerfile` using [VOLUME][], but it
+[doesn't][1124-explicit] support host mounts. For those you have to
+use the [-v][run-v] option when you invoke `docker run …`:
+
+ $ docker run -i -t -v /usr/portage:/usr/portage:ro -v /usr/portage/distfiles:/usr/portage/distfiles:rw wking/gentoo-portage /bin/bash
+
+Bridging
+========
+
+Docker sets up a `docker0` bridge between the host's network and the
+containers. Docker tries to guess an IP range that does not conflict
+with your local network, but [it's not omniscient][1558]. Until
+[1558][] is fixed, you're best bet is to set up your own bridge. If
+you already have a `docker0` bridge:
+
+ $ ip addr show dev docker0
+ 5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
+ link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
+ inet 10.0.42.1/16 scope global docker0
+ valid_lft forever preferred_lft forever
+ …
+
+then you can just change it's address:
+
+ # ip addr del 10.0.42.1/16 dev docker0
+ # ip addr add 172.31.42.1/16 dev docker0
+
+If the `docker0` bridge doesn't already exist, you'll have to [create
+it yourself][bridge]:
+
+ # brctl addbr docker0
+ # ip addr add 172.31.0.1/16 dev docker0
+ # ip link set dev docker0 up
+
+If you want to start over from scratch, you can stop docker and remove
+the bridge:
+
+ # /etc/init.d/docker stop
+ # ip link set dev docker0 down
+ # brctl delbr docker0
+
+Linking
+=======
+
+You can [link containers by name][linking]:
+
+ $ docker run -d -name redis crosbymichael/redis
+ $ sudo docker run -link redis:db -d -name webapp me/someapp
+
+This links `webapp` to `redis` using the alias `db`. `DB_PORT` (and
+similar) environment variables are set in the `webapp` container,
+which it can use to connect to `redis` container. You can also use
+[ambassadors][] to link containers on separate hosts.
+
+[Docker]: http://www.docker.io/
+[wikipedia-lxc]: http://en.wikipedia.org/wiki/LXC
+[1509]: https://github.com/dotcloud/docker/pull/1509
+[0c7e4c4]: http://code.google.com/p/go/source/detail?r=0c7e4c45acf8
+[JS]: https://github.com/GaretJax
+[overlay-11]: https://github.com/tianon/docker-overlay/issues/11
+[go-zugaina]: http://gpo.zugaina.org/dev-lang/go
+[OSSDL]: https://mark.ossdl.de/tag/ossdl-overlay/
+[gentoo]: http://docs.docker.io/en/latest/installation/gentoolinux/
+[aufs3]: http://aufs.sourceforge.net/
+[v0.7]: http://blog.docker.io/2013/11/docker-0-7-docker-now-runs-on-any-linux-distribution/
+[overlay]: https://github.com/tianon/docker-overlay/
+[lxc]: http://lxc.sourceforge.net/
+[c255a45]: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c255a458055e459f65eb7b7f51dc5dbdd0caf1d8
+[045eb9f]: https://github.com/tianon/docker-overlay/commit/045eb9f54bbfad07657ca1dafeb84d56c56fdbea
+[866-wtk]: https://github.com/dotcloud/docker/issues/866#issuecomment-30190904
+[archived]: https://index.docker.io/
+[run]: http://docs.docker.io/en/latest/commandline/cli/#run
+[Dockerfile]: http://www.docker.io/learn/dockerfile/
+[Dockerfile-spec]: http://docs.docker.io/en/latest/use/builder/
+[769]: https://github.com/dotcloud/docker/issues/769
+[2167]: https://github.com/dotcloud/docker/issues/2176
+[2956]: https://github.com/dotcloud/docker/pull/2956
+[VOLUME]: http://docs.docker.io/en/latest/use/builder/#volume
+[1124-explicit]: https://github.com/dotcloud/docker/pull/1124#issuecomment-22824230
+[run-v]: http://docs.docker.io/en/latest/use/working_with_volumes/
+[1558]: https://github.com/dotcloud/docker/issues/1558
+[bridge]: http://docs.docker.io/en/latest/use/networking/
+[linking]: http://docs.docker.io/en/latest/use/working_with_links_names/
+[ambassadors]: http://docs.docker.io/en/latest/use/ambassador_pattern_linking/
+
+[[!tag tags/linux]]
+[[!tag tags/tools]]