DockerでImmutable Infrastractureに触れる

Dockerとは

DockerはクラウドベンダであるdotCloudがオープンソースで公開しているOSレベル仮想化を提供するソフトウェアであり、LXCとAUFSをベースに作られています。

LXC (LinuX Containers)

LXCは、Linux上でOSレベル仮想化を提供する仕組みです。
LXCを用いることで一つのコントロールホスト上で、コンテナと呼ばれる単位で複数の隔離されたLinuxシステムを走らせる事が可能となります。

仮想化の分類としては、物理マシンにファームウェアとしてハイパーバイザを内蔵し、ハードウェアによる仮想化を行うIBM PowerVM, 日立 Virtage。
物理マシン上にソフトウェアとしてハイパーバイザを導入し、ソフトウェアによる仮想化を行うVMWare vSphere, Xen。
ホストOSにカーネルモジュールとしてハイパーバイザ機能を追加し、ソフトウェアによる仮想化を行うKVMなどがあります。

対してLXCのOSレベル仮想化はOSへのアクセスの仮想化を行い、ホスト内の隔離された環境で仮想マシンを動かす技術です。
つまり、個別のプロセスとネットワークスペースを作り出す仮想環境であると言うことができます。

OS内部は物理リソースを管理するカーネル空間とユーザープロセスを実行するユーザー空間に分かれ、コンテナ型の仮想化ではカーネルの機能により複数のユーザー空間を作り出すことで、ユーザープロセスから見えるリソースを分割します。

LXCは、ホストおよびゲストOSがLinuxに限定されるという点はありますが、物理マシンのシミュレーションを行っていないので、VPSやEC2などの仮想マシン上でも問題なく動作し、かつマシンを起動するプロセスが不要となるので、ハイパフォーマンスかつ省リソースな仮想化ツールとして有効です。

AUFS (Advanced multi layered Unification FileSystem)

AUFSはUnionFSと呼ばれる異なるファイルシステムのファイルやディレクトリを透過的に重ね合わせ、ひとつのファイルツリーを構成できるファイルシステムの実装の一つです。
元の仮想マシンイメージを書き換えることなく、更新が発生した部分を別の場所に書き込むため、仮想マシンの立ち上げ時にイメージのコピー発生せず、すぐに使い始めることができます。

なぜDockerか

Dockerを使ってみようと思ったは、Immutable Infrastructure という考え方を知ったからです。
Immutable Infrastructureは、6wunderlist.comのCTOであり、「情熱プログラマー」の著者であるChad Fowler氏のブログでTrash Your Servers and Burn Your Code: Immutable Infrastructure and Disposable Componentsという記事で綴られています。

Immutable Infrastracture とは

Immutableとは、状態が変更出来ないことを指しています。
つまり、Immutable Infrastractureとは「運用中のサーバーに変更を加えない」というアプローチでサーバーを管理することを意味しています。

Immutable Infrastractureの考えでは、サーバーの設定を変更する場合、その変更を加えた新しいサーバーを用意し、アプリケーションのデプロイも新しくサーバーを立ち上げてそちらにデプロイを行います。
稼働中のサーバーにSSHでログインして設定を変更するようなことはせず、常にサーバーを追加していき、DNSを張り替えた後、参照されなくなったサーバーを破棄します。
Immutable Infrastractureの実現には、Blue-Green Deploymentと呼ばれる手法をとります。

ThoughtWorksのソフトウェアデリバリーコンサルタントであるKief Moris氏は、ブログでImmutable Serverについて説明しています。

自動構成ツール(CFEngine、Puppet、Chef)はサーバをどのように構成するかを定義し、新しいマシンや既存のマシンを規約に従った構成にできます。このようなツールは脆弱なSnowflakeServersの問題を避け、解体と再構築が可能なPhoenixServersを実現します。イミュータブルサーバはこのようなツールを使ったやり方の論理的な帰結と言えます。サーバを1度配置したら、2度と変更せずに、新しいインスタンスに置き換えるのです。

つまり、仮想マシンが状態を持っているがために、冪等性や自己修復性のために条件を付けてセットアップの処理を書かなければならず、しかも定期的に構成管理ツールのサーバーと通信する必要があったが、仮想マシンが不変だという前提に立てば、その面倒が軽減されるということです。

