ローカル開発環境(apache/tomcat)をコンテナ化+SSL化
ローカルのapache+tomcatで動いているアプリケーションをdockerに乗っけてみました。 SSL込みで設定していきました。Docker for Macを使用しています。
成果物をこちらのリポジトリにあげておきます。
Apache
ApacheでVirtualHostで3つのFQDNの通信を扱うようにしていきます。SSLの設定も行っていきますが、その際にはmkcertを使用してローカル認証局と鍵の作成を行います。
httpd.confの作成
SSL通信を有効にするため、conf/httpd.confをベースのdockerイメージからコピーしてきて変更を加えていきます。以下の項目のコメントアウトを外します。
#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so ... #LoadModule ssl_module modules/mod_ssl.so ... #Include conf/extra/httpd-ssl.conf
今回はVirtualHosts+Proxy Moduleを使っていきたいと思うので下記のコメントアウトも外します。tomcatへの通信をhttpで行うために必要なモジュールもついでに外します。
#Include conf/extra/httpd-vhosts.conf ... #LoadModule proxy_module modules/mod_proxy.so ... #LoadModule proxy_http_module modules/mod_proxy_http.so
各VirtualHostsで共有の鍵を使いたいので、httpd-ssl.confに鍵の設定をして、httpd-vhosts.confの設定がhttpd-ssl.confより後にくるように記述の位置を変えます。下記のようになるはずです。
... # Secure (SSL/TLS) connections Include conf/extra/httpd-ssl.conf # Virtual hosts Include conf/extra/httpd-vhosts.conf ...
鍵の作成
mkcertを使って認証局+鍵の作成を行っていきます。Goで作られているらしいので興味ある方はぜひ。
brew install mkcert brew install nss # Firefoxでアクセスする際には必要のようです mkcert -install # ローカル認証局作成 Macの方はキーチェーンアクセスを見ると出来ているのが分かる mkcert localhost "*.example.com " "*.cool.com" # generateされた下記のファイル2つをdockerコンテキストに配置
httpd-ssl.confの設定
httpd-ssl.confの下記をコメントアウトします。今回は先程生成した2つのpemファイルを利用するためです。
SSLCertificateFile "/usr/local/apache2/conf/server.crt" ... SSLCertificateKeyFile "/usr/local/apache2/conf/server.key"
そして下記のように記述を加えます。
SSLCertificateFile "/usr/local/apache2/conf/localhost+2.pem" # 後ほどDockerfileでCOPYするように宣言します SSLCertificateKeyFile "/usr/local/apache2/conf/localhost+2-key.pem"
httpd-vhosts.confの設定
tomcatのコンテナへajpで通信するように設定を加えます。 通常は静的ファイルはDocumentRoot配下を参照させて、それ以外はtomcatと通信という形になるかと思いますが、今回はとりあえず全部tomcatコンテナに流します。 下記のような形としました。VirtualHostのセクション内です。
<Directory "/usr/local/apache2/docs/one.cool.com">
Options Indexes
Require all granted
</Directory>
<Location /todolist>
ProxyPass http://app:8080/todolist/
</Location>
/private/etc/hostsに今回設定したFQDNを追加
本題とは関係ないですが自分のPCからアクセスできるように、/private/etc/hosts
に記述しておきます。
127.0.0.1 www.example.com 127.0.0.1 one.cool.com 127.0.0.1 two.cool.com
Dockerfileの作成
設定ファイルと鍵、httpのドキュメントをコンテナにCOPYしポート80番と443番をListenします。イメージはなるべく軽くしたいのでDebian系OSがベースのものでなく、alpineベースのものを選んでいます。
FROM httpd:2.4-alpine # copy configuration files COPY --chown=root:www-data conf/httpd.conf /usr/local/apache2/conf COPY --chown=root:www-data conf/extra /usr/local/apache2/conf/extra # copy keys for ssl/tls COPY --chown=root:www-data keys /usr/local/apache2/conf # copy document WORKDIR /usr/local/apache2/docs RUN chown root:www-data /usr/local/apache2/docs COPY --chown=root:www-data docs . EXPOSE 80 443
httpdがうまく動いているかテスト
docker-compose.yamlを作成し、下記のようにhttpdの設定を宣言します。
version: '3' services: web: container_name: httpd build: ./httpd ports: - "9080:80" - "9443:443"
以下のURLにSSLでアクセスできることが確認できました。
- https://www.example.com:9443/
- https://one.cool.com:9443/index.html
- https://two.cool.com:9443/index.html
Tomcat
kotlin + SpringBootで作成した簡単なアプリケーションをコンテナに乗っけてみます。黒べこ本のサンプルに載っているTodoアプリです。
kotlinのアプリケーションの設定を一部変更
最初にkotlinのアプリケーションのbuild.gradle
に変更を加えていきます。今回はwarを作成してそれをデプロイするため、下記のように記述を加えていきます。
apply plugin: 'war' dependencies { providedRuntime("org.springframework.boot:spring-boot-starter-tomcat") // SpringBoot組み込み以外のTomcatを利用するときに必要みたいです }
次に、warファイルをTomcatに展開するにあたって必要らしいServletInitializerというclassをエントリポイントのあるclassと同パッケージに配置します。下記のような内容のclassです。
package com.example.todolist import org.springframework.boot.builder.SpringApplicationBuilder import org.springframework.boot.web.servlet.support.SpringBootServletInitializer class ServletInitializer : SpringBootServletInitializer() { override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder { return application.sources(TodolistApplication::class.java) } }
Dockerfileの作成
Warに固める作業自体はローカルのIntelliJで行います。Dockerコンテキスト配下にソースを置いてそこに成果物を固めて良いのですが、今回は単純にcopyしてコンテキスト配下に盛ってきたいと思います。いちいちその作業をやるのが面倒くさいのでMakefileを作ります。
※ AutoDeployしてDockerで都度都度検証したい場合には、Volumeマウントして動かしたほうが良いとは思います。
build: cp ~/ideaProjects/todolist/build/libs/todolist.war tomcat/build docker-compose up --build run: docker-compose up
makefileに記述したように、warはtomcat/build配下に格納するので、そのwarをdockerの方にcopyするだけです。なのでDockerfileは下記のようになります。tomcat側もイメージは軽くしたいのでalpineを使います。 またSpringBootは環境変数からコンテキストパスを設定できるのでしておきます。SpringBoot1.x系は別の変数名になるらしいので注意です。
FROM tomcat:9.0.16-jre8-alpine ENV SERVER_SERVLET_CONTEXT_PATH /todolist COPY build/todolist.war /usr/local/tomcat/webapps EXPOSE 8080
動作を検証する
docker-comopseに下記を追記し、make build
してみます。[https://one.cool.com:9443/todo]
にアクセスしてみるとアプリケーションの画面が表示されました。
app: container_name: tomcat build: ./tomcat ports: - "8080:8080"
まとめ
アプリケーションをBuildするところからDockerでできるように今度する。マルチステージビルドが使えそう。