プログラミングBlog

docker oracle memo

docker oracle memo

公式Repository clone

git clone https://github.com/oracle/docker-images.git

oracle database 本体 DL

zipファイルが自動で解凍されてしまう場合
faq.cybozu.info

build方法

./buildDockerImage.shの名前が変更されているようなので以下のコマンドとなる。

./buildContainerImage.sh -v 19.3.0 -e -I

memory変更

defaultだとmemoryの不足でエラーとなるため、増やしておく
f:id:Tokuty:20211009081825p:plain

container内の時刻変更

docker exec コンテナ名 date

VScode Remote containerでの時間同期の話とDockerのtimezone設定方法 - プログラミング学習のメモ書き

password変更

docker exec oracle ./setPassword.sh password

ログイン

sqlplus SYSTEM/password@ORCLCDB

参考サイト

qiita.com

WSL2 + Docker Hub 環境作成時のまとめ  

WindowsでDocker環境作成時のまとめ

手順

① WSL2 install
② Docker Hub install

①WSL2

以下のサイトから必要な機能をDownLoadする
docs.microsoft.com

手順 1 - LinuxWindows サブシステムを有効にする
手順 5 - WSL 2 を既定のバージョンとして設定する
手順1から手順5までを行う

②DockerHub

Docoker Hnbを以下のサイトからDownLoad
hub.docker.com

トラブルシューティング

メモリ

  • WSL2のメモリ使用量を変更する
    デフォルトだと6GBのメモリを消費するため、CPU100%超える。。。
    メモリの設定を変更しておく
    zenn.dev

  • 自動起動しないよう変更

①Docker Desktopの歯車マークをクリック
②Start Docker when you log in チェックマークをはずす
③Apply & Restart押下

f:id:Tokuty:20210918185207p:plain

Docker + Gradle + Spring Boot でWarファイル作成後にTomcatにDeproy

①Spring BootをGradleでビルド、Warファイルを作成する
TomcatにWarファイルをDeproyする
前回の続きです
Vscode + Docker + Spring Boot 構築

必要なファイル

以下の記事でアプリを構築しておく
Vscode + Docker + Spring Boot 構築
github.com

以下を確認しておく
ない場合は作成する

ServletInitializer.java

package com.example.demo;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(DemoApplication.class);
    }

}

別のtomcatコンテナにDeproyする場合に必要となる

build.gradle

plugins {
    id 'org.springframework.boot' version '2.5.4'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
    id 'war'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    mavenCentral()
}

war {
    archiveName 'helloworld.war'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()
}

Warファイル作成用のpluginが追加されているかの確認
id 'war'

dependenciesにspring boot に内蔵されているtomcatを使用しない設定が追加されているかの確認
この記述がないとtomcatが多重起動してしまう
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'

手順① Spring BootをGradleでビルド、Warファイルを作成する

  • gradleがinstallされていることの確認

gradle -v

  • tomcatのversionを調べる

Deproy先のtomcatのversionを合わせるため

./gradlew dependencies

9.0.52であることを確認
Deproy先のtomcatのversionを9.0.52とする

+--- org.springframework.boot:spring-boot-starter-tomcat:2.5.4
|    |    +--- jakarta.annotation:jakarta.annotation-api:1.3.5
|    |    +--- org.apache.tomcat.embed:tomcat-embed-core:9.0.52
|    |    +--- org.apache.tomcat.embed:tomcat-embed-el:9.0.52
|    |    \--- org.apache.tomcat.embed:tomcat-embed-websocket:9.0.52
|    |         \--- org.apache.tomcat.embed:tomcat-embed-core:9.0.52
  • build.gradleを修正する

warファイルの名前を変更するため以下を追加

war {
    archiveName 'helloworld.war'
}
  • Warファイルを作成する
    gradle build

build/libs/直下にwarファイルが作成される
build/libs/helloworld.war

手順② TomcatにWarファイルをDeproyする

Deproy先のTomcatサーバーは以下を使用
tokuty.hatenablog.com

  • git clone
git clone git clone https://github.com/TakushiTokuyama/Docker.git

起動するまでは記事を参照

  • WarファイルをDeproyする

さきほど作成したhelloworld.warTomcatwebapps/にコピーして設置する

