Fargateでのコンテナの上書き
について
- Fargateで
コンテナの上書き
をしようと思うと以下の2つができます。
- で、ちょっとコンテナの上書きをすることで解決したいなって問題があったので、いろんな事例を調べてみました。結果、Dockerfileの中身を上書きできるんだろうなって結論に至ったわけですが、どうやらそこで今回とんちんかんな認識をしてしまった結果、大いにハマってしまったという経験をしました。
- 参考にしたのは以下など
解決したい問題
- Fargateで作成したJMeterコンテナがあって、こいつはシナリオファイルを引数にとるのですが、引数を環境変数として規定して、環境変数を上書きすることで引数にとるシナリオファイルを変更する(違う種類のシナリオを実行する)ようにしたい、というのが今回解決したい問題でした。
解決前の状況
- FargateでJMeterコンテナが実行します。
- Dockerfileには、以下を記載しています。
- ENTRYPOINTで
jmeter.sh
を実行する
- CMDで
-n -t シナリオファイル
- 結果的に、
jmeter.sh -n -t シナリオファイル
というコマンドを実行するコンテナとなり、シナリオファイルに沿った内容のWEBチェックを実行します
FROM alpine:3.9
ARG JMETER_VERSION="5.1.1"
ARG PLUGIN_VERSION="1.4.0"
ENV JMETER_HOME /opt/apache-jmeter-${JMETER_VERSION}
ENV JMETER_BIN ${JMETER_HOME}/bin
ENV JMETER_DOWNLOAD_URL https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz
ENV PLUGIN_DOWNLOAD_URL https://jmeter-plugins.org/downloads/file/JMeterPlugins-Standard-${PLUGIN_VERSION}.zip
ENV SCENARIO_DOWNLOAD_URL [S3に配置したJMeterのシナリオファイル.jmx]
# Install extra packages
ARG TZ="Asia/Tokyo"
RUN apk update \
&& apk upgrade \
&& apk add ca-certificates \
&& update-ca-certificates \
&& apk add --update openjdk8-jre tzdata curl unzip bash \
&& apk add --no-cache nss \
&& rm -rf /var/cache/apk/* \
&& mkdir -p /tmp/dependencies \
&& curl -L --silent ${JMETER_DOWNLOAD_URL} > /tmp/dependencies/apache-jmeter-${JMETER_VERSION}.tgz \
&& curl -L --silent ${PLUGIN_DOWNLOAD_URL} > /tmp/dependencies/JMeterPlugins-${PLUGIN_VERSION}.zip \
&& curl -L --silent ${SCENARIO_DOWNLOAD_URL} > /tmp/test-plan.jmx \
&& mkdir -p /opt \
&& tar -xzf /tmp/dependencies/apache-jmeter-${JMETER_VERSION}.tgz -C /opt \
&& unzip -oq "/tmp/dependencies/JMeterPlugins-${PLUGIN_VERSION}.zip" -d $JMETER_HOME \
&& rm -rf /tmp/dependencies
ENV PATH $PATH:$JMETER_BIN
WORKDIR ${JMETER_HOME}
ENTRYPOINT [ "jmeter.sh" ]
CMD [ "-n" , "-t" , "/tmp/test-plan.jmx" ]
- で、シナリオファイルを差し替えて実行したい場合は、上記のDockerfileに記載した内容の
ENV JMETER_DOWNLOAD_URL
をFargateの環境変数の上書き
で上書きすればいいだけだと考えたのです。
全然うまくいかないよ、、、
- でも全然うまくいかない。これはFargateのせいかと考えて色々と調べてみた結果、Fargateの問題ではなく、そもそもDockerfileの書き方が良くないんじゃないかという事に、思い至りました。
- というか、、、
ENV JMETER_DOWNLOAD_URL
自体はちゃんと上書きされていた、、、
- でもそうなると、なぜうまくいかないのか?と思いましたが、以下のように考えると納得できました。
ENV JMETER_DOWNLOAD_URL
の値自体が上書きされても、DockerRun時に、その次の行以下に記載されているRUN
内容が再実行することってないよね?
- うん。一度Buildされているから、DockerRunするたびにイメージをBuildするなんて意味不明な動きをDockerがすることはないよな。と、、、
一度に2度の作業をするコンテナを作りたい
- で、そうなってくると今回作ったJMeterのコンテナって、以下の2つのことを一度に実行してくれないと困るってことになります。
jmeter.sh
を実行すること
シナリオファイルをダウンロード
すること
ならば簡単だ!ENTRYPOINT
かCMD
を複数書けばいい!
- が、話はそんなに簡単ではありませんでした。
- まず、CMDはENTRYPOINTの引数のような形で記載しないといけない
- なので、ENTRYPOINTで
jmeter.sh
を実行しているのに、CMDでcurl
を実行しようとするとjmeter.sh
にはcurl
なんてオプションはありませんよって言われる、、、
- であれば、ENTRYPOINTは使わない!CMDを2個書いてやる!となるのですが、CMDは複数書いても最後に書いた内容しか実行されない、、、
- やばい、、、どうすればいいんだ??
- で、このシェルスクリプトをどう書くかっていうのがセンスだよなあって痛感しました。自分はここで相当悩み、助け舟を出してもらい解決策を見出しました。こいうところでサクッとスクリプトを書けるような人間になりたいなあ!!
#!/bin/bash
curl -L --silent $1 > /tmp/test-plan.jmx
jmeter.sh -n -t /tmp/test-plan.jmx
$1
で第一引数をcurlしてシナリオファイルとして保存します
- 保存したシナリオファイルを
jmeter.sh -n -t /tmp/test-plan.jmx
で実行する
- そして、Dockerfileに以下のように記載して
CMD
に第一引数となるシナリオファイルの保存先を指定する
COPY run.sh /tmp/
ENTRYPOINT [ "sh" , "/tmp/run.sh" ]
CMD [ "S3上のシナリオファイル" ]
- こうすることで、
コンテナの上書き
であるCMDの上書き
を利用してシナリオファイルの引数をいかようにも書き換えられるということになります。
ということで課題クリア!
- シナリオファイルが複数になった場合の対応は、上記の対応策で解決です。
- また、JMeterのバージョン変更とか大きな変更のときはビルドし直す必要がありますが、そんなときはイメージにつけるタグで管理します
まとめ
- Fargateはあくまで実行環境で、実行の大元となるDockerfileを正しく理解することがコンテナを利用する際には必要なんだと感じました。
- Dockerfileのコマンドの意味が理解できてくると、Fargateってこんなに便利なんだなって理解できるようになりました。
- 例えば今回のFargateの
コンテナの上書き
機能として利用したCMDの上書きも、docker上でいうdocker run image名 [CMDの上書き]
コマンドと同じ意味で、Dockerで使える機能がAWS上で気軽に使えるっていうのは凄いことなんだなって思いました。