📒

docker-composeで環境によってDockerfileのCMDを使い分けたい

2022/04/15に公開

やりたいこと

少し複雑なdocker-composeでテスト向けと、その他の環境(developmentやproduction)の設定を使い分けたいです。
その時、docker-composeのコマンドを呼び出す時のオプションで使い分けられるようにしたいです。
ここで、docker-compose-fオプションで、docker-composeの値を変えることができるのは知っていたのですが、ここでしたいのは、Dockerfileに書かれてある

CMD ["npm", "test"]

を、実行時には

CMD ["node", "index.js"]

としたいということです。最初はif文で書いても良いのかと思いましたが、後の章で書いていますが、あまり良くないようです。

環境

本来はもっと複雑なのですが、記事用に簡素化します。使っているものは以下の3つだけです。

  • node.js
  • mariadb
  • docker-engine & docker-compose

環境による分け方

色々と調べた結果、daisuke furukawaさんの記事[1]のように、環境によってDockerfileを分け、docker-compose.ymlとは別に、例えば、development.ymlのようなdocker-composeのdeploy環境情報を上書きするファイルを作りdeployするのが良さそうです。個人的には、ファイルの数が多くなって、あまり気が進まないのですが…
例えば

  • Dockerfile: テスト用
  • Dockerfile.dev: ローカル実行用
  • docker-compose.yml: テスト用をベースとしたdocker-compose
  • development.yml: ローカル実行用にdocker-composeを上書きする

と言った感じですね。
そして、テストをするときは、普通に

docker-compose up --build

と実行して、ローカルで実際に動かすときは

docker-compose -f docker-compose.yml -f development.yml up --build

と言った感じに動かします。
ちなみに、development.yml

version: "3"
services:
  api:
    build:
      dockerfile: ./Dockerfile.dev
  web:
    build:
      dockerfile: ./Dockerfile.dev

というように、変更点だけ書けばOKです。
良くない(であろう)例は次の章に書いています。

良くない(であろう)例〜Dockerfileにif文を書く〜

僕もはじめ、推測では、node.jsで立てるコンテナのDockerfileで実行するコマンドを、環境によって使い分けることをしないといけないと思っていました。
例えば、こんな感じ

FROM node:16

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install
RUN npm install pm2 -g

COPY . .

EXPOSE 3000

if NODE_ENV == "TEST"
CMD ["npm", "test"]
else 
CMD ["pm2-runtime" ,"web.config.js"]

しかし、@t_nさんの記事[2]によるとif文を使う方法は、あまり良くないようです。

さいごに

自分は職業エンジニアではなく、実務で使ったことがないので、もっといい方法があれば、ご教示いただけると幸いです。

脚注
  1. dockerで本番環境と開発環境を使い分ける方法いろいろ / daisuke furukawa https://crieit.net/posts/docker (2022-04-15閲覧) ↩︎

  2. DockerFileにif文(条件分岐) / @t_n (Qiita) https://qiita.com/t_n/items/203cd3593427a35f7ed7 (2022-04-15閲覧) ↩︎

Discussion