Dockerで1つのイメージ複数のコマンドを切り替える方法
2018-01-29 17:30:00 +0900
これをやりたい理由
作るDockeイメージは1つにしたいのだけど、デプロイする先によってコンテナの役割(例えばCronやJobワーカーを動かすコンテナとWebサーバーを実際に動かすコンテナ等)を分けたいときに利用する。
例えばAzureのWebApps for Container (Web Apps on Linux)で、 Webサーバーはスケールアウトしたいけど、Jobワーカーサーバーはスケールアウトしたくない(もしくはJobワーカーサーバーは任意のタイミングにしたい)とか 管理するコンテナを分けたいとかそういうときに利用すれば便利だと思っている。
やりかた
init.shという起動時の環境変数によって実行するコマンドを変更するスクリプトをCMDで実行してあげればOK。 これで実行時に環境変数を渡してあげればOK。
下記例はRubyアプリケーションを動かす際の自分のDockerfileの雛形のようなものである。
# Dockerfile --- FROM ruby:2.5 ENV LANG C.UTF-8 ENV RACK_ENV production EXPOSE 3000 RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY Gemfile /usr/src/app/ COPY Gemfile.lock /usr/src/app/ RUN bundle install -j4 --without development test RUN mkdir tmp COPY . /usr/src/app RUN chmod u+x init.sh CMD "./init.sh"
# init.sh --- #!/bin/bash set -e if [[ "${RUN_WEBAPP}" != "" ]] then echo "Starting uniron ..." bundle exec unicorn -c config/unicorn.rb else [[ "${RUN_WEBJOB}" != "" ]] echo "Starting sidekiq ..." bundle exec sidekiq -r ./app.rb -C ./sidekiq.yml fi
以上の内容でDockerイメージをBuildして、docker runするときに環境変数を渡せばOK。
サンプルでWebサーバーを実行する場合
docker run -e RUN_WEBAPP=true xxx
サンプルでJobワーカーサーバーを実行する場合
docker run -e RUN_WEBJOB=true xxx
おわりに
ちなみにAWSのElasticBeanstalkあたりだとマルチコンテナーをそもそもサポートしているので、そっちを使うほうがまぁ普通だと思っている。 もしくはCronを利用しないで、SidekiqやDelatedJobあたりでワーカーがいくらスケールアウトしても問題ないようにするとか、 WebサーバーとWorkerの同居を許容してしまうとか、そういう方法で解決したほうが至極真っ当な感じはする。
余談
AzureからAWSのDynamoDBって利用すると遅いのかな。 ぶっちゃけ用途があえばCosmosDBでもよかったんだけど、メッセージングアプリっぽいの作りたくて、 MongoベースのAPIでまともに要件を満たせるのか感があって、不安...