LoginSignup
4
7

More than 5 years have passed since last update.

Oracle 11 g + Spring boot を Vagrant + Docker compose で試してみたメモ

Posted at

やること

docker で javaのフレームワークの動作環境を試してみる。

動作環境

  • windows10
  • vagrant2.1.1
  • virtualbox5.2.14
  • ubuntu-18.04
  • Docker version 18.05.0-ce, build f150324
  • docker-compose version 1.21.2, build a133471

ディレクトリ構造

project
  + bin   # コマンド覚書用のシェルスクリプト
  + data  # dockerの永続化用ディレクトリ
  - docker
    - gradle
      - Dockerfile
    - oracle
      - 11.2.0.2
        - Checksum.xe
        - Dockerfile.xe
        - checkDBStatus.sh
        - rnOracle.sh
        - setPasword.sh
        - xe.rsp
        - oracle-xe-11.2.0-1.0.x86_64.rpm.zip # Oracleからダウンロードしたもの。.gitignoreで無視
      - buildDockerImage.sh
    - spring
      - Dockerfile
    - .env # docker-composer.yml で使用する環境変数設定
    - docker-compose.yml
  - src
    - hello # spring initializerで作成されたものをひながたに改変
      - build.gradle
      - settings.gradle
      - lib
        - ojdbc7.jar  # Oracleからダウンロードしたもの。.gitignoreで無視
      - src
        - main
          - java
            - hello
              - hello
                - model
                  - Staff.java
                - repository
                  - StaffRepository.java
                - HelloApplication.java
          - resouces
            - application.yml
        + test

設定ファイル

