DockerでApacheとTomcat環境構築。ついでにMaven&Java連携

# 概要
Javaでwebアプリ作りたくなったので、ローカル環境をごちゃごちゃやってみるぞ！！
IDEに依存したくないのでコマンドべースで環境ができるように頑張るぞ(っ・Д・)っ

# できあがる環境
- macOS Sierra 10.12.6
- Docker version 17.09.0-ce
- Apache 2.4.6
- Tomcat9.0.1
- Maven 3.5.0
- Java 8

# Docker環境を構築
それぞれコンテナを作成して最後にdocker-compose.ymlでくっつける。とりあえず最低限動くものを作って今後カスタマイズしていきたい！
## Apacheコンテナ作成
個人的にapache on centos勉強したいのでインストールしてイメージ作成

```:Dockerfile
FROM centos:7

RUN yum -y update && yum clean all
RUN yum -y install httpd httpd-devel gcc* make && yum clean all

# mod_jk conf files
ADD httpd-proxy.conf /etc/httpd/conf.d/

# Simple startup script to avoid some issues observed with container restart 
ADD run-httpd.sh /run-httpd.sh
RUN chmod -v +x /run-httpd.sh

CMD ["/run-httpd.sh"]
```

```:httpd-proxy.conf
# forward to tomcat container
ProxyPass / ajp://tomcat:8009/
```

```:run-httpd.sh
#!/bin/bash

# Make sure we're not confused by old, incompletely-shutdown httpd
# context after restarting the container.  httpd won't start correctly
# if it thinks it is already running.
rm -rf /run/httpd/* /tmp/httpd*

exec /usr/sbin/apachectl -DFOREGROUND
```

## Tomcatコンテナ作成

```:Dockerfile
FROM tomcat:9.0.1-alpine

MAINTAINER Uchiyama <shintaro.0112@gmail.com>

ADD tomcat-users.xml /usr/local/tomcat/conf/
ADD context.xml /usr/local/tomcat/webapps/manager/META-INF/context.xml

RUN rm -rf /usr/local/tomcat/webapps/ROOT

CMD ["catalina.sh", "run"]
```

```:tomcat-users.xml
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="manager-script"/>
  <user username="manager" password="manager!" roles="manager-script"/>
</tomcat-users>
```

