okinawa

IT勉強メモ

DockerでJava・Apatche・Tomcat・MySQL環境を構築

構成図

参考サイト

ここらへんのサイトを眺めながら作業すると理解度が高まる。

Apache(httpd)とTomcatの連携
ApacheTomcatはhttpではなく、AJPというプロトコルで通信する
Apache httpd と Tomcat を連携させる方法 |
エーフロンティア|ApacheへのHTTPリクエストをTomcatに転送する
Dockerコンテナ(Apache+Tomcat)の設定ファイルを作成

TomcatMySQLの接続
Tomcat 8.0系でのデータソース定義 - 俄
Apache Tomcat 8 (8.0.53) - JNDI Datasource HOW-TO

・Dockerのnetworkを固定IPで作成
docker-compose 固定IPアドレスを指定

Dockerのネットワーク、基礎理解は万全ですか?【Dockerコンテナ・グレートジャーニー④】 #Docker - Qiita

大まかな流れ

Apache(httpd)とTomcatの連携
httpd.confを編集してAJPを有効にする。
Tomcatのserver.xmlを編集してAJPを有効&HTTPを無効にする。

TomcatMySQLの接続
JDBCTomcatに配置&context.xmlを編集してDB接続を有効にする。

・docker-compose.yml&Dockerfile作成

・テスト用のJavaプログラム作成

・docker compose実行で終了

Apache(httpd)とTomcatの連携

  1. httpdTomcatAJPで通信できるようにするため、設定ファイルに変更を加える。
  2. 変更後の設定ファイルをホストマシンにコピーする(docker composeで変更後の設定ファイルでコンテナを作るため)

httpdの設定ファイル変更
設定ファイルはhttpdコンテナの下記にある。
/usr/local/apache2/conf/httpd.conf

httpd.confに下記の変更を加えてAJPを有効にする&Tomcatの所在を伝える

# 下記2行を探してコメントアウトを解除。AJPを有効にする。
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

# 2行を追加。場所はどこでもOK。httpdへのアクセス全てをTomcatへ転送する。
ProxyPass / ajp://172.30.0.3 # Tomcatのパス。別サーバならIPアドレス。
ProxyPassReverse / ajp://172.30.0.3 #Tomcatのパス。別サーバならIPアドレス。

変更が終わったら、httpd.confをコピーしてホストマシンの下記に配置。(後でhttpdコンテナにコピーする用)
C:\Users\username\Documents\dockertest\apa\httpd.conf

Tomcatの設定ファイル
設定ファイルはTomcatコンテナの下記にある。
/usr/local/Tomcat/conf/server.xml

<!-- 下記の行をコメントアウト解除&編集 -->
    <!--
    <Connector protocol="AJP/1.3"
               address="::1"
               port="8009"
               redirectPort="8443"
               maxParameterCount="1000"
               />
    -->

↓編集後

    <Connector protocol="AJP/1.3"
               address="0.0.0.0"
               port="8009"
               redirectPort="8443"
               secretRequired="false"
               maxParameterCount="1000"
               />

server.xmlの変更点2↓

<!-- 下記の行を探してコメントアウトする。HTTP通信は使わないので -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               maxParameterCount="1000"
               />

変更が終わったら、server.xmlをコピーしてホストマシンの下記に配置。(後でTomcatコンテナにコピーする用)
C:\Users\username\Documents\dockertest\tomcat\server.xml

TomcatMySQLの接続

MySQLJDBC配置とTomcat設定ファイルの変更が必要。

JDBC配置
1,MySQL :: MySQL コネクタからダウンロード。JDBC Driver for MySQLのPlatform Independentを選択する。

2,ダウンロードしたらJDBCのjarファイルを下記に配置する。(後でTomcatコンテナにコピーする用)
C:\Users\username\Documents\dockertest\tomcat\mysql-connector-j-8.2.0.jar

・Tomcaとの設定ファイル変更
変更する設定ファイルはTomcatコンテナの下記にある。
/usr/local/Tomcat/conf/context.xml

<!-- 下記を追加する -->
 <Resource name="jdbc/MyDB" auth="Container"
          type="javax.sql.DataSource"
          maxTotal="100" maxIdle="30" maxWaitMillis="10000"
          username="root" password="rootpass"
          driverClassName="com.mysql.cj.jdbc.Driver"
          url="jdbc:mysql:172.30.0.4:3306/test?allowPublicKeyRetrieval=true&useSSL=false"/>
     <!-- url="jdbc:mysql:MySQLのパス。別サーバーならIP:ポート番号/DB名 -->

変更したらcontext.xmlをコピーして、ホストマシンの下記に配置する。(後でTomcatコンテナにコピーする用)
C:\Users\username\Documents\dockertest\tomcat\context.xml