docker/.env
ORACLE_PWD=MY_DB_PASSWORD
USER_PASS=MY_DB_USER_PASSWORD
docker/docker-compose.yml
version: '3'
services:
  dbserver:
    build:
      context: ./oracle/11.2.0.2/
      dockerfile: Dockerfile.xe
    volumes:
      - ../data/database:/u01/app/oracle/oradata
      - ./oracle/startup:/docker-entrypoint-initdb.d/startup
    ports:
      - 1521:1521
      - 8085:8080
    env_file: .env
    environment:
      - TZ=`ls -la /etc/localtime | cut -d/ -f8-9`
    shm_size: 1g
    restart: unless-stopped

  gradle:
    build: ./gradle
    user: gradle
    volumes:
      - ../src/hello:/app
      - cache1:/home/gradle/.gradle
    links:
      - dbserver
    environment:
      - TZ=`ls -la /etc/localtime | cut -d/ -f8-9`
    command: [echo, "no work"]

  spring:
    build: ./spring
    ports:
        - "8080:8080"
    volumes:
        - ../src/hello:/app
    links:
      - dbserver
    environment:
      - TZ=`ls -la /etc/localtime | cut -d/ -f8-9`
    command: [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app/build/libs/hello-0.0.1-SNAPSHOT.jar"]

volumes:
  cache1: 

データベースの準備

DockerでOracleデータベース11g XEを構築を参考にデータベースを設定した。
oracle/docker-images の 11.2.0.2ディレクトリをコピー。
同じディレクトリにoracle-xe-11.2.0-1.0.x86_64.rpm.zipのlinux版を配置。
また、javaからDBにつなげるためのojdbc7ドライバーをダウンロードしておく。

githubからcloneするもの

  • oracle/docker-imagesの OracleDatabase/SingleInstance/dockerfiles/11.2.0.2ディレクトリ
    • docker/oracle/11.2.0.2に配置

Oracleからダウンロードするもの

  • oracle-xe-11.2.0-1.0.x86_64.rpm.zip
    • docker/oracle/11.2.0.2/oracle-xe-11.2.0-1.0.x86_64.rpm.zipに配置
  • ojdbc7.jar
    • src/hello/lib/ojdbc7.jar に配置

データベース起動

docker-compose up -d dbserver

sqlplusでの接続

データベースを立ち上げた状態でないと接続できない。
かならず、docker-compose upした後に行うこと。

bin/sqlplus.sh
#!/bin/bash

bin_dir=$(cd $(dirname $0) && pwd)
container_name=dbserver

# 環境変数読み込み
. $bin_dir/../docker/.env

cd $bin_dir/../docker && docker-compose exec $container_name sqlplus sys/$ORACLE_PWD@localhost:1521/XE as sysdba

シェルを実行して接続を試みる。

vagrant@vagrant[master]:/vagrant/tutorial/lesson/spring$ ./bin/sqlplus.sh

立ち上がっていない状態でアクセスすると以下のようなエラーがでる。

7df144c6f135        docker_dbserver              "/bin/sh -c 'exec $O…"   19 seconds ago      Up 18 seconds (health: start
ing)   0.0.0.0:1521->1521/tcp, 0.0.0.0:8085->8080/tcp   docker_dbserver_1
WARNING: The JAVA_OPTS variable is not set. Defaulting to a blank string.

SQL*Plus: Release 11.2.0.2.0 Production on Sun Jul 15 15:08:51 2018

Copyright (c) 1982, 2011, Oracle.  All rights reserved.

ERROR:
ORA-12528: TNS:listener: all appropriate instances are blocking new connections

Enterを2回押して一旦終了させる。

Enter user-name:
ERROR:
ORA-12547: TNS:lost contact


Enter user-name:
ERROR:
ORA-12547: TNS:lost contact


SP2-0157: unable to CONNECT to ORACLE after 3 attempts, exiting SQL*Plus

もう一度sqlplusでの接続を試みる。

vagrant@vagrant[master]:/vagrant/tutorial/lesson/spring$ ./bin/sqlplus.sh
7df144c6f135        docker_dbserver              "/bin/sh -c 'exec $O…"   25 seconds ago      Up 23 seconds (health: start
ing)   0.0.0.0:1521->1521/tcp, 0.0.0.0:8085->8080/tcp   docker_dbserver_1
WARNING: The JAVA_OPTS variable is not set. Defaulting to a blank string.

SQL*Plus: Release 11.2.0.2.0 Production on Sun Jul 15 15:08:55 2018

Copyright (c) 1982, 2011, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL> 

sqlplusの立ち上げ方が悪いのだろうか?
もしうまい方法知っているかたがいれば教えていただけると助かります。

ユーザの準備

sqlplusでつなぐことができたら、javaから接続するためのユーザの作成を行う。
今回は起動してみるテストだけで公開しないのですべての権限を持つユーザを作成。

CREATE TABLESPACE my_data DATAFILE '/u01/app/oracle/oradata/MY_DATA.dbf' SIZE 200M  SEGMENT SPACE MANAGEMENT AUTO;
CREATE USER testuser IDENTIFIED BY "my_pass" DEFAULT TABLESPACE my_data TEMPORARY TABLESPACE temp;
GRANT DBA TO testuser ;
quit;

※ここで設定したmy_passはdocker/.envのMY_DB_USER_PASSWORDのこと。

一旦ログアウトしたら、作成したユーザでの接続を試みる。

bin/sqlplus.sh
#!/bin/bash

bin_dir=$(cd $(dirname $0) && pwd)
container_name=dbserver
. $bin_dir/../docker/.env
cd $bin_dir/../docker && docker-compose exec $container_name sqlplus testuser/$USER_PASS@localhost:1521/XE

テスト用のテーブルの作成

create table STAFF (
    EMP_ID     number primary key,
    STAFF_NAME varchar2(100)
);
insert into STAFF (EMP_ID, STAFF_NAME) values (1, 'Jasmine');

ビルドツールとソース

ビルドツールのdockerファイル

docker/gradle/Dockerfile
FROM gradle:4.8.1-jdk8
WORKDIR /app

ソースの準備

Dockerで始めるSpring Bootを参考に、Spring Initializerを使ってプロジェクトを作成。srcフォルダ以下に配置する。
今回はDBと接続したいため、DBに関する設定を追記。

設定ファイル

src/hello/build.gradle
buildscript {
    ext {
        springBootVersion = '2.0.3.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
  compile('org.springframework.boot:spring-boot-starter-web')
  compile('org.springframework.boot:spring-boot-starter-data-jpa')
  compile files('lib/ojdbc7.jar')
  testCompile('org.springframework.boot:spring-boot-starter-test')
}
src/hello/src/main/resouce/applicatin.yaml
spring:
  datasource:
    url: jdbc:oracle:thin:@//dbserver:1521/XE
    username: testuser
    password: pass
    driverClassName: oracle.jdbc.driver.OracleDriver
    testWhileIdle: true
    validationQuery: SELECT 1
  jpa:
    showSql: true
    hibernate:
      ddlAuto: create-drop
      naming:
        implicitStrategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
        physicalStrategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
    properties:
      hibernate:
        dialect: org.hibernate.dialect.Oracle10gDialect

プログラム

src/hello/src/main/java/hello/hello/model/Staff.java
package hello.hello.model;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Column;

@Table(name="staff")
@Entity
public class Staff {

  @Id 
  @Column(name="emp_id")
  private long id;

  @Column(name="staff_name")
  private String name;

  public void setId(long id){
    this.id = id;
  }
  public long getId(){
    return this.id;
  }

  public void setName(String  name){
    this.name = name;
  }

  public String getName(){
    return this.name;
  }
}
src/hello/src/main/java/hello/hello/repository/StaffRepository.java
package hello.hello.repository;

import java.util.Optional;
import org.springframework.data.repository.CrudRepository;

import hello.hello.model.Staff;

public interface StaffRepository extends CrudRepository<Staff, Long> {
  Optional<Staff> findById(long id);
}
src/hello/src/main/java/hello/hello/HelloApplication.java
package hello.hello;

import java.util.Optional;
import java.util.Collections;
import java.util.Map;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import hello.hello.model.Staff;
import hello.hello.repository.StaffRepository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@SpringBootApplication
@RestController
public class HelloApplication {
  @Autowired StaffRepository repository;

  @PersistenceContext
  private EntityManager entityManager;

  @RequestMapping("/")
  public String home() {
      return "Hello World from Docker";
  }
  @RequestMapping("/staff")
  public String staff() {
      Optional<Staff> optional =  repository.findById(1);
      Staff staff = optional.orElseGet(() -> new Staff());
      return "Hello " + staff.getName();
  }

  @RequestMapping("/query")
  public String query() {
      List<Staff> results = entityManager
            .createNativeQuery("select * from staff where emp_id = :id ", Staff.class)
            .setParameter("id",1)
            .getResultList();
      String name = "";

      if(results.size() != 0){
        name = results.get(0).getName();
      }
      return "Hello " + name;
  }
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

ビルドの実行

bin/clean-build.sh
#!/bin/bash

# このシェルスクリプトのディレクトリの絶対パスを取得。
bin_dir=$(cd $(dirname $0) && pwd)
container_name=gradle
cd $bin_dir/../docker && docker-compose run $container_name  gradle clean build

起動

docker/spring/Dockerfile
FROM openjdk:jdk-alpine
WORKDIR /app
ENV JAVA_OPTS=""
bin/up.sh
#!/bin/bash

# このシェルスクリプトのディレクトリの絶対パスを取得。
bin_dir=$(cd $(dirname $0) && pwd)

composeFile=${1:-"docker-compose.yml"}
cd $bin_dir/../docker && docker-compose -f $composeFile up $@

./bin/up.shで起動。

http://<仮想環境のIP>:8080/にブラウザでアクセスして表示を確認。

この時点でのソース

参考

DockerでOracleデータベース11g XEを構築
dockerでOracle DB 11gを動かす
Dockerで始めるSpring Boot
表領域
oracle spring sample
auto increment
SpringBootの開発環境をdockerでつくる
sample
Spring Data JPA でのクエリー実装方法まとめ
【JavaEE】今からでも間にあうJPA入門
初めてのJPA--シンプルで使いやすい、Java EEのデータ永続化機能の基本を学ぶ
Invalid number format for port number
Gradle使い方メモ
Dockerで- /etc/localtime:/etc/localtime:ro がMount Deniedを出すやつ
docker-compose
oracleでautoincrement

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7