ちょっと話題の記事

はじめてのDocker on EC2

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

JAWS DAYS2014Immutable Infrastructureトラックが提供されたり、昨日Immutable Infrastructure Conference #1が開催されたり、ここ最近のテクノロジートレンドはImmutable Infrastructureに染まっている感じがあります。

僕自身も色々なBlogを読んだり自分で手を動かしてみたりと色々試行錯誤を繰り返しているのですが、僕がEC2上でDockerについてやってみたことを整理してみました。

Docker自体ここ数年でたくさんの人が試しているし、アウトプットも多いので、今更感は否めないのですが、これから試す人にとって少しでも参考になれば幸いです。

EC2上でのDockerのセットアップ

今回はCentOSをEC2にLaunchしました。使用したAMIは「CentOS 6 (x86_64) - with Updates(ami-31e86030)」です。

まずはyum updateで最新化します。またDockerのインストールで使うwgetをインストールしておきます。

# yum -y update
# yum -y install wget

SELinuxを無効化しておきます。これはコンテナ上でユーザにパスワードを設定する場合など、SELinuxで制限がかかってしまうものがある為です。

# echo "SELINUX=disabled" > /etc/selinux/config

EPELリポジトリを追加し、docker-ioパッケージをインストールします。

# wget http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
# rpm -ivh epel-release-6-8.noarch.rpm
# yum -y --enablerepo=epel install docker-io

インストールしたDockerをサービス起動します。

# chkconfig docker on
# service docker start

Dockerコマンドを色々試してみる

まずは実行してみる

docker runコマンドで、CentOSのコンテナイメージでコンテナを起動し、echoコマンド実行してみます。初回はコンテナイメージのダウンロードが入りますので少し時間がかかります。

# docker run -t centos /bin/echo "hello docker"
hello docker

echoコマンドが実行されました。そしてこのコンテナはコマンドを実行するとそのまま停止されてしまいます。

インタラクティブに実行してみる

インタラクティブに実行するには-iオプションを付けてコンテナを起動します。

# docker run -i -t centos /bin/bash
bash-4.1# echo "hello docker"
hello docker
bash-4.1# exit
exit

こちらもexitすることでコンテナが停止します。

コンテナを一覧表示する

docker psコマンドでコンテナが一覧表示されます。

# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

何も表示されません。これは先ほど実行したdockerコンテナが既に停止状態にある為です。停止状態にあるコンテナも含め全て表示するには-aオプションを付けます。

# docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
2561af2b236c        centos:6.4          /bin/bash              29 seconds ago      Exit 0                                  dreamy_einstein     
a41a2a8174f2        centos:6.4          /bin/echo hello dock   36 seconds ago      Exit 0                                  agitated_turing

最初に実行した2つのコンテナが表示されました。

コンテナを削除する

不要になったコンテナを削除するのはdocker rmコマンドを実行します。

# docker rm 2561af2b236c
2561af2b236c

# docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
a41a2a8174f2        centos:6.4          /bin/echo hello dock   2 minutes ago       Exit 0                                  agitated_turing

2561af2b236cというコンテナIDを持ったコンテナが削除されています。

停止しているコンテナの全削除

試行錯誤してコンテナをポコポコ立てているとゴミがどんどん溜まっていきます。一つ一つIDを指定して削除するのはだいぶ面倒だと思ったのですが、@znzさんが素晴らしいTipsを書かれていました

まずはコンテナを足して、2つにしてみます。

# docker run -t centos /bin/echo "hello docker 2"
hello docker 2

# docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
b68343c6822a        centos:6.4          /bin/echo hello dock   37 seconds ago      Exit 0                                  elegant_hawking 
a41a2a8174f2        centos:6.4          /bin/echo hello dock   2 minutes ago       Exit 0                                  agitated_turing

以下のように、コンテナIDをコマンド結果から入力します。

# docker rm `sudo docker ps -a -q`
b68343c6822a
a41a2a8174f2

# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

コマンド一回でコンテナが全部消えていますね!素晴らしい!

コンテナからイメージを作成する

上記の作業はCentOSのオフィシャルコンテナイメージを使っていたのですが、自分で作ったコンテナをイメージ化して使い回すことが出来ます。

例えばCentOSのオフィシャルコンテナイメージをベースに、yum updateで現時点で最新のパッケージが適用されたイメージを作ってみます。インタラクティブにコンテナを起動し、yum updateして停止してみます。

# docker run -i -t centos /bin/bash
bash-4.1# yum update -y
--snip--
Complete!
bash-4.1# exit

# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
35369a096a54        centos:6.4          /bin/bash           5 minutes ago       Exit 127                                dreamy_brattain

このコンテナをベースに、updateというタグ名を付与したイメージを作成します。

# docker commit 35369a096a54 centos:update
062217fc2fa069117695a2093145c1a2f1bc59d85877a6fe768af1e350fb2347

docker imagesコマンドでローカルに保存されているコンテナイメージの一覧を表示します。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              update              062217fc2fa0        50 seconds ago      602.8 MB
centos              6.4                 539c0211cd76        11 months ago       300.6 MB
centos              latest              539c0211cd76        11 months ago       300.6 MB

TAGがupdateになっているコンテナイメージが出来ていますね!

イメージのタグからコンテナ起動

では作成したupdateイメージからコンテナを起動してみます。最新のパッケージが適用されているので、yum updateしても何も適用されません。

$ sudo docker run -i -t centos:update /bin/bash
bash-4.1# yum update -y
No Packages marked for Update