tomcat managerをhost名localhost以外で動かせるようにするため。詳細は[このstackOverFlow](https://stackoverflow.com/questions/38551166/403-access-denied-on-tomcat-8-manager-app-without-prompting-for-user-password)参照

```:context.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<Context antiResourceLocking="false" privileged="true" >
<!--
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
-->
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>
```

## docker-composeで連携

```:docker-compose.yml
version: '3'
services:
  httpd:
    container_name: httpd-container
    build: ./docker/httpd
    ports:
      - "80:80"
  tomcat:
    container_name: tomcat-container
    build: ./docker/tomcat
    expose:
      - "8009"
volumes:
  data: {}
```

## 動かしてみる

```zsh:zsh
docker-compose up -d --build
docker-compose ps
```

コンテナが立ち上がったことを確認して以下URLをクリックしてtomcatのhomeページが見れればOK!
http://localhost/

なんだか動かなかったらhttpdやtomcatコンテナのアクセスログを見てどこまでたどり着いてるか確認してみる。

```:zash
docker exec -it httpd-container tail -f /etc/httpd/logs/access_log
docker exec -it tomcat-container1 tail -f /usr/local/tomcat/logs/localhost_access_log.`date +%Y-%m-%d`.log
```

# MavenによりJavaアプリケーションを作成
## Mavenをインストール
```bash:zsh
brew install maven
mvn -v
```

## Mavenでプロジェクト（雛形）作成

```bash:zsh
mvn archetype:generate \ # プロジェクト作成
-DgroupId=tech.ucwork \ # パッケージ名指定
-DartifactId=myapp \ # アプリケーション名指定
-DarchetypeArtifactId=maven-archetype-webapp # 初期のアプリ形式指定（web）
-DinteractiveMode=false #インタラクティブ形式で実行しない
```

## JavaでHelloWorld表示
### ディレクトリ構成
どのサイト参考にしたか忘れちゃったがこんな感じのファイル作っていく

```bash:zsh
$ tree -NL 5 src                                                                                                                     +[master]
src
└── main
    ├── java
    │   └── tech
    │       └── ucwork
    │           └── HelloServlet.java
    ├── resources
    │   └── log4j.properties
    └── webapp
        ├── WEB-INF
        │   └── web.xml
        └── index.jsp

7 directories, 4 files
```

### javaファイル

```:HelloServlet.java
package tech.ucwork;

import java.io.IOException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static Logger log = LoggerFactory.getLogger(HelloServlet.class);
	
    public HelloServlet() {
    }
    
    @Override
    public void init() {
    	log.debug("servlet init...");
    }

    @Override
  	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	log.debug("servlet service...");
      PrintWriter out = response.getWriter();
	  	out.println("hello5");
  	}
}
```

```:log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %5p %c{1} - %m%n

log4j.rootLogger=debug, stdout
```

## Mavenでビルド＆パッケージング
pom.xmlをこんな感じにしてコマンド実行や！

```:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>tech.ucwork</groupId>
  <artifactId>myapp</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>myapp Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.6</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.7</version>
        <scope>test</scope>
    </dependency>
    <dependency> 
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.12</version>
    </dependency>
  </dependencies>
  <build>
    <!-- mavenでコンパイルするたｍのプラグイン -->
    <finalName>${project.artifactId}-${project.version}</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <encoding>UTF-8</encoding>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <!-- mavenからtomcatにwarファイル展開するためのプラグイン -->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <path>/app</path><!-- webapps配下に展開するためのファイル（ディレクトリ名） -->
          <server>tomcat-localhost</server>
          <url>http://localhost/manager/text</url>
        </configuration>
      </plugin>
    </plugins>
  </build> 
</project>
```

```:zsh
mvn clean package
```

## Tomcatにデプロイ
### MavenでTomcatにdeployする
~~[このサイト](https://qiita.com/gishi_yama/items/32d811cbb10d50912fc3)を参考に実現。~~

~~相当壁にぶつかったが[このstackOverFlow](https://stackoverflow.com/questions/38551166/403-access-denied-on-tomcat-8-manager-app-without-prompting-for-user-password)で解決~~

### warファイルをTomcatにデプロイ
よくよく考えたら以下理由でmaven使うよりもっと簡単に実現できた
（あんなに悩んだのに・・・・）
1. tomcat複数構成にした時http経由のmanager機能デプロイするとtomcat全台数に投げる方法がわかんない
2. そもそもブラウザ経由でデプロイできちゃうのってどうなの。basic認証的な物はあるけど
3. {TOMCAT_HOME}/webapps/配下にwarファイルつければデプロイ出来た説

```:zsh
mvn clean package
docker cp target/myapp-1.0-SNAPSHOT.war tomcat-container:/usr/local/tomcat/webapps/app.war
```

参考）[Mavenの基本](http://www.techscore.com/tech/Java/ApacheJakarta/Maven/5/)

# TODO
## Tomcat初期設定関連（既存ファイルの削除＆ログ等の設定）
[このサイトを参考に設定したい](https://qiita.com/hidekatsu-izuno/items/ab604b6c764b5b5a86ed)

## ApacheとTomcatのクラスタ構成における負荷分散＆セッション管理
[ここを参考に設定したい](http://ozuma.o.oo7.jp/works/code/tomcat_cluster/)

## Tomcatの各種設定チューニング
[各種設定ファイルの基本](http://www.searchman.info/java_eclipse/1030.html)
[詳細な設定](http://www.atmarkit.co.jp/ait/articles/0711/20/news125.html)
[スレッドプールの詳細](https://codezine.jp/article/detail/781)

##