参考サイト

www.youtube.com

www.it-mure.jp.net

arcanum.hatenablog.com

Vscode + Docker + Gradle + Spring boot 構築

javaの環境をRemote - Containers(Vscode拡張機能)で構築

②Dockerコンテナ内でSpring Bootを構築

前提条件

docker version

構成

vscode + docker + spring の最終的な構成となります。

.
└── demo
    ├── HELP.md
    ├── bin
    │   ├── main
    │   │   ├── application.properties
    │   │   ├── com
    │   │   │   └── example
    │   │   │       └── demo
    │   │   │           ├── DemoApplication.class
    │   │   │           ├── ServletInitializer.class
    │   │   │           └── controller
    │   │   │               └── HelloController.class
    │   │   └── templates
    │   │       └── index.html
    │   └── test
    │       └── com
    │           └── example
    │               └── demo
    │                   └── DemoApplicationTests.class
    ├── build.gradle
    ├── gradle
    │   └── wrapper
    │       ├── gradle-wrapper.jar
    │       └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    ├── settings.gradle
    └── src
        ├── main
        │   ├── java
        │   │   └── com
        │   │       └── example
        │   │           └── demo
        │   │               ├── DemoApplication.java
        │   │               ├── ServletInitializer.java
        │   │               └── controller
        │   │                   └── HelloController.java
        │   └── resources
        │       ├── application.properties
        │       ├── static
        │       └── templates
        │           └── index.html
        └── test
            └── java
                └── com
                    └── example
                        └── demo
                            └── DemoApplicationTests.java

必要なファイル

今回はRemote - Containers(Vscode拡張機能)で環境構築していくため、特に必要なし

手順① Remote-Container

  • Vscodeのコマンドパレット起動

ctrl + shift + p もしくは command + shift + p

  • Remote - containerの機能を使ってjava環境作成

Remote-Containers:Add Development Container Configuration Files選択
f:id:Tokuty:20210911084242p:plain

Java選択
f:id:Tokuty:20210911084308p:plain

11選択
f:id:Tokuty:20210911084425p:plain

16選択
f:id:Tokuty:20210911084436p:plain

Gradleを選択
f:id:Tokuty:20210911084446p:plain

以下のフォルダとファイルが作成される
f:id:Tokuty:20210911092103p:plain

devcontainer.jsonにextensionを追加
"vscjava.vscode-spring-initializr"
spring boot 作成時に使う

 "extensions": [
        "vscjava.vscode-java-pack",
        "vscjava.vscode-spring-initializr"
    ],

右下に表示されたReopen Containerを選択
もしくは右下の緑色の箇所をクリックしReopen Containerを選択
f:id:Tokuty:20210911084457p:plain

左下に下記の表示が出たらコンテナ内にアクセス成功
f:id:Tokuty:20210911084505p:plain

手順② Spring Boot 作成

  • Vscodeのコマンドパレット起動
    ctrl + shift + p もしくは command + shift + p

create java project選択
f:id:Tokuty:20210911085639p:plain

spring boot 選択
f:id:Tokuty:20210911092357p:plain

Gradle Project選択
f:id:Tokuty:20210911092619p:plain

2.5.4選択
f:id:Tokuty:20210911092651p:plain

Java選択
f:id:Tokuty:20210911092711p:plain

ルートパッケージ名 src/main/java直下の名前を選択
f:id:Tokuty:20210911093101p:plain

プロジェクト名
f:id:Tokuty:20210911093158p:plain

今回はWarを選択   
f:id:Tokuty:20210911093220p:plain

11を選択し、開発環境のJava versionと合わせる
f:id:Tokuty:20210911093240p:plain

spring webThymeleaf選択
f:id:Tokuty:20210911093312p:plain

workspaceを作成したい場所を選択
f:id:Tokuty:20210911093402p:plain

openを選択すると作成したプロジェクトを開く
f:id:Tokuty:20210911093430p:plain

以下のフォルダとファイルが作成される
f:id:Tokuty:20210911093529p:plain

  • controllerとviewを追加

以下のパスに追加する
src/main/java/com/example/demo/controller/HelloController.java

HelloController.java

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String index(){
        return "hello";
    }
}