イメージを削除する

作成したコンテナイメージを削除するのはdocker rmiコマンドを実行します。なおそのイメージを使用したコンテナが存在する場合は削除できませんので、先にコンテナを削除した後にイメージを削除します。次の例ではコンテナ:86ad0ef5a87fを削除した後、コンテナイメージ:062217fc2fa0を削除しています。

$ sudo docker rm 86ad0ef5a87f
86ad0ef5a87f

$ sudo docker rmi 062217fc2fa0
Deleted: 062217fc2fa069117695a2093145c1a2f1bc59d85877a6fe768af1e350fb2347

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              6.4                 539c0211cd76        11 months ago       300.6 MB
centos              latest              539c0211cd76        11 months ago       300.6 MB

コンテナイメージ:062217fc2fa0が削除されていますね!

DockerにホストOSからSSHで接続してみる

それでは実用的な使い方として、コンテナをバックグラウンドで実行し、ホストからコンテナにSSH接続をしてみます。

Dockerfileを使ってイメージを作成する

先ほどは手作業したコンテナからイメージを作成しましたが、今度はDockerfileを使ってイメージを作成してみます。

Dockerfileを配置するディレクトリを作成し、Dockerfileを作成します。なお、今回はSSHで接続するために、Dockerfileと同一ディレクトリ内にauthorized_keysファイルを配置し、イメージ作成時に組み込んでいます。

$ mkdir ~/docker
$ cp ~/authorized_keys ~/docker
※authorized_keysは事前に用意しておいて下さい。

$ cd ~/docker
$ vi Dockerfile
FROM centos

# Install SSH
RUN yum update -y
RUN yum install -y sudo
RUN yum install -y passwd
RUN yum install -y openssh-server
RUN yum install -y openssh-clients

RUN /usr/bin/ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -C '' -N ''
RUN /usr/bin/ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -C '' -N ''
RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config
RUN sed -ri 's/#UsePAM no/UsePAM no/g' /etc/ssh/sshd_config

# Create User
RUN useradd worker
RUN passwd -f -u worker
RUN mkdir -p /home/worker/.ssh
RUN chmod 700 /home/worker/.ssh
ADD ./authorized_keys /home/worker/.ssh/authorized_keys
RUN chmod 600 /home/worker/.ssh/authorized_keys
RUN chown -R worker /home/worker/

# Add sudoers
RUN echo "worker  ALL=(ALL)  ALL" >> /etc/sudoers.d/worker

EXPOSE 22

このDockerfileからイメージを作成します。イメージ作成はdocker buildコマンドを使います。ここではsshdというタグを付与しました。

# docker build -t centos:sshd .
--snip--
Successfully built 40625ead6983

コンテナイメージが作成されたことを確認します。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
centos              sshd                40625ead6983        9 seconds ago       643.3 MB
centos              6.4                 539c0211cd76        11 months ago        300.6 MB
centos              latest              539c0211cd76        11 months ago        300.6 MB

では作成したコンテナイメージから、sshdを起動した状態でコンテナを立ち上げてみましょう!-dオプションを付けてバックグラウンド起動しています。また-pオプションをつけてポートフォワーディングするようにしています。

# docker run -d -p 22 centos:sshd /usr/sbin/sshd -D
2ae8a06038de1efc3e3325be9c3be49368ff422b8a6e3abb6dea5d25524fcc26

起動したコンテナを確認します。

# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                   NAMES
2ae8a06038de        centos:sshd         /usr/sbin/sshd -D   10 seconds ago      Up 10 seconds       0.0.0.0:49158->22/tcp   jolly_pare

sshdのコンテナイメージを使ったコンテナがバックグラウンド起動していることが分かります。また「0.0.0.0:49158->22/tcp」という表示から、49158番ポートが22番ポートにフォワーディングされていることも分かりますね。

それでは接続...するのですが、まずDockerコンテナのIPアドレスを確認します。

# ifconfig 
docker0   Link encap:Ethernet  HWaddr FE:9A:75:95:42:A1  
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::d811:45ff:fee8:5b27/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:20857 errors:0 dropped:0 overruns:0 frame:0
          TX packets:43674 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1155152 (1.1 MiB)  TX bytes:65358408 (62.3 MiB)

では接続!

# ssh -i ~/.ssh/mykey.pem -l worker 172.17.42.1 -p 49158
The authenticity of host '[172.17.42.1]:49158 ([172.17.42.1]:49158)' can't be established.
RSA key fingerprint is e7:f1:8e:96:59:7c:a5:fe:7b:64:b8:7c:d1:ee:86:6b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[172.17.42.1]:49158' (RSA) to the list of known hosts.
Last login: Wed Mar 26 02:07:00 2014 from ip-172-17-42-1.ap-northeast-1.compute.internal       
$

ちゃんとSSHログインできました!sudoも使えてます!

$ sudo ls /
bin  boot  dev	etc  home  lib	lib64  media  mnt  opt	proc  root  sbin  selinux  srv	sys  tmp  usr  var

わーい出来たー!

まとめ

何が「わーい出来たー!」だ。すんなり出来ているように見えますが、僕の知識不足もあり、非常に難航しました。SSHで接続するためのDockerfileなんかは試行錯誤して試行錯誤してやっと出来たものです。2日くらいかかってしまいました。だいぶ情報が出そろっているとはいえ、環境によって細かいチューニングやコツがいるなぁと思いました。

とにかく「とりあえず使う」ことは出来るようになったので、次は活用を考えたいと思います!