5分で分かるDockerのキホン
全国100万人のImmutable Infrastructure職人のみなさんこんにちは。 もう誰も彼もがDockerなので、あんまりブログに書こうという気にもならなかったのですが、知り合いからリクエストを貰ったので、5分くらいで分かるようにかいつまんで概略を説明します。
Dockerとは
- 詳しくは本家サイト見ればだいたい分かる。
- 仮想化技術
- コンテナ単位でパッケージング
- VirtualBoxとかと違って高速、オーバーヘッドが少ない。chrootに近い。LXCには依存しなくなっている
- コンテナごとにIDが振られる
- コンテナは差分保存なのでロールバックも簡単
- 一回作ればどこでも動く。Javaっぽい
- Dockerfileでコンテナを作成する
- Dockerfileの1行ごとにコンテナIDがフラれる
- 動作環境
- Linux Kernel 3.8以降 64bit OS
- Macの場合はVirtualBoxの中で動かす形になる→ boot2docker
- Windowsの場合もVirtualBoxを使って仮想マシンの中にDocker環境を作ることになる。
- 何がうれしいの?
- 高速に起動する。したがってCI用に使ったり、Chefのクックブックの実験環境に使ったり、開発環境に使ったり色々便利。もう本番環境で使っている例も多数
- コンテナ内に閉じ込めることでポータビリティがあがる。アプリケーションのデプロイ戦略が楽な方に大きく変わりうる
- 差分で管理されるので配布と再利用が簡単
- いろんな環境で動く
- Dockerfileを使ってコードでインフラを管理できる
Ubuntu 12.04 LTS 64bitで動かす
まずKernelを3.8に変更する
sudo apt-get update
sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring
sudo reboot
aptレポジトリを追加してインストール
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
sudo sh -c "echo deb https://get.docker.io/ubuntu docker main /etc/apt/sources.list.d/docker.list"
sudo apt-get update
sudo apt-get install lxc-docker
とりあえずDockerを使ってUbuntuのコンテナを起動する
sudo docker run -i -t ubuntu /bin/bash
初回なのでたくさんイメージをダウンロードするのでちょっと時間がかかるはず。終わると以下のようにログインできている
Unable to find image 'ubuntu' locally
Pulling repository ubuntu
316b678ddf48: Download complete
a7cf8ae4e998: Download complete
3db9c44f4520: Download complete
(略)
cb12405ee8fa: Download complete
4d26dd3ebc1c: Download complete
d4010efcfd86: Download complete
root@6485cdbce682:/#
この状態だと、インタラクティブシェルで、exitするとプロセスが終了する。
どのコンテナが起動しているかを確認する
sudo docker ps
として確認すればOK。(ps -a だと停止済のコンテナも含む)
コンテナ自体を削除する場合
以下のようにする(末尾のパラメータはコンテナID)
sudo docker rm 04b26990125f
複数のコンテナをまとめて停止したり削除する
以下のように引数にコマンド実行の結果を渡せばOK。
sudo docker stop `sudo docker ps -aq`
sudo docker rm `sudo docker ps -aq`
独自のイメージを作る
適当に変更を加えたあとにログアウトし、
sudo docker commit コンテナID 適当な名前
のようにする。作ったものを確認するには
sudo docker images 名前
として一覧に出ることを確認すればOK
たとえば
sudo docker commit eb0dd1195df2 ryuzee/apache2
これができれば
sudo docker run -i -t ryuzee/apache2 /bin/bash
にように今度はこれを使うことができる。なお、イメージの名称は、ユーザー名/中身 という形式にするのが推奨
イメージの一覧を取得する
sudo docker images
とすることでイメージの一覧が取得できる。
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 13.10 5e019ab7bf6d 4 weeks ago 180 MB
ubuntu saucy 5e019ab7bf6d 4 weeks ago 180 MB
ubuntu 12.04 74fe38d11401 4 weeks ago 209.6 MB
(略)
ubuntu 10.04 3db9c44f4520 4 weeks ago 183 MB
ubuntu lucid 3db9c44f4520 4 weeks ago 183 MB
Dockerfileでイメージを作る
FROM ubuntu
RUN sudo apt-get update -y
RUN sudo apt-get install apache2 -y
RUN sudo apt-get install memcached -y
RUN sudo apt-get install php5 -y
## 環境変数の設定
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
## 公開するポートの指定
EXPOSE 80
## コンテナ起動時に実行するコマンドを指定
CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]
のように、ベースとするイメージを指定したあと、実行するコマンドを書いていく。これができたら
sudo docker build .
を実行するとビルドされる。ただしこれで作られたイメージには名前がついていないので、
sudo docker build -t 名前 .
のようにすると良い。もしくはあとから名前をつける場合は、
sudo docker tag bc9e46f7accc ryuzee/apache2
のようにする
Dockerfile内で使えるコマンド
FROM <image> 元となるイメージを指定する。:の後ろでタグ指定可能
MAINTAINER <name> メンテナの名前
RUN <command> ビルド中に実行したいコマンドを指定。パッケージのインストールとか設定とか
CMD <command> 起動後のコンテナで実行したいコマンドを指定する。1つしか書けない
EXPOSE <port> [</port><port> ...] 外部に公開するポートを指定
ENV <key> <value> 環境変数の設定
ADD <src> <dest> ファイルを配置。絶対パスで記述する
Dockerfile作成上の注意
- ENTRYPOINTやCMDは1つのDockerfileの中で1個しか指定できない
- したがって複数プロセスを起動したい時はsupervisordを使って行う
イメージの削除
以下のように引数にイメージIDを指定する。ただし依存するコンテナが存在する場合は削除できない
sudo docker rmi f6eb3276aab2
ポートの設定
Dockerfileの中でEXPOSEを使って指定するか、起動時に設定する。以下の例では、コンテナ側の80番にポートフォワードするために母艦側で8888を指定している
sudo docker run -d -p 8888:80 ryuzee/apache2
起動サービスの設定
Dockerfileの中でCMDを使って指定するか、起動時に設定する
docker run -d -p 8080:80 ryuzee/apache2 /usr/sbin/apache2 -DFOREGROUND
ローカル側のディスクを共有
あらかじめDockerfileの中で公開するVOLUMEの設定をしておいた上で、起動時に -v を使ってローカル側:コンテナ側の形で指定する。なお、絶対パスで指定する必要がある点には注意。
ログ系とかは外だしにしとくと便利かも。
sudo docker run -p 9999:80 -p 2222:22 -t -v /home/ryuzee/docker/basic/logs:/var/log/apache2 -d ryuzee/basic
イメージの共有
Docker Registryを使って作成したイメージを共有することができる。例えば、パブリックレジストリを使うと世の中に公開したり、他の人が公開しているものを使ったりできる
公式レポジトリとコマンドラインをひもづけるには
sudo docker login
としてログインすればOK
作ったイメージを公開するには、
sudo docker push ryuzee/basic
としてプッシュしてあげれば良い。
以下のようなログが表示される。
The push refers to a repository [ryuzee/basic] (len: 1)
Sending image list
Pushing repository ryuzee/basic (1 tags)
511136ea3c5a: Image already pushed, skipping
Image f10ebce2c0e1 already pushed, skipping
Image 82cdea7ab5b5 already pushed, skipping
Image 5dbd9cb5a02f already pushed, skipping
Image 74fe38d11401 already pushed, skipping
869d76ced5c7: Image successfully pushed
(略)
424924b964f9: Image successfully pushed
4f0307fd0f8f: Image successfully pushed
d77d7fd91796: Image successfully pushed
532d67a9eec2: Image successfully pushed
5804bf0385b9: Image successfully pushed
Pushing tag for rev [5804bf0385b9] on {https://registry-1.docker.io/v1/repositories/ryuzee/basic/tags/latest}
自分用のDocker registryをたてる
index.docker.io だけでなく、自分でDocker Registryを作ることができる。またこのとき、Amazon S3にファイルが保存できるので、AWS内に仮想マシンをたててDocker使う場合はネットワーク的なメリットもある。
手順
まずS3に適当にバケットを作成しておく。今回は東京リージョンにryuzee-dockerimageという名前で作成。 なお、docker pullして持ってくるregistryは古いので、できればGitHubから最新を持ってきたほうが困らない感じ。
git clone https://github.com/dotcloud/docker-registry
cd docker-registry
sudo docker build -t ryuzee/registry .
コンテナを起動する。-eで環境変数を指定しており、アプリの中で必要なAWSのアクセスキーやシークレットキーを指定している。もちろんコンテナの中にconfig.ymlを置いたり、起動時にVOLUMEを使って設定ファイルを外部から共有してもOK。
sudo docker run \
-e SETTINGS_FLAVOR=s3 \
-e AWS_BUCKET=ryuzee-dockerimage \
-e STORAGE_PATH=/images \
-e AWS_KEY=AKIXXXXXXXXXXXXXXXXXX \
-e AWS_SECRET=abcnjsifhAHFkfkjidjdjdjdiki \
-e SEARCH_BACKEND=sqlalchemy \
-p 5000:5000 \
ryuzee/registry
ここまでできたら、まず以下のようにタグをつけて
sudo docker tag bb34bb42eb3a localhost:5000/ryuzee/basic
その後にレポジトリにプッシュする
sudo docker push locahost:5000/ryuzee/basic
Pullしたいときの考えかたも基本的に一緒
sudo docker pull localhost:5000/ryuzee/basic
dockerコマンドでsudo毎回叩くとかありえない人向け
dockerグループに自分を追加してあげることでsudo付けなくてもOKになる。なお作業完了後、シェルの再起動が必要なので、ログアウト/ログインする
sudo groupadd docker
sudo gpasswd -a ryuzee docker
sudo service docker restart
Ubuntu上のVagrantから簡単に操作する
Vagrant 1.6系からDockerに正式対応したので、Ubuntu上だとかなり楽に使える。 Vagrantfileは以下のようになる。
Vagrant.configure("2") do |config|
config.vm.provider "docker" do |d|
d.image = "ryuzee/basic"
end
end
これを用意して、いつもどおり
vagrant up --provider=docker
とすればOK
vagrant ssh
でログインしてごにょごにょしたい場合は以下のようにhas_ssh
を有効にしつつ、sshでの接続ユーザー名やキーペア(またはパスワード)とポート番号を指定する(ポート番号を指定しない場合、なぜかBad Port
というエラーになるので注意)
Vagrant.configure("2") do |config|
config.vm.provider "docker" do |d|
d.image = "ryuzee/basic"
d.remains_running = false
d.has_ssh = true
end
config.ssh.username = "root"
config.ssh.password = "root"
config.ssh.port = "22"
end
さらにコンテナ起動時のCMDを指定したり、ポートマッピングを設定することも可能。
## このあたりが追加になる
d.cmd = ["/usr/sbin/httpd", "-DFOREGROUND"]↲
d.ports = ["8888:80"]
過去の資産の再利用
Chefとの組み合わせ方
packerを使ってイメージの作成を行えば、過去の資産の再利用が可能。Packerは0.6以上のバージョンにすること。 以下の例では、BerkshelfおよびChef-Soloプロビジョナーとの組み合わせで、Dockerのイメージを作成している。
{
"builders": [{
"type": "docker",
"image": "centos",
"export_path": "image.tar"
}],
"provisioners":[
{
"type": "chef-solo",
"cookbook_paths": ["./vendor-cookbooks/"],
"run_list": ["timezone", "apache2-simple", "memcached"],
"json": {"memcached":{"maxcon":"512","cachesize":"512"}},
"prevent_sudo": true,
"skip_install": false
}],
"post-processors": [{
"type": "docker-import",
"repository": "ryuzee/packer-sample",
"tag": "0.1"
}]
}
ソースはこちら。 一点気をつける点としては、DockerfileでサポートされているEXPOSEやENDPOINTやCMDなどを現時点ではサポートしていないため、自分でdocker run
の際に引数で渡す必要がある。
あとは頼んだ…