やりたいこと
Dockerのコンテナとのポートフォワーディング(ポート番号指定)を「テスト環境(自端末)」と「本番環境(heroku)」でソースファイルを分ける事なく実現したい。
①テスト環境ではホストOSの「8888」番ポートをコンテナの「8888」番ポートと紐づけたい。
②本番環境ではポート番号はheroku側で自動割当されるので、それを利用したい。
ネット調査をしてくと「dockerfile」や「docker-compose.yml」を本番環境用とテスト環境用でわけるような手法がありました(パット見でよく読んでいませんが)が、これは避けたかった。
前提
- 本番環境:heroku
- テスト環境:ローカル端末(自分のPC)
- docker-compose.ymlを利用
- dockerfileを利用
- pythonでアプリは実装
- webserverはflaskを利用
できるだけ最小の単位で実現したかったという思いから、「dockerfile」だけでなんとかできないか模索したが、どうにもならなかったので「docker-compose.yml」を利用することとしました。
STEP1:ホスト側に環境変数を新規に作成
図のように[wk_port:8888]というやつを作成
STEP2:ホスト環境変数を「docker-compose.yml」で参照
ポイント
①[ports]のところでホスト側の環境変数を参照し、ポートフォワーディング
②後続で、コンテナ上の環境変数としても[wk_port:8888]を利用したいので「environment」にて定義
ちなみに[8888]は本番環境では利用しません。
テスト環境用のポート番号として利用します。
version: '3'
services:
<サービス名>:
build:
dockerfile: ./Dockerfile
ports:
- $wk_port:$wk_port
environment:
wk_port: $wk_port
STEP3:webserver(Flask)起動時にコンテナ上の環境変数を参照し、ポートを振り分け
ソース自体は「hello world」を表示させるだけの簡易なものです。
ポイント
最後の部分で「コンテナ上」の環境変数[wk_port]を参照し、値が設定されている場合、設定されていない場合で処理を振り分けています
①値が設定されている場合=テスト環境です
⇒ wk_portをポート番号として利用するようにしています
②値が設定されていない場合=本番環境(heroku)です
⇒ herokuからポート番号を取得するようにしています
なお、heroku上(dynoという単位)で環境変数を作成することも可能です。
ターミナルから「heroku config:set <環境変数名>=<設定値>」を実行する
今回ですと「heroku config:set wk_port=''」としました。
from flask import Flask
import os
app = Flask(__name__)
@app.route('/')
def hello():
return 'hello world'
if __name__ == '__main__':
if os.environ.get('wk_port','')!='':
app.run(debug='true',host='0.0.0.0',port=os.environ.get('wk_port','8888'))
else:
app.run(debug='true',host='0.0.0.0',port=os.environ.get('PORT','5000'))
最後に
この方法が正しいのかはわかりませんが、実現できたので記録として残します。
後日談
投稿後、気になる点がでてきたので、別記事で投稿しています。