Dockerイメージ・コンテナ用のファイル作成

作業は、イメージ作成のためにDockerfile作成と、コンテナ作成のためにdocker-compose.ymlを作成する。

docker-compose.ymlの作成

ファイル名は必ずdocker-compose.ymlで作成する。

ホストマシンの下記に配置する。
C:\Users\username\Documents\dockertest\docker-compose.yml

version: '3'
services:
#コンテナ名。apacheのコンテナ
  apachetest:
#Dockerfileからイメージ作成。パスはdocker-compose.ymlからの相対パス
    build: ./apa
#Docker内の仮想ネットワーク名。LANを作るイメージ
    networks:
      apatommynet:
        ipv4_address: 172.30.0.2
# ホストマシンからコンテナへの接続ポート指定。ホストの8080に接続があったらコンテナの80に接続する
    ports:
      - 8080:80
  tomcattest:
    build: ./tomcat
    networks:
      apatommynet:
        ipv4_address: 172.30.0.3
# ホストマシンの保存領域とコンテナの保存領域を同期する。ホストのwebappsフォルダとコンテナのwebappsフォルダを同期
    volumes:
      - C:\Users\username\Documents\dockertest\tomcat\webapps:/usr/local/tomcat/webapps
  mysqltest:
    image: mysql
    networks:
      apatommynet:
        ipv4_address: 172.30.0.4
    volumes:
      - mysqlvolume01:/var/lib/mysql
# 環境変数の指定
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: testdb
      MYSQL_USER: user
      MYSQL_PASSWORD: userpass
# ネットワーク作成
networks:
  apatommynet:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.30.0.0/16
          gateway: 172.30.0.1

# ボリューム作成
volumes:
  mysqlvolume01:

※追記:ApacheTomcatMySQLと通信するから固定IPにしたが、コンテナ名でもコンテナ間通信はできるのかも?

コンテナ間通信については下記が参考になる。
qiita.com

Dockerfileの作成

Dockerfileは拡張子なしで「Dcokerfile」で作成する。

Dckerfileを元にイメージが作られる。

Apachehttpd)用

# ベースとなるイメージ
FROM httpd

# ローカルのhttpd.confファイルをコンテナの/usr/local/apache2/conf/へコピー
COPY httpd.conf /usr/local/apache2/conf/

作成後、下記に配置する。
C:\Users\username\Documents\dockertest\apa\Dockerfile

Tomcat

# ベースとなるイメージ tomcatのバージョン9。バージョンはwarファイルと合わせる
FROM tomcat:9

# ローカルのserver.xmlファイルをコンテナの/usr/local/tomcat/conf/へ上書きコピー
COPY server.xml /usr/local/tomcat/conf/
COPY context.xml /usr/local/tomcat/conf/
COPY mysql-connector-j-8.2.0.jar /usr/local/tomcat/lib

tomcatのバージョンについて
Eclipseでwarファイルをエクスポートするときに、下記の画面が出るので、Tomcatコンテナのバージョンはここと合わせる。

Eclipseエクスポート

作成後、下記に配置する。
C:\Users\username\Documents\dockertest\tomcat\Dockerfile

Javaプロジェクト作成

Eclise

TestTest.java

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class TestTest
 */
@WebServlet("/TestTest")
public class TestTest extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
    * @see HttpServlet#HttpServlet()
    */
    public TestTest() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
    * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String result = "";
        try (Connection con = DriverManager.getConnection(
                "jdbc:mysql://172.30.04:3306/testdb?allowPublicKeyRetrieval=true&useSSL=false",
                "root",
                "rootpass");
             PreparedStatement pstmt = con.prepareStatement("SELECT * FROM sys.sys_config;");
             ResultSet rs = pstmt.executeQuery()) {
            // 検索結果を表示
            while (rs.next()) {
                result = rs.getString("variable");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        request.setAttribute("message", result);

        RequestDispatcher dispatcher = request.getRequestDispatcher("/jsp/index.jsp");
        dispatcher.forward(request, response);
    }

    /**
    * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
Hello!World!
 <h1>メッセージ: <%= request.getAttribute("message") %></h1>
</body>
</html>

docker compose実行

下記コマンドを実行。

docker compose -f C:\Users\username\Documents\dockertest\docker-compose.yml up -d

実行後、warファイルを作成して下記に配置する。
C:\Users\username\Documents\dockertest\tomcat\webapps\ApatcheTomcatTest.war

しばらくすると自動でコンパイルされて、クラスファイル等が作られる。

そしたら「http://localhost:8080/ApatcheTomcatTest/TestTest」にアクセス。

この画面が出たら成功↓メッセージ:の後にSELECT結果が表示される。