2017年1月17日火曜日

sshログインできるテスト環境を Docker で作る


Dockerコンテナでテストした AnsibleのPlaybook を EC2構築に、そのまま使用したいと思い、
EC2(CentOS6)の初期状態に近い環境を、Docker コンテナで用意してみました。

ここでは、CentOS7 の Dockerを使用しています。

Ansibleのテスト用に用意するDocker コンテナは以下のようにセットアップします。
  • OSは centos6 を使用すること
  • centosユーザで 秘密鍵(パスフレーズなし)を使用した sshログインができること
  • centosユーザで sudo(パスワードなし)が使用できること
  • ja_JP.UTF-8 が使用できること

1. CentOS6 の Dockerイメージをダウンロード


Docker HUB から CentOS6のイメージをダウンロードしてローカルに保存します。
[root@centos0702 docker]# docker pull centos:6
Trying to pull repository docker.io/library/centos ...
6: Pulling from docker.io/library/centos
32c4f4fef1c6: Already exists
Digest: sha256:1092df198d3da4faccc0660941b763ce5adf133b0ec71701b760d6f173c1f47b
Status: Downloaded newer image for docker.io/centos:6

ローカルに保存したイメージを確認します。
[root@centos0702 docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    6                   8315978ceaaa        10 weeks ago        194.6 MB


2. Docker コンテナのセットアップ


DockerコンテナをEC2(CentOS6)の初期状態に寄せていきます。
Docker コンテナを起動します。下記の例ではコンテナのホスト名を centos6 としています。
[root@centos0702 docker]# docker run -it -h centos6 centos:6 /bin/bash
[root@centos6 /]#

EC2(CentOS6)に寄せるのに最低限必要と思われるパッケージを追加インストールします。
[root@centos6 /]# yum -y install cloud-init iptables-ipv6 openssh-server openssh-clients sudo

ロケールに ja_JP.UTF-8 が無いので glibc-common を再インストールして追加します。
[root@centos6 /]# locale -a
C
POSIX
en_US.utf8
[root@centos6 /]# yum -y reinstall glibc-common
[root@centos6 /]# locale -a | grep ja
ja_JP
ja_JP.eucjp
ja_JP.ujis
ja_JP.utf8
japanese
japanese.euc

wheel グループに所属しているユーザはsudo(パスワードなし)を使用可能にします。
[root@centos6 /]# sed -i -e 's/^# \(%wheel.ALL=(ALL).NOPASSWD: ALL\)$/\1/' /etc/sudoers
[root@centos6 /]# grep wheel /etc/sudoers
## Allows people in group wheel to run all commands
# %wheel        ALL=(ALL)       ALL
%wheel  ALL=(ALL)       NOPASSWD: ALL

centos ユーザを追加します。一応、パスワード(p@ssw0rd)を設定します。
[root@centos6 /]# useradd -d /home/centos -s /bin/bash -G wheel centos
[root@centos6 /]# echo "centos:p@ssw0rd" | chpasswd
[root@centos6 /]# id centos
uid=500(centos) gid=500(centos) groups=500(centos),10(wheel)

sshd を初期化します
[root@centos6 /]# service sshd start
Generating SSH2 RSA host key:                              [  OK  ]
Generating SSH1 RSA host key:                              [  OK  ]
Generating SSH2 DSA host key:                              [  OK  ]
Starting sshd:                                             [  OK  ]

ここからは 別ターミナルを使用して、ホスト側で作業します。
コンテナID を調べます。
[root@centos0702 docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
d0dcd51f6301        centos:6            "/bin/bash"         41 minutes ago      Up 41 minutes                           stoic_mestorf

ホストからコンテナにテスト用に SELinux の config ファイルをコピーします
[root@centos0702 docker]# docker cp /etc/selinux/config d0dcd51f6301:/etc/selinux/config

ホストで centos ユーザ用のSSH鍵を作成します。
[root@centos0702 docker]# ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
57:d3:40:15:47:1b:43:9c:6c:5f:26:5e:d4:6a:60:ff root@centos0702
The key's randomart image is:
+--[ RSA 4096]----+
|           .o.*B*|
|            oo.*O|
|           .o+o*o|
|           . .= .|
|        S .  . . |
|         .      E|
|                 |
|                 |
|                 |
+-----------------+

コンテナのcentos ユーザに公開鍵を設定します。
[root@centos0702 docker]# cat ~/.ssh/id_rsa.pub > ./authorized_keys
[root@centos0702 docker]# docker exec d0dcd51f6301 mkdir -p /home/centos/.ssh
[root@centos0702 docker]# docker exec d0dcd51f6301 chmod 700 /home/centos/.ssh
[root@centos0702 docker]# docker exec d0dcd51f6301 chown centos.centos /home/centos/.ssh
[root@centos0702 docker]# docker cp ./authorized_keys d0dcd51f6301:/home/centos/.ssh/authorized_keys
[root@centos0702 docker]# docker exec d0dcd51f6301 chmod 600 /home/centos/.ssh/authorized_keys
[root@centos0702 docker]# docker exec d0dcd51f6301 chown centos.centos /home/centos/.ssh/authorized_keys

コンテナのIPアドレスを調べて、秘密鍵で ssh ログインできるか試します。
[root@centos0702 docker]# docker inspect d0dcd51f6301 | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",
[root@centos0702 docker]# ssh -l centos -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null 172.17.0.2
[centos@centos6 ~]$ exit
logout
Connection to 172.17.0.2 closed.

最後に、コンテナを終了します。
[root@centos6 /]# exit
exit
[root@centos0702 docker]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
d0dcd51f6301        centos:6            "/bin/bash"         About an hour ago   Exited (0) About a minute ago                       stoic_mestorf


3. Docker イメージの作成


上記2のコンテナからイメージを作成します
[root@centos0702 docker]# docker commit d0dcd51f6301 centos6_ec2
sha256:108de20759f57d7c0c77110a449f532a80006f5a2656a36e851a3452c7b73151

イメージを確認します
[root@centos0702 docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos6_ec2         latest              108de20759f5        25 seconds ago      632.9 MB
docker.io/centos    6                   8315978ceaaa        10 weeks ago        194.6 MB

不要になったコンテナを削除します。
[root@centos0702 docker]# docker rm d0dcd51f6301
d0dcd51f6301
[root@centos0702 docker]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES


4. Dockeイメージの起動&動作確認


上記で作成したイメージ(centos6_ec2)からコンテナを起動して、Ansible で疎通確認をしてみます。

sshd サービスを forground で実行し、コンテナを常駐起動します。 
[root@centos0702 docker]# docker run -d centos6_ec2 /usr/sbin/sshd -D
386a0684a9fcdd66229ecb36dd4b856ffe864f70a052131db3c1b3b4ec823516
[root@centos0702 docker]# docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS               NAMES
386a0684a9fc        centos6_ec2         "/usr/sbin/sshd -D"   7 seconds ago       Up 4 seconds                            jolly_banach

コンテナのIPアドレスを調べます
[root@centos0702 docker]# docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS               NAMES
386a0684a9fc        centos6_ec2         "/usr/sbin/sshd -D"   7 minutes ago       Up 7 minutes                            jolly_banach
[root@centos0702 docker]# docker inspect 386a0684a9fc | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",

Ansible で疎通確認します。
デフォルトで、~/.ssh/id_rsa の秘密鍵が使用されるので、明示的に --private-key は指定しません。
[root@centos0702 docker]# env ANSIBLE_HOST_KEY_CHECKING=False ansible -u centos -i ,172.17.0.2 172.17.0.2 -m ping
172.17.0.2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Dockerコンテナを停止します
[root@centos0702 docker]# docker stop 386a0684a9fc
386a0684a9fc
[root@centos0702 docker]# docker ps -a
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS                       PORTS               NAMES
386a0684a9fc        centos6_ec2         "/usr/sbin/sshd -D"   11 minutes ago      Exited (255) 7 seconds ago                       jolly_banach

停止したDockerコンテナを開始します
[root@centos0702 docker]# docker start 386a0684a9fc
386a0684a9fc
[root@centos0702 docker]# docker ps -a
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS               NAMES
386a0684a9fc        centos6_ec2         "/usr/sbin/sshd -D"   13 minutes ago      Up 2 seconds                            jolly_banach