もちろん構成管理ツールが不要になるわけではなく、ベースとなる仮想マシンの構築や、初回起動後の仮想マシンに対してマシンごとの変更を設定するために使われていくでしょう。
しかしそこではChefやPuppetのようなサーバー/クライアントタイプではなく、Ansibleのようなものの方が向いているかもしれません。

dockerに触ってみる

今回は軽くdockerに触って見ることにしましょう。ホストOSはMac OS X 10.8.5で、VIrtual Boxとvagrantはセットアップ済みとします。

CoreOS

dockerはLXCを用いているので、Linuxホストでしか実行できません。
従ってまずはOSX上にLinuxを立ち上げます。
CoreOSとは、Linux kernelとsystemdだけで構成された軽量なディストリビューションであり、dockerを動かすための最小構成として用意されています。

git clone https://github.com/coreos/coreos-vagrant/ coreos
cd coreos
vagrant up
vagrant ssh

vagrant sshでログインしてみます

Last login: Thu Oct 10 07:50:15 UTC 2013 from 10.0.2.2 on pts/0
   ______                ____  _____
  / ____/___  ________  / __ \/ ___/
 / /   / __ \/ ___/ _ \/ / / /\__ \
/ /___/ /_/ / /  /  __/ /_/ /___/ /
\____/\____/_/   \___/\____//____/
core@localhost ~ $ uname -a
Linux localhost 3.10.10+ #1 SMP Fri Oct 4 00:00:19 UTC 2013 x86_64 Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz GenuineIntel GNU/Linux
core@localhost ~ $ cat /etc/gentoo-release
CoreOS release 94.1.0
core@localhost ~ $

dockerもデフォルトで起動しています。

core@localhost ~ $ ps ax | grep docker
  427 ?        Ssl    0:00 /usr/bin/docker -d
 2195 pts/0    S+     0:00 grep --colour=auto docker 

docker

dockerで使用できるコマンド一覧です。

