Docker環境でドメインごとにコンテナを切り替える為の方法はいくつか提供して下さっている方がいます。
その中で私が試したのは下記の二つになります。
- nginx-proxy
→既に積極的な開発は行われていません
→1コンテナで複数のポートを開放している場合、私が思ったようなアクセスができませんでした。 - traefik
上記の機能を試した結果、私の目的には「traefik」が合致しました。
■traefikを動作させる
/tmp/traefik.yml
# Providers config
providers:
docker: {} # Dockerとの連携を有効
# API/Dashboard config
api:
insecure: true # WebUI にアクセスできるように設定
# コンテナを作る前に必ずポートが使用できることを確認してください
entryPoints:
web:
address: ":80"
secure:
address: ":443"
nodejs:
address: ":8080"
certificatesResolvers:
default:
acme:
email: system@test.local
storage: acme.json
httpChallenge:
entryPoint: web
entryPointsは各環境のポート等に合わせて定義を行ってください。
docker-compose.yml
version: '3.7'
services:
traefik:
image: traefik
container_name: traefik
restart: "always"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /tmp/traefik.yml:/etc/traefik/traefik.yml:ro
docker-compose-app.yml
version: '3.7'
services:
test-app-test:
# =====================
# 既存のコンテナの設定
# =====================
# アプリのコンテナの設定に下記を追加する
labels:
- traefik.enable=true
- traefik.docker.network=docker-network
- traefik.http.middlewares.app-https-redirect.redirectscheme.scheme=https
# 80設定(HTTPSにリダイレクト)
- traefik.http.routers.test-app-test.rule=Host(`apptest.local`))
- traefik.http.routers.test-app-test.entrypoints=web
- traefik.http.routers.test-app-test.middlewares=app-https-redirect
# 443設定
- traefik.http.routers.test-app-test-secure.rule=Host(`apptest.local`))
- traefik.http.routers.test-app-test-secure.entrypoints=secure
- traefik.http.routers.test-app-test-secure.tls=true
- traefik.http.routers.test-app-test-secure.service=test-app-test-secure-service
- traefik.http.services.test-app-test-secure-service.loadbalancer.server.port=80
# 8080設定
- traefik.http.routers.test-app-test-nodejs.rule=Host(`apptest.local`))
- traefik.http.routers.test-app-test-nodejs.entrypoints=nodejs
- traefik.http.routers.test-app-test-nodejs.tls=true
- traefik.http.routers.test-app-test-nodejs.service=test-app-test-nodejs-service
- traefik.http.services.test-app-test-nodejs-service.loadbalancer.server.port=8080
- とりあえず、動作する環境を作ってみてください。(そのあと設定を変更し、理解をしてください)
- traefikの各entrypointsごとの設定を行っています。
- http は https へリダイレクトを行っています。
-
Host(`apptest.local\`)
は各アプリ環境のドメインを記載してください - 「traefik.http.routers.test-app-test」の「test-app-test」は「services:」直下の「test-app-test:」と一致する必要があります。
※「test-app-test:」で使用できない文字は使用できません。
※「.(ドット)」も使用しない方が良いかと思います。(何かしら手を加えれば設定できるかもしれませんが、私は確認をしていません) - httpsでアクセスがあるならば「.tls=true」は記載をしてください
- サーバ側のポートは「.loadbalancer.server.port」で設定します
■動作確認サンプル一式
「/tmp/test」に下記のファイルを配置してください。
- traefik.yml
- docker-compose.yml(共通の定義ファイル)
- docker-compose-base.yml(アプリケーション用のベースの定義ファイル)
- docker-compose-app.yml(アプリケーションの個別の定義ファイル)
traefik.yml
# Providers config
providers:
docker: {} # Docker との連携を有効
# API/Dashboard config
api:
insecure: true # WebUI にアクセスできるように設定
entryPoints:
web:
address: ":80"
secure:
address: ":443"
nodejs:
address: ":8888"
certificatesResolvers:
default:
acme:
email: test@local.test
storage: acme.json
httpChallenge:
entryPoint: web
docker-compose.yml
version: '3.7'
services:
traefik:
image: traefik
container_name: traefik
restart: "always"
ports:
- "80:80"
- "443:443"
- "8888:8888"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /tmp/test/traefik.yml:/etc/traefik/traefik.yml:ro
networks:
- test-network
db:
image: mysql:5.7.12
container_name: db
environment:
MYSQL_ROOT_PASSWORD: root
networks:
- test-network
networks:
test-network:
external: true
docker-compose-base.yml
version: '3.7'
services:
app-#SERVICE_NAME#:
container_name: app-${SERVICE_NAME}
privileged: true
networks:
- test-network
labels:
- traefik.enable=true
- traefik.docker.network=docker-network
- traefik.http.middlewares.app-https-redirect.redirectscheme.scheme=https
- traefik.http.routers.app-${SERVICE_NAME}.rule=Host(`${SERVICE_DOMAIN}`)
- traefik.http.routers.app-${SERVICE_NAME}.entrypoints=web
- traefik.http.routers.app-${SERVICE_NAME}.middlewares=app-https-redirect
- traefik.http.routers.app-${SERVICE_NAME}-secure.rule=Host(`${SERVICE_DOMAIN}`)
- traefik.http.routers.app-${SERVICE_NAME}-secure.entrypoints=secure
- traefik.http.routers.app-${SERVICE_NAME}-secure.tls=true
- traefik.http.routers.app-${SERVICE_NAME}-secure.service=app-${SERVICE_NAME}-secure-service
- traefik.http.services.app-${SERVICE_NAME}-secure-service.loadbalancer.server.port=80
- traefik.http.routers.app-${SERVICE_NAME}-nodejs.rule=Host(`${SERVICE_DOMAIN}`)
- traefik.http.routers.app-${SERVICE_NAME}-nodejs.entrypoints=nodejs
- traefik.http.routers.app-${SERVICE_NAME}-nodejs.tls=true
- traefik.http.routers.app-${SERVICE_NAME}-nodejs.service=app-${SERVICE_NAME}-nodejs-service
- traefik.http.services.app-${SERVICE_NAME}-nodejs-service.loadbalancer.server.port=8888
networks:
test-network:
external: true
docker-compose-app.yml
version: '3.7'
services:
app-#SERVICE_NAME#:
#簡単なサンプル用です
image: httpd:alpine
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
上記のファイルを配置後、下記コマンドを実行していきます
# ymlファイルに定義しているネットワークを作成します。
# 必要に応じて、NAT用などを作成してください
docker network create test-network
# 共通定義のコンテナを作成します
# ※traefikのentryPointsのポートは開放しておくこと
docker-compose -f docker-compose.yml up -d --build
#### アプリケーションコンテナを作成(一つ目)
# 同じ定義で複数のアプリケーションを追加していく想定の為、変数で定義します
SERVICE_NAME=test1
SERVICE_DOMAIN=${SERVICE_NAME}.local.host
# sedで置き換えているのは、環境変数が使用できない部分を変更するためです
# この部分はアプリケーションコンテナのビルドで共通の処理を想定しています
sed -e "s/#SERVICE_NAME#/${SERVICE_NAME}/g" docker-compose-base.yml > base.yml \
&& sed -e "s/#SERVICE_NAME#/${SERVICE_NAME}/g" docker-compose-app.yml > app.yml \
&& export SERVICE_NAME=${SERVICE_NAME} \
&& export SERVICE_DOMAIN=${SERVICE_DOMAIN} \
&& docker-compose -f base.yml -f app.yml up -d --build
#### アプリケーションコンテナを作成(二つ目)
SERVICE_NAME=test2
SERVICE_DOMAIN=${SERVICE_NAME}.local.host
sed -e "s/#SERVICE_NAME#/${SERVICE_NAME}/g" docker-compose-base.yml > base.yml \
&& sed -e "s/#SERVICE_NAME#/${SERVICE_NAME}/g" docker-compose-app.yml > app.yml \
&& export SERVICE_NAME=${SERVICE_NAME} \
&& export SERVICE_DOMAIN=${SERVICE_DOMAIN} \
&& docker-compose -f base.yml -f app.yml up -d --build
上記のコマンドを実行すればアプリケーションのコンテナが二つ立ち上がっている状態になります。
次はアクセスを行い、確認します。
# ローカルdocker環境にドメインでアクセスする為、hostsに記載をします
192.168.1.10 test1.local.host
192.168.1.10 test2.local.host
# アクセスする為のURLは下記になります。
https://test1.local.host/
https://test2.local.host/
私はコマンドの部分のshellを用意して使用しています。
実際に自身の環境作成に組み込むと処理は多くなると思いますが、とりあえずのサンプルになりますので、、、
■関連記事
※動作させるため、stackoverflow等の多くサイトを参考にさせて頂いています