index.html

以下のパスに追加する
src/main/resources/templates/index.html

<html xmlns:th="http://www.thymeleaf.org">

<h1>helloworld</h1>

</html>
  • VscodeにDebug構成を追加する

構成の追加
f:id:Tokuty:20210912115819p:plain

Java
f:id:Tokuty:20210912115840p:plain

launch.json追加
f:id:Tokuty:20210912115853p:plain

  • Spring boot実行

デバッグなしで実行
f:id:Tokuty:20210912115957p:plain

起動
f:id:Tokuty:20210912120021p:plain

http://localhost:8080 にアクセス
f:id:Tokuty:20210912120040p:plain

GiitHub

github.com

次回

次回は
①ビルドツール Gradleを使用して、warファイルを作成
TomcatでwarファイルをDeproyする

Deproy場所は以下を使用
Tomcat + nginx でReverseProxsyServer

参考サイト

blog.kondoumh.com

Vscode + Docker + Nginx + Tomcat でhelloworld

DockerにてNginxとTomcatを構築。
Nginxはリバースプロキシサーバー、 Tomcatアプリケーションサーバーとしてhelloworldを表示させる
今回はNginxコンテナとTomcatコンテナ、二つ作成する

前提条件

  • Vscode上で作成

  • Dockerが使える環境が必要です

  • install 確認コマンド

docker version

構成

docker-compose build 前の段階では以下の構成となります

.
├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   └── conf.d
│       └── nginx.conf
└── tomcat
    └── Dockerfile

最終的な構成となります。

.
├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   ├── conf.d
│   │   └── nginx.conf
│   └── log
│       ├── access.log
│       ├── error.log
│       ├── tomcat_access.log
│       └── tomcat_error.log
└── tomcat
    ├── Dockerfile
    ├── log
    │   ├── catalina.2021-09-06.log
    │   ├── host-manager.2021-09-06.log
    │   ├── localhost.2021-09-06.log
    │   ├── localhost_access_log.2021-09-06.txt
    │   └── manager.2021-09-06.log
    └── webapps
        └── sample
            └── helloworld.html

必要なファイル

  • docker-compose.yml
  • Dockerfile(nginx)
  • nginx.conf(nginx)
  • Dockerfile(tomcat)

docker-compose.yml

services:
  nginx:
    build:
      context: ./nginx
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d/
      - ./nginx/log:/var/log/nginx
    ports:
      - 80:80

  tomcat:
    build:
      context: ./tomcat
    volumes:
      - ./tomcat/webapps:/usr/local/tomcat/webapps
      - ./tomcat/log:/usr/local/tomcat/logs
    ports:
      - 8080:8080

リバースプロキシの設定用にconf.dを修正する必要があるため、マウントしておきます。
ログも何かと必要となるため、マウント。
webapps配下はアプリケーションのデプロイ場所となるためこちらも同様

dockerfile(nginx)

FROM nginx

RUN apt-get update && apt-get install -y vim

EXPOSE 80

RUN rm -rf /etc/nginx/conf.d/

COPY ./conf.d/nginx.conf /etc/nginx/conf.d/
  • defaultのnginx設定を削除して作成した設定に入れ替える
RUN rm -rf /etc/nginx/conf.d/

COPY ./conf.d/nginx.conf /etc/nginx/conf.d/

nginx.conf

server {
    listen 80;
    server_name localhost;

    access_log /var/log/nginx/tomcat_access.log;
    error_log /var/log/nginx/tomcat_error.log;
    location / {
        proxy_pass http://host.docker.internal:8080;
    }
}
  • リバースプロキシの設定

http://localhost:80(nginx)でリクエストした場合に、
http://localhost:8080(tomcat)にリクエストを転送するようにする
dockerの場合はlocalhostではなくhost.docker.internalでないと読み込んでくれないため、注意。 めちゃハマりました。

proxy_pass http://host.docker.internal:8080;

Dockerfile(tomcat)

FROM tomcat:9.0.52

RUN apt-get update && apt-get install -y vim

EXPOSE 8080

versionはデプロイしたいアプリに合わせると良い。
今回はhelloworldを表示させたいだけ、なので気にしなくても良いが、こちらを使用