core@localhost ~ $ docker
Usage: docker [OPTIONS] COMMAND [arg...]
 -H=[unix:///var/run/docker.sock]: tcp://host:port to bind/connect to or unix://path/to/socket to use

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
    cp        Copy files/folders from the containers filesystem to the host path
    diff      Inspect changes on a container's filesystem
    events    Get real time events from the server
    export    Stream the contents of a container as a tar archive
    history   Show the history of an image
    images    List images
    import    Create a new filesystem image from the contents of a tarball
    info      Display system-wide information
    insert    Insert a file in an image
    inspect   Return low-level information on a container
    kill      Kill a running container
    login     Register or Login to the docker registry server
    logs      Fetch the logs of a container
    port      Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
    top       Lookup the running processes of a container
    ps        List containers
    pull      Pull an image or a repository from the docker registry server
    push      Push an image or a repository to the docker registry server
    restart   Restart a running container
    rm        Remove one or more containers
    rmi       Remove one or more images
    run       Run a command in a new container
    search    Search for an image in the docker index
    start     Start a stopped container
    stop      Stop a running container
    tag       Tag an image into a repository
    version   Show the docker version information
    wait      Block until a container stops, then print its exit code

docker searchコマンドもしくはindex.docker.ioでdockerのimageを検索することができます。

core@localhost ~ $ docker search ubuntu
Found 25 results matching your query ("ubuntu")
NAME                             DESCRIPTION
shykes/ubuntu
base                             Another general use Ubuntu base image. Tags available are: latest, quantal (12.10)
ubuntu                           General use Ubuntu base image. Tags available are: latest, quantal (12.10), precise (12.04).
boxcar/raring                    Ubuntu Raring 13.04 suitable for testing vagrant-shell
dhrp/ubuntu
creack/ubuntu                    Tags:  12.04-ssh,  12.10-ssh,  12.10-ssh-lamp.    root password: toor
crohr/ubuntu                     Ubuntu base images. Only lucid (10.04) for now.
pallet/ubuntu2                   ubuntu 12.04 with openssh-server.  root password `pallet`.
erikh/ubuntu
samalba/wget                     Test container inherited from ubuntu with wget installed
creack/ubuntu-12-10-ssh
tithonium/rvm-ubuntu             The base 'ubuntu' image, with rvm installed, and ruby 1.8.7, 1.9.2, 1.9.3, and 2.0.0 installed.    As of this writing: 1.8.7-p371, 1...
dekz/build                       13.04 ubuntu with build
ooyala/test-ubuntu
ooyala/test-my-ubuntu
ooyala/test-ubuntu2
ooyala/test-ubuntu3
ooyala/test-ubuntu4
ooyala/test-ubuntu5
surma/go                         Simple augmentation of the standard Ubuntu image with go1.1.1
nickstenning/python24            Ubuntu with Python 2.4 (in addition to system Python 2.7)
nickstenning/python25            Ubuntu with Python 2.5 (in addition to system Python 2.7)
nickstenning/python26            Ubuntu with Python 2.6 (in addition to system Python 2.7)
nickstenning/python27            Ubuntu with Python 2.7
nickstenning/python32            Ubuntu with Python 3.2 (in addition to system Python 2.7)

docker pullでimageを取得できます。
baseと名前がつけられたUbuntu quantal (12.10)を取得してみます。

core@localhost ~ $ docker pull base
Pulling repository base
b750fe79269d: Download complete
27cf78414709: Download complete

docker imagesで確認してみます。

core@localhost ~ $ docker images
REPOSITORY          TAG                 ID                  CREATED             SIZE
base                latest              b750fe79269d        6 months ago        24.65 kB (virtual 180.1 MB)
base                ubuntu-12.10        b750fe79269d        6 months ago        24.65 kB (virtual 180.1 MB)
base                ubuntu-quantal      b750fe79269d        6 months ago        24.65 kB (virtual 180.1 MB)
base                ubuntu-quantl       b750fe79269d        6 months ago        24.65 kB (virtual 180.1 MB)

docker runで仮想環境のコマンドを叩くことができます。

core@localhost ~ $ docker run base lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 12.10
Release:    12.10
Codename:   quantal

docker runのオプションです。

core@localhost ~ $ docker run

Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Run a command in a new container

  -a=map[]: Attach to stdin, stdout or stderr.
  -c=0: CPU shares (relative weight)
  -cidfile="": Write the container ID to the file
  -d=false: Detached mode: Run container in the background, print new container id
  -dns=[]: Set custom dns servers
  -e=[]: Set environment variables
  -entrypoint="": Overwrite the default entrypoint of the image
  -h="": Container host name
  -i=false: Keep stdin open even if not attached
  -lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
  -m=0: Memory limit (in bytes)
  -n=true: Enable networking for this container
  -p=[]: Expose a container's port to the host (use 'docker port' to see the actual mapping)
  -privileged=false: Give extended privileges to this container
  -t=false: Allocate a pseudo-tty
  -u="": Username or UID
  -v=map[]: Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)
  -volumes-from=[]: Mount volumes from the specified container
  -w="": Working directory inside the container

-i,-tオプションをつけてbashを叩いてコンテナにログインしてみます。

core@localhost ~ $ docker run -i -t base bash
root@70fb584cf943:/#

hoge.txtを作成して、exitします。

root@d4c5774e54a0:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  selinux  srv  sys  tmp  usr  var
root@d4c5774e54a0:/# touch hoge.txt
root@d4c5774e54a0:/# ls
bin  boot  dev  etc  hoge.txt  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  selinux  srv  sys  tmp  usr  var
root@d4c5774e54a0:/# exit
exit

再度ログインしてみると

core@localhost ~ $ docker run -i -t base bash
root@8f4a40a0d782:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  selinux  srv  sys  tmp  usr  var
root@8f4a40a0d782:/#

hoge.txtはありません。
実はすでに異なるコンテナが作成されているからです。

docker psコマンドでコンテナを確認することができます。
-aオプションで終了したコンテナも確認できます。

core@localhost ~ $ docker ps
ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS
core@localhost ~ $ docker ps -a
ID                  IMAGE               COMMAND             CREATED              STATUS              PORTS
8f4a40a0d782        base:latest         bash                About a minute ago   Exit 0
d4c5774e54a0        base:latest         bash                2 minutes ago        Exit 0

コンテナが必要なくなればdocker rmで削除します。

