#はじめに
コロナ禍で自宅勤務になったので、今更ながらDockerやgolangでも使ってみようと思い少しお勉強してみました。
Qiitaで記事書くのも初めてなので優しくしてね(汗)
仕事ではOracleが多いのでgolangからOracleに接続を試みます。
#評価環境
ホストOS:CentOS Linux release 7.7.1908 (Core)
Docker:Docker version 19.03.8, build afacb8b
DB Server:Oracle Database 11g Express Edition Release 11.2.0.2.0
#Oracleクライアント
インスタントクライアントをOTN(Oracle Technology Network)からダウンロードします。
今回は入手できた最新の19.6を使いました。
instantclient-basic-linux.x64-19.6.0.0.0dbru.zip
instantclient-sdk-linux.x64-19.6.0.0.0dbru.zip
instantclient-sqlplus-linux.x64-19.6.0.0.0dbru.zip
sqlplusは必須ではありませんが接続確認用に入れています。
#接続ライブラリ
mattn/go-oci8 というのがあるらしいのでそれを使っています。
#実行手順
host# はホストのrootアカウントで実行
container# はDockerコンテナ上のrootアカウントで実行
イメージを取得して実行(デーモンで起動したいのだがExitedになってしまう)
host# docker pull golang
host# docker run -it --name gogo golang
container# exit
コンテナにモジュールをコピーしてコンテナに接続
host# docker start gogo
host# docker cp instantclient-basic-linux.x64-19.6.0.0.0dbru.zip gogo:/usr/lib
host# docker cp instantclient-sdk-linux.x64-19.6.0.0.0dbru.zip gogo:/usr/lib
host# docker cp instantclient-sqlplus-linux.x64-19.6.0.0.0dbru.zip gogo:/usr/lib
host# docker exec -it gogo /bin/bash
必要なモジュールをインストール後、Oracleクライアント/usr/lib配下に展開
container# apt-get update
container# apt-get install -y vim libaio1 unzip
container# cd /usr/lib
container# unzip instantclient-basic-linux.x64-19.6.0.0.0dbru.zip
container# unzip instantclient-sdk-linux.x64-19.6.0.0.0dbru.zip
container# unzip instantclient-sqlplus-linux.x64-19.6.0.0.0dbru.zip
環境変数を設定(本来なら.bash_profileに書くべきですが省略)
container# export LD_LIBRARY_PATH=/usr/lib/instantclient_19_6:$LD_LIBRARY_PATH
container# export NLS_LANG=JAPANESE_JAPAN.AL32UTF8
sqlplusで接続してみる。日本語で表示されたのでNLS_LANGもちゃんと効いている様子。
container# /usr/lib/instantclient_19_6/sqlplus scott/tiger@dbhost:1521/xe
SQL*Plus: Release 19.0.0.0.0 - Production on 水 4月 22 09:24:41 2020
Version 19.6.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
Oracle Database 11g Release 11.2.0.4.0 - 64bit Production
に接続されました。
SQL>exit
container#
よく分からないがoci8.pc というファイルが必要らしいので作成
container# vi /usr/lib/pkgconfig/oci8.pc
prefix=/usr/lib/instantclient_19_6/
libdir=${prefix}
includedir=${prefix}sdk/include/
Name: oci8
Description: Oracle Instant Client
Version: 19.6
Libs: -L${libdir} -lclntsh
Libs.private:
Cflags: -I${includedir}
githubからgo-oci8を取得
container# cd $GOPATH/src
container# go get github.com/mattn/go-oci8
動作確認用のプログラム作成
package main
import (
"database/sql"
"fmt"
"os"
_ "github.com/mattn/go-oci8"
)
func execSQL(db *sql.DB, sql string) bool{
_,err := db.Exec(sql)
if err != nil {
fmt.Println(err)
return false
} else {
return true
}
}
func main() {
db, err := sql.Open("oci8", os.Args[1])
if err != nil {
fmt.Println(err)
return
}
defer db.Close()
if !execSQL(db,"create table HOGE (NUM number(2),WORD varchar2(10))"){
return
}
if !execSQL(db,"insert into HOGE values (1,'One')"){
return
}
if !execSQL(db,"insert into HOGE values (2,'Two')"){
return
}
if !execSQL(db,"insert into HOGE values (3,'Three')"){
return
}
rows ,err := db.Query("select NUM,WORD from HOGE order by NUM")
if err != nil {
fmt.Println(err)
return
}
defer rows.Close()
for rows.Next(){
var num int
var word string
rows.Scan(&num, &word)
fmt.Println(num, word)
}
_,err = db.Exec("drop table HOGE")
}
実行してみる
container# go run test.go scott/tiger@dbhost:1521/xe
1 One
2 Two
3 Three
container#
ということで何とか動きましたとさ。めでたし めでたし