RUN apt-get update && apt-get install -y vim
何かしらのエラーがあった場合、設定を確認していく必要があるため、vimを入れておきます
vimにはだいぶ助けられました

手順

* image作成

docker-compose build

* コンテナ起動

docker-compose up -d

* http:localhost:80にアクセス

f:id:Tokuty:20210906203926p:plain

何もデプロイするものがないため404 not foundが返却されているが
tomcatの表示がされている。

http://localhost:80(nginx)にアクセスするとnginx.confで設定したproxy_pass http://localhost:8080(tomcat)に転送されていることの確認ができました

マウントしたログで確認しても良い

* webapps直下にhelloworld.htmlを設置する

webapps/sample/helloworld.html

helloworld.html

<h1>helloworld</h1>

* コンテナを作り直して起動する
停止と削除
docker-compose down

構築
docker-compose build

起動
docker-compose up -d

* http:localhost:80/helloworld.htmlにアクセスする

f:id:Tokuty:20210906205432p:plain

無事に表示できました!!

コンテナ内の設定を確認したい場合は以下のコマンドでコンテナ内に入り、vimで確認していきましょう

docker-compose exec tomcat bash

GitHub

https://github.com/TakushiTokuyama/Docker/tree/develop/ReverseProxyServer

参考サイト

qiita.com www.jcsc.co.jp

C# .NET dockerで環境構築

普段はWindowsを使ってますが、Mac mini環境でもC#をさわってみたくなりました。
最初から環境を作成するのはとても大変なため、dockerで環境構築してみることに。

前提条件

  • DockerHubのアカウント登録後、Docker for Mac を install

hub.docker.com

  • install 確認コマンド

docker version

構成

最終的にsampleフォルダ内にプロジェクトが作成されます

.
├── Dockerfile
├── docker-compose.yml
└── sample

必要なファイル

  • docker-compose.yml
  • Dockerfile

docker-compose.yml

version: '3'
services:
  web:
    build: .
    ports:
      - 5000:5000
    tty: true
    volumes:
      - ./sample:/sample
  • コンテナを起動させ続ける

tty: true

  • データの永続化

- ./sample:/sample

localのsampleフォルダ内にコンテナのsampleフォルダをマウントさせる
これをすることで、コンテナを削除してもデータを保存しておくことができる

Dockerfile

FROM mcr.microsoft.com/dotnet/core/sdk:3.1

RUN mkdir /sample
WORKDIR /sample
  • 公式のimageを使用

FROM mcr.microsoft.com/dotnet/core/sdk:3.1

hub.docker.com

手順

  • image作成

docker-compose build

  • コンテナを作成 起動

docker-compose up -d
ここでlocalにsampleフォルダが作成されます

  • コンテナ内に入る

docker-compose exec web bash

  • プロジェクト作成

dotnet new mvc

  • 起動

dotnet run

エラー

warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {36020275-9c58-4ee1-bc60-9c7050c13fa7} may be persisted to storage in unencrypted form.
crit: Microsoft.AspNetCore.Server.Kestrel[0]
      Unable to start Kestrel.
System.InvalidOperationException: Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date.
To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'.

コンテナからアクセスできるようにエンドポイントの設定をする

  • appsettings.Development.jsonに設定を追加

"urls": "http://*:5000;"

http://localhost:5000にアクセスして確認

f:id:Tokuty:20210828181457p:plain

参考サイト

qiita.com
qiita.com
mseeeen.msen.jp

GitHub

github.com

(Node.js) sqlite3を使って大量のデータをInsert

概要

sqlite3を使って400件のデータをinsertする処理を行った後に、
DBに登録したデータの総件数を取得しましたが、
なぜか397件しか取得できていなかったため、理由をまとめました。

問題点について

問題点  

原因を調査していると他にも問題点がたくさんありました。

1. insertした時のデータが順序通りではなくばらばらになってしまっていた。
2. insertした総件数が正しい値で取得できていなかった。

3. autoincrementが上手く機能せずに空で登録されている
4. データをテキストファイルに書き込む処理にて、登録の順序がばらばら。

400件のinsert自体はうまくいっていたので上記4つを修正しました。

問題ありの修正部分

