ECS上にamazonlinux2環境を構築するときの落とし穴

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261265/a4994afb-7d86-6b08-07cc-d86d36376e29.png)

## はじめに

皆さん、どうもです。[ｋ．ｓ．ロジャース](https://www.wantedly.com/companies/ks-rogers)のやすもんです。
今回は、先日構築したECSのamazonlinux2環境でコンテナインスタンスがぶっ壊れるという落とし穴にハマったので、現象の共有と回避方法を書いていきたいと思います。

## 前提
* AWSのECS上に構築する
* イメージはamazonlinux2を利用
* systemctlを利用してサービスの管理をしたい

## ECS上に上記の前提でhttpdが動くコンテナを作成
### まずはローカルで構築
適当にhttpdが動くdockerを用意します

```Dockerfile
# amazon linux
FROM amazonlinux:2

# httpd24
RUN yum -y install httpd

RUN systemctl enable httpd.service
```

ビルドしてコンテナ起動

```shell
$ docker build -t test:latest ./

$ docker run --privileged -d -t -p 8080:80 --name testapp test:latest /sbin/init
```

動作確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261265/4c828223-bb31-d174-4a30-fcfb9557f261.png)

### ECSにデプロイする
ECRを作成して先程作ったイメージをアップロード
<img width="883" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/261265/2275ee21-78e2-4eba-0cc2-a94d3b794210.png">

適当にクラスタを作成
<img width="716" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/261265/0200305e-7557-0aac-0314-a93da8d62531.png">

タスク定義を作成
<img width="1250" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/261265/c9ec973a-4eb7-cd06-dff9-a304f8469e39.png">
systemctlを利用するために特権付与し、コマンドで`/sbin/init`を指定

タスクを起動する
<img width="1092" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/261265/619f2a0b-96ca-e1ee-3a99-60c8a993871a.png">

動作確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/261265/39487661-dc2a-9864-2389-0ad86dfa74b3.png)

## 落とし穴
一見、上記まで実行して「あれ？できてるやん？」て思うかもしれませんが、落とし穴はここからです

ECSを利用している方々は、CIを組んで自動でデプロイできる仕組みを作り、頻繁にイメージとコンテナが更新されるという運用をしている方が大半だと思います。

ということで、次に全く同じ構成で新しいタスク定義を作成して手動で更新してやりましょう
タスクを停止します
<img width="1020" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/261265/72e3df98-683c-1989-9dc1-ac74db75ef1f.png">

全く同じ内容でタスク定義を作成して、起動させます
<img width="877" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/261265/187c87bf-a736-f213-fba5-d0f527dc5595.png">

すると、エラーが出てSTOPします
<img width="1306" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/261265/1d7609ad-3689-3d04-7d33-1daa7ea3bcf3.png">

エラー内容は

```
CannotStartContainerError: API error (500): cgroups: cannot find cgroup mount destination: unknown 
```

ほう。。。cgroupをマウントできずにエラーとな。。。

色々調査して以下のような記事を見つけて対応しようと試みるも。。。
http://blog.livedoor.jp/kkss06122015-armadillo/archives/10167213.html

そもそも、ECSのインスタンスの`/sys/fs/cgroup`配下はからっぽ。。。
記述されている`sudo mkdir /sys/fs/cgroup/systemd`も権限エラーで実行できず、systemdを無理やり作ってマウントすることも不可でした。

どうやら、特権付与(privileged)をtrueにしてしまうと初回起動はするが、その後コンテナを更新したときにマウントエラーが発生し、以降コンテナが立ち上がらなくなるみたいだ・・・
そして、systemctlを利用するには、特権付与(privileged)をtrueにしないといけない。

特権付与(privileged)をtrueにせず、systemctlを使えようにする方法など色々調査して実験してみたが、この現象を回避する方法はなさそうだった。

## 回避方法
では、この落とし穴をどう回避するのかというと、docker経験者はピンとくるかもしれませんが、foreground固定します。
また、殆どの場合systemctlを利用したい場合は複数のサービスを起動させたいという理由があると思うので、以下のように記述します。

```Dockerfile
# amazon linux
FROM amazonlinux:2

# httpd24
RUN yum -y install httpd php-fpm

CMD /bin/bash -c "httpd && php-fpm && tail -f /dev/null"
```

こうすることで、systemctlを利用しないため、特権付与(privileged)が不要になります。
よって、コンテナを再作成したときのcgroupのマウントエラーが発生しなくなるという感じです。
補足ですが、Dockerfile上でCMDを指定したのでタスク定義で指定していたcommandの`/sbin/init`は不要になります。

## 最後に
今回はECS上にamazonlinux2を構築したときにハマった落とし穴を紹介しました。
実際に私自身この落とし穴に2~3日ハマって、systemctlは利用しないという結論に至りました。
もっとスマートな解決法を知っている方はコメント欄にて教えて頂きたいです！

### Wantedlyでもブログ投稿してます
Techブログに加えて会社ブログなどもやっているので、気になった方はぜひ覗いてみてください。
https://www.wantedly.com/companies/ks-rogers