みなさんDocker使ってますか。私は闇の深いEC2に阻まれて難しい状況です。闇を抱えたままDockerizeします。
闇が深いとは
このくらいを指すものとします。
- AMIの出所がわからない
- EC2インスタンスのAMI IDが、自前AMIになってる
- Linuxディストリはわかるが、起点にしたバージョンはわからない
- AMIがどうやってできたのかわからない
- sudo vi /etc/hoge.conf してるっぽい
- sudo yum install -y hoge してるっぽい
- wget https://~~~~/hoge.tar.gz から make install してるっぽい
- AMI更新手順がわからない
- 変更したい人々と、変更できる人々が違っている
- 実施できるのは、本番環境にSSHできる極少人数
- 簡単なはずのconfの変更も尻込みして進まない
- Dockerize & k8s移行とか盛り上がるけど、遠すぎて動きが鈍い
AWS使っててもこれよりヤバい現場や、オンプレでさらにヤバい現場はいくらでもあるでしょうけど、一旦このくらいで。
Dockerコンテナ化したいEC2インスタンスを用意し、闇の深いEBSボリュームをデタッチする
闇の深いEC2インスタンスを用意します。NDAの都合で手頃なEC2インスタンスがないので、Amazon Linux1の最新のAMIからEC2インスタンスを作成して、でっちあげます。後の動作確認のため、説明上のサンプルの闇として、$HOMEにテキストファイルを設置しておきました。
[ec2-user@ip-172-16-12-85 ~]$ pwd
/home/ec2-user
[ec2-user@ip-172-16-12-85 ~]$ echo "hello world" > hoge.txt
[ec2-user@ip-172-16-12-85 ~]$ cat hoge.txt
hello world
[ec2-user@ip-172-16-12-85 ~]$
キモはDockerizeしたいEC2インスタンスのEBSボリュームです。これをどうにか調達できるなら、AMIからでも何でも大丈夫です。
Dockerコンテナイメージ作成用EC2インスタンスを作る
注意事項は以下くらいを守れば雑で大丈夫です。
- 先程のEBSスナップショットと同じアベイラビリティゾーンに、EC2インスタンスを作成する
- LinuxなEC2インスタンスを作成する
- ストレージ増し(たとえばgp2で20GB)、グレード上げ(t3.small)など雑で構わないので強めに作成する
- EC2にIAMロールをつけておく。ECRにpush,pullできる権限をつけておく。
[ec2-user@ip-172-16-4-210 ~]$ sudo yum update -y
[ec2-user@ip-172-16-4-210 ~]$ sudo yum install docker
[ec2-user@ip-172-16-4-210 ~]$ sudo reboot
[ec2-user@ip-172-16-4-210 ~]$ sudo systemctl start docker.service
[ec2-user@ip-172-16-4-210 ~]$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[ec2-user@ip-172-16-4-210 ~]$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
闇の深いEBSボリュームを、Dockerコンテナイメージ作成用EC2インスタンスにアタッチする
AWSマネジメントコンソールで、ポチポチしてアタッチします。EC2インスタンス内でディレクトリを作成して、mountします。
[root@ip-172-16-4-210 ec2-user]# mkdir /mnt/darkness-ebs
[root@ip-172-16-4-210 ec2-user]# mount /dev/nvme1n1p1 /mnt/darkness-ebs
[root@ip-172-16-4-210 ec2-user]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 961M 0 961M 0% /dev
tmpfs 978M 0 978M 0% /dev/shm
tmpfs 978M 436K 978M 1% /run
tmpfs 978M 0 978M 0% /sys/fs/cgroup
/dev/nvme0n1p1 20G 1.5G 19G 8% /
tmpfs 196M 0 196M 0% /run/user/1000
/dev/nvme1n1p1 7.9G 1.1G 6.7G 14% /mnt/darkness-ebs
[root@ip-172-16-4-210 ec2-user]#
EBSの中身で、Dockerコンテナイメージを作る
マウントポイントにEBSの中身がまるごと入ってますので、これでDockerコンテナイメージを作ります。怪しいのが出てますが、いったん気にしない。
[root@ip-172-16-4-210 ec2-user]# cd /mnt/darkness-ebs
[root@ip-172-16-4-210 darkness-ebs]# tar -c -C /mnt/darkness-ebs/ . | docker import - darkness-image
tar: ./var/run/acpid.socket: socket ignored
tar: ./var/run/dbus/system_bus_socket: socket ignored
sha256:b141609cf9664a07dc17371b8d6545e16d921c809a6cd845da66d119c85fe92f
[root@ip-172-16-4-210 darkness-ebs]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
darkness-image latest b141609cf966 8 seconds ago 1.04GB
[root@ip-172-16-4-210 darkness-ebs]#
Dockerコンテナを起動する
Dockerコンテナイメージを作れたので、起動してみましょう。正しくできているなら、 /home/ec2-user/hoge.txt
の中身が闇の深いものになっているはずです。
[root@ip-172-16-4-210 darkness-ebs]# docker run -itd darkness-image /bin/bash
6d326fb4879e3a3015116e3215bfe8c2376d7fc16abea0b60ec112e333d6fc52
[root@ip-172-16-4-210 darkness-ebs]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d326fb4879e darkness-image "/bin/bash" 11 seconds ago Up 9 seconds ecstatic_sinoussi
[root@ip-172-16-4-210 darkness-ebs]# docker exec -it 6d326fb4879e /bin/bash
[root@6d326fb4879e /]# cd /home/ec2-user/
[root@6d326fb4879e ec2-user]# ls -alF hoge.txt
-rw-rw-r-- 1 ec2-user ec2-user 12 Oct 14 07:29 hoge.txt
[root@6d326fb4879e ec2-user]# cat hoge.txt
hello world
[root@6d326fb4879e ec2-user]#
よさげ。
DockerイメージをAWS ECRに登録する
Docker Hubにパブリックイメージとして登録できれば、取り回しも楽なのですが、ここまでの手順を踏まなければならないような状況のDockerイメージが、パブリックにできるわけもないです。ECRに登録しましょう。
[root@ip-172-16-4-210 darkness-ebs]# aws ecr get-login --no-include-email --region us-east-2
[root@ip-172-16-4-210 darkness-ebs]# docker login -u AWS -p (略)
[root@ip-172-16-4-210 darkness-ebs]# docker tag darkness-image:latest 841403573067.dkr.ecr.us-east-2.amazonaws.com/darkness-image:latest
[root@ip-172-16-4-210 darkness-ebs]# docker push 841403573067.dkr.ecr.us-east-2.amazonaws.com/darkness-image:latest
The push refers to repository [841403573067.dkr.ecr.us-east-2.amazonaws.com/darkness-image]
fd32b2439881: Pushed
latest: digest: sha256:814254568e93795d20a91c2e28dc6dcdeffe6975e960b8f1c68bb5890593b65c size: 529
[root@ip-172-16-4-210 darkness-ebs]#
Dockerfileで利用する
ECRからのpullが若干煩雑ですが、それだけなんとかすれば、なんとでもなります。
[root@ip-172-16-4-210 darkness-ebs]# aws ecr get-login --no-include-email --region us-east-2
[root@ip-172-16-4-210 darkness-ebs]# docker login -u AWS -p (略)
あとは、いつものDockerfileで好きなように。
[root@ip-172-16-4-210 ~]# cat Dockerfile
FROM darkness-image:latest
RUN echo "hello world"
CMD /bin/bash
[root@ip-172-16-4-210 ~]# docker build -t darkness-image:1.0.0 .
Sending build context to Docker daemon 16.38kB
Step 1/3 : FROM darkness-image:latest
---> b141609cf966
Step 2/3 : RUN echo "hello world"
---> Running in aa28eeffae4f
hello world
Removing intermediate container aa28eeffae4f
---> d2a56a7ba2e1
Step 3/3 : CMD /bin/bash
---> Running in 44a51a617196
Removing intermediate container 44a51a617196
---> edc94cc0c123
Successfully built edc94cc0c123
Successfully tagged darkness-image:1.0.0
[root@ip-172-16-4-210 ~]#
ECRにpushしたら、各所で使えるようになります。
[root@ip-172-16-4-210 ~]# docker tag darkness-image:1.0.0 841403573067.dkr.ecr.us-east-2.amazonaws.com/darkness-image:1.0.0
[root@ip-172-16-4-210 ~]# docker push 841403573067.dkr.ecr.us-east-2.amazonaws.com/darkness-image:1.0.0
The push refers to repository [841403573067.dkr.ecr.us-east-2.amazonaws.com/darkness-image]
fd32b2439881: Layer already exists
1.0.0: digest: sha256:15a5a58ba521936180f67f12f36c311a498b477e436e7e3f7bd0c9274437e661 size: 530
[root@ip-172-16-4-210 ~]#
ローカル開発環境で利用する
ECRからのpullが若干煩雑ですが、それだけなんとかすれば、なんとでもなります。
sasasin@mbp2018:~$ aws ecr get-login --no-include-email --region us-east-2
sasasin@mbp2018:~$ docker login -u AWS -p (略)
sasasin@mbp2018:~$ docker run -itd darkness-image:1.0.0 /bin/bash
デーモンプロセスをどうにかする
ECRまでのpushを優先するため /bin/bash
にしてますが、実際のところ何かデーモンプロセスが常駐して、たぶん sysvinit
, upstart
, systemd
あたりのはず。どうにかがんばる必要があります。Dockerコンテナ内で sysvinit
, upstart
, systemd
を動かすのもそれなり大変なので、おとなしく supervisord
にするのが無難かと思います。
突貫にやるなら、コンテナ起動時に呼ぶ /sbin/bootstrap.sh
みたいなのを用意すれば十分かもしれません。中身はたとえばこのように。
#!/bin/bash
/sbin/service nginx start
/sbin/service puma start
/sbin/service crond start
Dockerfileを改善していく
Dockerfileにできたことで、
- DockerfileとしてGitHub管理できるようになる
- ローカル環境などで、挙動の検証がやりやすくなる
- セキュリティパッチ入れたときとか
- confを変更したときとか
- 何かインストールしてみたときとか
- Dockerコンテナを動かせるところなら、どこでも動かせる
- ECS, EKS など
- 他のパブリッククラウドに移設してもよい
などなど、手のつけられないEC2インスタンスが、手のつけられるようになります。闇を抱えながらも、前進することができるようになります。Dockerizeしていきましょう。