まず、非同期について考慮していなかったため、
順序通りの登録と、総件数の取得が上手くいっていませんでした。

問題点1と2については、insert部分の書き方insert処理が終了した後に総件数を取得するように修正しました。
動的なデータを登録する場合は、SQLインジェクションも考慮して、db.prepareを使う
insert処理終了後に、コールバックで総件数を取得するsqlを呼び出す。

修正前

// INSERT ALL
users.forEach((user, index) => {

    var insertSql = `insert or replace into user 
        (firstName, lastName, fullName)
        values (${user.firstName}, ${user.lastName}, ${user.fullName})`

    DbSetting.DbCommon.getDb().run(
        insertSql
    )

    fs.appendFile("insert.txt", insertSql, (error) => {
        if (error) throw err;
    });
})

// ALL COUNT
DbSetting.DbCommon.getDb().get(`select count(*) from user`, (err, row) => {
    if (err) {
        console.log(error)
    }
    console.log(row["count(*)"])
})

修正後

// db呼び出し
var db = DbSetting.DbCommon.getDb()

var insertSql = `insert into user 
        (firstName, lastName, fullName)
        values (? ,? ,?)`

var stmt = db.prepare(insertSql)

// INSERT ALL
users.forEach((user) => {
    stmt.run(`${user.firstName}`, `${user.lastName}`, `${user.fullName}`);

    fs.appendFileSync("insert.txt", insertSql, (err) => {
        if (err) throw err;
    });
})

stmt.finalize(() => {
    // ALL COUNT
    db.get(`select count(*) from user`, (err, row) => {
        if (err) {
            console.log(err)
        } else {
            console.log(row["count(*)"])
        }
    })
});

問題点3autoincrementoに関しては書き方を以下のように修正。
NUMBER型では使テーブルは作成されるが、autoincrementされないため、INTEGER型に修正。
NUMBER型だとROWIDとも紐づけが自動でされない模様。

id NUMBER AUTO INCREMENT PRIMARY KEY → userId INTEGER PRIMARY KEY AUTOINCREMENT

問題点4同期処理に変更
appendFile → appendFileSync

修正後の全体コード

dbCommon.js

var sqlite3 = require('sqlite3').verbose()

let db

exports.DbCommon = class DbCommon {
    static init() {
        db = new sqlite3.Database('sample.db');
    }

    static getDb() {
        return db
    }

    static initCreateTableUser() {
        db.serialize(() => {
            // CreateTableUser
            let CREATE_TABLE_USER = 'CREATE TABLE IF NOT EXISTS User'
                + '(userId INTEGER PRIMARY KEY AUTOINCREMENT,'
                + 'firstName TEXT NOT NULL,'
                + 'lastName TEXT NOT NULL,'
                + 'fullName TEXT NOT NULL)'

            db.run(CREATE_TABLE_USER, (error) => {
                if (error) {
                    console.log(error)
                }
                console.log(CREATE_TABLE_USER);
            });
        })
    }
}

index.js

const DbSetting = require('./dbCommon');
const UserModel = require('./User')

const fs = require('fs')

// CreateDataBase
DbSetting.DbCommon.init();

DbSetting.DbCommon.getDb();

// initCreateTableUser
DbSetting.DbCommon.initCreateTableUser()

let users = new Array()

// users
for (var i = 0; i < 400; i++) {
    users.push(new UserModel.User(i, i, i, i + i))
}

// db呼び出し
var db = DbSetting.DbCommon.getDb()

var insertSql = `insert into user 
        (firstName, lastName, fullName)
        values (? ,? ,?)`

var stmt = db.prepare(insertSql)

// INSERT ALL
users.forEach((user) => {

    stmt.run(`${user.firstName}`, `${user.lastName}`, `${user.fullName}`);

    fs.appendFileSync("insert.txt", `firstName:${user.firstName} lastName:${user.lastName} fullName:${user.fullName}\n`, (err) => {
        if (err) throw err;
    });
})

stmt.finalize(() => {
    // ALL COUNT
    db.get(`select count(*) from user`, (err, row) => {
        if (err) {
            console.log(err)
        } else {
            console.log(row["count(*)"])
        }
    })
});

GitHub

github.com

参考サイト

qiita.com