Docker 便利そうな事にようやく気付いたので、CoreOS で始めるメモ。Mac OS X で作業してます。diskutil
や pbcopy
なんかは環境に合わせて読み変えて下さい。
物理サーバーへ CoreOS をインストール
インストールディスクの作成
- CoreOS の web サイトより ISO ファイルをダウンロード
- USB メモリへ ISO ファイルのディスクイメージをコピー:
diskutil unmountDisk /dev/diskN # USB メモリをアンマウント
sudo dd if=./coreos_production_iso_image.iso of=/dev/diskN bs=1m # dd で ISO を USB メモリにコピー
インストール
cloud-config の作成
インストーラーの設定をカスタマイズする cloud-config.yml
を作成する。CentOS における ks.cfg
みたいなものか。
SSH 鍵 coreos_key
ペアを作成:
ssh-keygen -t rsa -C anony@foo.bar -f ./coreos_key
公開鍵 coreos_key.pub
の文字列をコピーして cloud-config.yml
に使用:
cat ./coreos_key.pub | pbcopy
cloud-config.yml
を作成:
touch ./cloud-config.yml
#cloud-config
coreos:
units:
- name: etcd.service
command: start
- name: fleet.service
command: start
- name: docker.service
command: start
# タイムゾーンを JST に設定
- name: timezone.service
command: start
content: |
[Unit]
Description=timezone
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/ln -sf ../usr/share/zoneinfo/Japan /etc/localtime
# 固定 IP の設定追加
- name: 10-static.network
runtime: false
content: |
[Match]
Name=eno1
[Network]
Address=192.168.0.98/24
Gateway=192.168.0.1
DNS=192.168.0.1
# NFS 自動マウントの設定追加
- name: media-myvolume.mount
command: start
content: |
[Mount]
What=192.168.0.88:/var
Where=/media/myvolume
Type=nfs
Options=nolock
update:
- reboot-strategy: best-effort
ssh_authorized_keys:
# 管理ユーザー core の公開鍵。coreos_key.pub の文字列を使用
- ssh-rsa AAAAB3NzaC[...] anony@foo.bar
hostname: coreos # ホスト名を適当に指定
manage_etc_hosts: localhost # ローカルの名前解決用
USB メモリから起動
CoreOS の USB メモリから PC を起動する。自動で core
ユーザーとしてログインする:
localhost login: core (automatic login)
CoreOS (stable)
Update Strategy: No Reboots
core@localhost ~ $
サーバーの IP アドレスを確認する:
ip add show
eno1: flags=4163<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet 192.168.0.98 netmask 255.255.255.0 broadcast 192.168.1.255
一時的に core
ユーザーにパスワードを設定する:
sudo passwd core
設定したパスワードを使用して、作成した cloud-config.yml
を作業 PC からサーバーに転送する:
scp ./cloud-config.yml core@192.168.0.98:~
実際にインストール
下記コマンドをサーバーで実行してインストールする:
sudo coreos-install -d /dev/sda -C stable -c ~/cloud-config.yml
-
/dev/sda
は環境に合わせて読み変える。
インストールが完了したら再起動する:
sudo reboot
接続確認
作業 PC から SSH 鍵 coreos_key
を用いて CoreOS サーバーへ SSH 接続できるか確認する:
ssh -i ./coreos_key core@192.168.0.98
ちなみに cloud-config.yml
の設定は /var/lib/coreos-install/user_data
を更新する事で変更が可能。設定の更新が必要な場合はこちらから。
接続できたら完了。以降は SSH 経由のこのサーバー上で Docker を実行する。
Vagrant で CoreOS を実行
ちょっと寄り道で、物理サーバーではなく Vagrant で CoreOS を起動する方法も書いておく。
CoreOS が公式に Vagrantfile
を公開しているので、これを利用する。
CoreOS の GitHub リポジトリから Vagrantfile
一式をクローンする:
git clone https://github.com/coreos/coreos-vagrant.git
cd ./coreos-vagrant
あとは普通に Vagrant の手順です:
vagrant up
vagrant ssh
Docker で "Hello, world."
ここから Docker の話。CoreOS に SSH ログインした状態で作業する。
まずは簡単に Docker の動作確認で、既存のコンテナから echo
コマンドを叩いて "Hello, world." と表示してみる。
イメージの取得
まず Docker Hub という公式のイメージ共有クラウドサービスから CentOS のイメージを取得する。尚、予め Docker Hub でユーザー登録をしてアカウントを取得しておく。
Docker Hub へログインする:
docker login
CentOS のイメージを検索する:
docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos The official build of CentOS. 764 [OK]
ansible/centos7-ansible Ansible on Centos7 27 [OK]
tutum/centos Centos image with SSH access. For the root... 12 [OK]
blalor/centos Bare-bones base CentOS 6.5 image 8 [OK]
[...]
検索結果の一番上 centos
が公式なイメージなので、こちらの最新版 (centos:latest
) を取得する:
docker pull centos:latest
コンテナの生成
Docker Hub 等から取得してきたホスト上のイメージ一覧は下記のコマンドで確認できる:
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos 7 8efe422e6104 2 weeks ago 224 MB
centos centos7 8efe422e6104 2 weeks ago 224 MB
centos latest 8efe422e6104 2 weeks ago 224 MB
-
centos
のイメージが 3 つ表示されているが、これはIMAGE ID
が示す通り同一のイメージ。タグの違いから 3 つ表示されている。
上記 centos:latest
イメージ上で echo
コマンドを実行してみる:
docker run centos:latest echo 'Hello, world.'
Hello, world.
上記の通り Hello, world.
と標準出力が返されるはず。
これは centos:latest
イメージを元に、echo 'Hello, world.'
を実行するコンテナを生成した事になる。
尚、コンテナは実行が終了しても削除されない。下記のコマンドを実行すると終了したコンテナが残っているのが分かる:
core@coreos ~ $ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bab4118699d3 centos:7 "echo 'Hello, world. 7 seconds ago Exited (0) 6 seconds ago trusting_elion
これは明示的に削除するまで、いつまでも残る。削除する場合は以下のようにする:
core@coreos ~ $ docker rm bab4118699d3
bab4118699d3
インタラクティブに実行
core@coreos ~ $ docker run -i -t --rm=true centos:latest sh
sh-4.2# echo 'Hello, world.'
Hello, world.
sh-4.2# exit
exit
core@coreos ~ $
-
-i
(--interactive=true
) 標準出力受け付けの維持 -
-t
(--tty=true
) 疑似 TTY の割り当て -
--rm=true
終了時にコンテナを自動削除
バックグラウンドで実行
core@coreos ~ $ docker run -d centos:latest sh -c "while true; do echo \"Hello, world.\"; sleep 1; done"
ae101d4eb9eaa8cc43a6789fa8752825cb43df8e6e9a11093d44f5ebe61bb96c
-
-d
(--detach=true
) コンテナをバックグランドで実行し、コンテナ ID を返す
docker ps
でバックグラウンドプロセス一覧を取得する:
core@coreos ~ $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ae101d4eb9ea centos:7 "\"sh -c 'while true About a minute ago Up About a minute hungry_shockley
docker logs
にプロセスの NAME
を指定して出力のログを取得する:
core@coreos ~ $ docker logs hungry_shockley
Hello, world.
Hello, world.
Hello, world.
docker stop
にプロセスの NAME
を指定して終了させる:
core@coreos ~ $ docker stop hungry_shockley
hungry_shockley
docker rm
に CONTAINER ID
を指定してコンテナを削除する:
core@coreos ~ $ docker rm ae101d4eb9ea
ae101d4eb9ea
Dockerfile の利用
既存の centos
イメージ上で様々なプロセスを立ち上げてみて、それをカスタムイメージとして保存してみます。
CentOS コンテナで Apache と SSH を立ち上げてみる
まずはインタラクティブに centos
イメージ上に自分の環境を構築してみます。
centos:centos7
は systemctl
回りの挙動が難しかったので centos:centos6
で旧来通り service
コマンドを使用する事にします。
centos:centos6
コンテナをインタラクティブに起動します:
docker run -i -t --rm=true centos:centos6 sh
インタラクティブシェルに入ると root
ユーザーとしてログインしている。サンドボックス化されているので、権限など気にせずガンガン root
で作業する事にする。
下記手順で Apache と SSH 環境をセットアップします:
yum update -y
yum install -y httpd openssh-server
sed -ri "s/^#PermitRootLogin yes/PermitRootLogin yes/" /etc/ssh/sshd_config
sed -ri "s/^PasswordAuthentication yes/PasswordAuthentication no/" /etc/ssh/sshd_config
sed -ri "s/^ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/" /etc/ssh/sshd_config
sed -ri "s/^UsePAM yes/UsePAM no/" /etc/ssh/sshd_config
mkdir -m 700 /root/.ssh
cat - > /root/.ssh/authorized_keys <<__KEY__
ssh-rsa AAAAB3NzaC[...] anony@foo.bar
__KEY__
chmod 600 /root/.ssh/authorized_keys
chown root:root /root/.ssh/authorized_keys
chkconfig httpd on
chkconfig sshd on
service httpd start
service sshd start
と、ここまでセットアップしてサーバーは立ち上がったが、サンドボックス化されているので、これらのサーバーを外部に公開する術が分からない...
...と、これは docker run
する時のパラメータを追加する事で解決する:
docker run -i -t --rm=true --expose=22,80 -p 10022:22 -p 10080:80 centos:centos6 sh
-
--expose=PORT
コンテナ内で外部公開を許可するポートを指定する。 -
-p PUBLISHED:EXPOSED
コンテナ内部で外部公開を許可されたポートEXPOSED
とサーバー上で公開するのに使用する割り当てポートPUBLISHED
の対で指定する。
これで サーバーが立ち上がっている事を確認できる。
イメージ化する
さて、外部公開の方法だが、これはインタラクティブにコンテナを生成するのではなく、Dockerfile
というファイルにコンテナで実行するコマンドを列挙して、バックグランド化するのがベスト。
Dockerfile の作成
前述のインタラクティブシェルで実行した内容を Dockerfile
で表現すると、下記の 2 つのファイルになる。
ssh-rsa AAAAB3NzaC[...] anony@foo.bar
FROM centos:centos6
MAINTAINER Yu I. <yu.inao@facebook.com>
RUN yum update -y
RUN yum install -y httpd openssh-server
RUN sed -ri "s/^#PermitRootLogin yes/PermitRootLogin yes/" /etc/ssh/sshd_config
RUN sed -ri "s/^PasswordAuthentication yes/PasswordAuthentication no/" /etc/ssh/sshd_config
RUN sed -ri "s/^ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/" /etc/ssh/sshd_config
RUN sed -ri "s/^UsePAM yes/UsePAM no/" /etc/ssh/sshd_config
RUN mkdir -m 700 /root/.ssh
ADD ./authorized_keys /root/.ssh/authorized_keys
RUN chmod 600 /root/.ssh/authorized_keys && chown root:root /root/.ssh/authorized_keys
RUN chkconfig httpd on
RUN chkconfig sshd on
RUN service httpd start
RUN service sshd start
EXPOSE 22 80
CMD [ "/sbin/init" ]
これら 2 つのファイルを任意のディレクトリ (ここでは myimage
) に格納する:
./myimage/
├── Dockerfile
└── authorized_keys
ビルドしてイメージ化
Dockerfile
を書いたらビルドして前述の CentOS 等と同じくイメージ化する。
ビルドは下記のコマンドで:
docker build -t myimage ./myimage/
-
-t
(--tag=""
) イメージを識別するためのリポジトリ名とタグ名を指定
完了したら下記のコマンドでホスト上のイメージに登録されているのを確認:
docker images
イメージを実行
あとは centos
イメージと同様、docker run -d
でバックグランド実行してやれば良い。
ただしコンテナのポートを適切に公開するパラメータを付けて実行する:
docker run -d -p 10022:22 -p 10080:80 myimage
-
-p
(--publish=[]
) ホストの指定ポートでコンテナ内部の指定ポートを公開
これで HTTP サーバーであれば下記のアドレスでアクセス可能になる:
http://192.168.0.98:10080/
つかれた。