core@localhost ~ $ docker ps -a
ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS
8f4a40a0d782        base:latest         bash                4 minutes ago       Exit 0
d4c5774e54a0        base:latest         bash                5 minutes ago       Exit 0
core@localhost ~ $ docker rm 8f4a40a0d782
8f4a40a0d782
core@localhost ~ $ docker ps -a
ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS
d4c5774e54a0        base:latest         bash                5 minutes ago       Exit 0

-dオプションでコンテナをバックグラウンドで起動出来ます。

core@localhost ~ $ docker run -i -t -d base bash
82e8a706e7ff

バックグラウンドで起動しているコンテナに対しては、docker attachでAttachできます。

core@localhost ~ $ docker ps
ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS
82e8a706e7ff        base:latest         bash                4 seconds ago       Up 4 seconds
core@localhost ~ $ docker attach 82e8a706e7ff

root@82e8a706e7ff:/#

コンテナ上で作業し、そのコンテナの状態を保存したい場合は、docker commitでコンテナのイメージを保存します。

index.docker.io に登録すれば、docker loginしてdocker pushすることでimageの公開も行うことが可能です。

docker commitでは、コンテナIDの後にREPOSITORYを指定できます。
公開するならば、ユーザー名/イメージ名の書式にするのがよいと思います。

core@localhost ~ $ docker ps -a
ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS
12c2c79f0f87        base:latest         bash                2 minutes ago       Up 2 minutes
core@localhost ~ $ docker commit 12c2c79f0f87 user/image
895a13e29f4a
core@localhost ~ $ docker images
REPOSITORY          TAG                 ID                  CREATED             SIZE
user/image          latest              895a13e29f4a        6 seconds ago       16.39 kB (virtual 180.1 MB)
base                latest              b750fe79269d        6 months ago        24.65 kB (virtual 180.1 MB)
base                ubuntu-12.10        b750fe79269d        6 months ago        24.65 kB (virtual 180.1 MB)
base                ubuntu-quantal      b750fe79269d        6 months ago        24.65 kB (virtual 180.1 MB)
base                ubuntu-quantl       b750fe79269d        6 months ago        24.65 kB (virtual 180.1 MB)

imageが不要になればdocker rmiで削除します。

core@localhost ~ $ docker rmi 895a13e29f4a
Untagged: 895a13e29f4a
Deleted: 895a13e29f4a

Dockerfiles

imageを構築し、commitする手順をDockerfilesというファイルに記述することもできます。
公式ドキュメント

フォーマット

Dockerfileのフォーマットは単純です。
命令では、大文字と小文字は区別されず、dockerはDockerfileの命令を順番に評価します。

最初の命令はFROMでなければなりません。
#から始まる行はコメントです。

FROM

FROMは起点となるイメージを指定します。
FROMはDockerfileの中で、最初の非コメントの命令でなければいけません。

FROM <image>
FROM <TAG>:<image>

FROMは、複数のイメージを作成するために、単一Dockerfileの内で複数回記述することもできます。

MAINTAINER
MAINTAINER <NAME>

MAINTAINERは著者情報の設定を行います。

RUN
RUN <command>

RUNは、現在のイメージで任意のコマンドを実行し、結果をコミットします。
コミットされたイメージは、Dockerfileの次のステップで使用されます。

CMD

RUN命令は実際にコマンドを実行し、結果をコミットしました。
しかしCMD命令はビルド時には何も実行しません。
CMD命令はコンテナ起動時にデフォルトでの実行コマンドを指定するものです。

CMD命令には次の3つの形式があります。

CMD ["executable", "param1", "param2"] (like an exec, preferred form)
CMD ["param1", "param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (as a shell)
EXPOSE

EXPOSE命令は、イメージを実行しているときに公開するポートを設定します

EXPOSE <port> [<port>...]
ENV
ENV <key> <value>

ENV命令は環境変数設定の値にセットします。

ADD

ADD命令はSRCから新しいファイルをコピーし、DESTパスでコンテナのファイルシステムに追加します。

ADD <src> <dest>
  • srcがURLで、destがスラッシュで終わらない場合、ファイルはURLからダウンロードされ、destにコピーされます
  • srcがURLで、destがスラッシュで終わる場合、ファイル名はURLから推論されます
  • srcがディレクトリである場合、ディレクトリーがファイルシステム・メタデータを含めてコピーされます
  • srcがgzip, bzip2,xzなどのtarアーカイブである場合、それはディレクトリとして展開されます
  • destが存在しない場合、ディレクトリと共に作成されます
  • 新しいファイルおよびディレクトリは権限 0755, uidおよびgidが0で作成されます
USER

USER命令は、イメージを実行するときに使用するユーザー名またはUIDを設定します。

USER daemon
WORKDIR

WORKDIR命令は、CMDコマンドの作業ディレクトリを指定します。

WORKDIR /path/to/workdir

dockerイメージのビルド

Dockerfileのあるディレクトリでdocker buildすることで、Dockerfileに基づいてイメージを作成することができます。

docker build .

-tオプションで名前をつけておいた方が後からわかりやすいです。

docker build -t username/imagename .
Dockerfileでredis-serverイメージを作成する

Dockerfileでイメージを作成してみます。
以下の内容を./redis/Dockerfileに保存し、

Dockerfile (redis-server)
FROM base

RUN apt-get update
RUN apt-get -y install redis-server

RUN echo "1" >> /proc/sys/vm/overcommit_memory

EXPOSE 6379
CMD ["/usr/bin/redis-server"]

docker build -t redis redis/でビルドします。

core@localhost ~ $ docker build -t redis redis/
Uploading context 10240 bytes
Step 1 : FROM base
 ---> b750fe79269d
Step 2 : RUN apt-get update
 ---> Running in a53ede3a27e0
Ign http://archive.ubuntu.com quantal InRelease
Hit http://archive.ubuntu.com quantal Release.gpg
Hit http://archive.ubuntu.com quantal Release
Hit http://archive.ubuntu.com quantal/main amd64 Packages
Get:1 http://archive.ubuntu.com quantal/universe amd64 Packages [5274 kB]
Get:2 http://archive.ubuntu.com quantal/multiverse amd64 Packages [131 kB]
Get:3 http://archive.ubuntu.com quantal/main Translation-en [660 kB]
Get:4 http://archive.ubuntu.com quantal/multiverse Translation-en [100 kB]
Get:5 http://archive.ubuntu.com quantal/universe Translation-en [3648 kB]
Fetched 9813 kB in 29s (329 kB/s)
Reading package lists...
 ---> dcedb6a66ab8
Step 3 : RUN apt-get -y install redis-server
 ---> Running in 0813f1e8d204
Reading package lists...
Building dependency tree...
The following extra packages will be installed:
  libjemalloc1
The following NEW packages will be installed:
  libjemalloc1 redis-server
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 319 kB of archives.
After this operation, 821 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu/ quantal/universe libjemalloc1 amd64 3.0.0-3 [85.9 kB]
Get:2 http://archive.ubuntu.com/ubuntu/ quantal/universe redis-server amd64 2:2.4.15-1 [233 kB]
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7, <> line 2.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin:
Fetched 319 kB in 3s (101 kB/s)
Selecting previously unselected package libjemalloc1.
(Reading database ... 9893 files and directories currently installed.)
Unpacking libjemalloc1 (from .../libjemalloc1_3.0.0-3_amd64.deb) ...
Selecting previously unselected package redis-server.
Unpacking redis-server (from .../redis-server_2%3a2.4.15-1_amd64.deb) ...
Processing triggers for ureadahead ...
Setting up libjemalloc1 (3.0.0-3) ...
Setting up redis-server (2:2.4.15-1) ...
Starting redis-server: redis-server.
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
Processing triggers for ureadahead ...
 ---> faf3c2058696
Step 4 : RUN echo "1" >> /proc/sys/vm/overcommit_memory
 ---> Running in 8a156b0deb85
 ---> 534829495ad6
Step 5 : EXPOSE 6379
 ---> Running in fe6d78cacb63
 ---> cb23d38bd114
Step 6 : CMD ["/usr/bin/redis-server"]
 ---> Running in cad2967f489a
 ---> e31730c0e9f0
Successfully built e31730c0e9f0

redisという名前でイメージを作成できたので、-dオプションでバックグラウンド指定し、-pオプションでport forwardを指定します。
CMD命令でredis-serverが指定してあるので、コマンドは省略できます。

core@localhost ~ $ docker run -d -p 6379 redis
a558ea555e65

docker inspectで詳細情報を確認することができます。


core@localhost ~ $ docker ps
ID                  IMAGE               COMMAND                CREATED             STATUS              PORTS
a558ea555e65        redis:latest        /usr/bin/redis-serve   3 seconds ago       Up 3 seconds        49157->6379
core@localhost ~ $ docker inspect a558ea555e65
[{
    "ID": "a558ea555e65a1fe3c4562aad4344035b7249606e065e3ed25d3b46ec561292f",
    "Created": "2013-10-11T04:21:48.191626933Z",
    "Path": "/usr/bin/redis-server",
    "Args": [],
    "Config": {
        "Hostname": "a558ea555e65",
        "Domainname": "",
        "User": "",
        "Memory": 0,
        "MemorySwap": 0,
        "CpuShares": 0,
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "PortSpecs": [
            "6379"
        ],
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": [
            "HOME=/",
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "Cmd": [
            "/usr/bin/redis-server"
        ],
        "Dns": null,
        "Image": "redis",
        "Volumes": {},
        "VolumesFrom": "",
        "WorkingDir": "",
        "Entrypoint": [],
        "NetworkDisabled": false,
        "Privileged": false
    },
    "State": {
        "Running": true,
        "Pid": 5104,
        "ExitCode": 0,
        "StartedAt": "2013-10-11T04:21:48.196375494Z",
        "Ghost": false
    },
    "Image": "e31730c0e9f0c23a8f3ecf282a3488d1eee717a0d5f0e7ca6ff1249795ffda20",
    "NetworkSettings": {
        "IPAddress": "172.17.0.9",
        "IPPrefixLen": 16,
        "Gateway": "172.17.42.1",
        "Bridge": "docker0",
        "PortMapping": {
            "Tcp": {
                "6379": "49157"
            },
            "Udp": {}
        }
    },
    "SysInitPath": "/usr/bin/docker",
    "ResolvConfPath": "/etc/resolv.conf",
    "HostnamePath": "/var/lib/docker/containers/a558ea555e65a1fe3c4562aad4344035b7249606e065e3ed25d3b46ec561292f/hostname",
    "HostsPath": "/var/lib/docker/containers/a558ea555e65a1fe3c4562aad4344035b7249606e065e3ed25d3b46ec561292f/hosts",
    "Volumes": {},
    "VolumesRW": {}
}]core@localhost ~ $

他のコンテナを立ち上げてredis-serverに接続してみます。
redis-clientを操作したいので、docker run実行時のコマンドを上書きします。

core@localhost ~ $ docker run -i -t redis bash
root@5383436248fa:/# redis-cli -h 172.17.0.9 -p 6379
redis 172.17.0.9:6379>

vagrantでprivate networkの設定を行っていれば、

config.vm.network :private_network, ip: "192.168.33.10"

ホストOSからでも接続できます。

redis-cli -h 192.168.33.10 -p 49157

OSX -> CoreOS (vagrant) -> コンテナ という構成なので、直接SSH接続できるようなイメージを作成するとしたら、sshサーバーを作るDockerfileを作成してdocer buildすればOKです。
passwordは適宜変更してください。

Dockerfile (ssh-server)
FROM base

RUN apt-get update

RUN apt-get install -y openssh-server

RUN mkdir /var/run/sshd
RUN echo 'root:password' |chpasswd

EXPOSE 22
CMD /usr/sbin/sshd -D

イメージをビルドして、

core@localhost ~ $ docker build -t base_ssh Dockerfiles/ssh/

ポートを確認して、

core@localhost ~ $ docker ps
ID                  IMAGE               COMMAND                CREATED             STATUS              PORTS
234c6e33237d        base_ssh:latest     /bin/sh -c /usr/sbin   19 minutes ago      Up 19 minutes       49153->22

接続します

ssh [email protected] -p 49153

雑感

dockerでのコンテナ操作は、vagrant upするよりも遙かに軽いです。
仮想マシンを立ち上げて・操作して・破棄してを気兼ねなくできるようになりました。
サーバー状態の変更をgitのようにcommitで操作できるのも便利です。
Dockerfileを配布することによってセットアップ手順も公開できることも可能性が広がりますね。