PostgreSQL を Docker で動かして、そこに Kotlin Script からアクセスする覚え書きです。
環境:
$ lsb_release -a|grep Description
Description: Ubuntu 24.04.1 LTS
$ docker --version
Docker version 27.2.0, build 3ab4256
まず、ローカルレポジトリにひとつも image が存在しないことを確認。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
postgres を docker run する。
$ docker run --rm -d -p 5432:5432 --name my-postgres -e POSTGRES_PASSWORD=foobar postgres
ローカルレジストリに postgres イメージは pull されている。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
postgres latest de869b203456 2 days ago 494MB
さらに docker ps すると postgres が起動していることも確認。 名前は my-postgres になっている。(先ほど --name でそれを指定したので。)
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5993a3338ab7 postgres "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp my-postgres
pokemon_db という名前のデータベースを作成する。
psql コマンドが存在しなければ入れる。
$ sudo apt install postgresql-client-common $ sudo apt install postgresql-client-17
psql で Postgres のプロンプトに入る。
$ psql -U postgres -h localhost -p 5432 -d postgres
Password for user postgres:
postgres=#
そして データベース作成用の SQL コマンドを実行。
postgres=# CREATE DATABASE pokemon_db;
CREATE DATABASE
pokemon_db データベースにテーブル pokemons を作成して、 いくつかのポケモンを追加する Kotlin Script を用意。
// psql.main.kts
@file:Repository("https://repo1.maven.org/maven2/")
@file:DependsOn("org.postgresql:postgresql:42.7.5")
@file:DependsOn("com.zaxxer:HikariCP:6.2.1")
import com.zaxxer.hikari.HikariDataSource
import com.zaxxer.hikari.HikariConfig
data class Db(
val driver: String,
val url: String,
val user: String,
val password: String)
val toConfig: (Db)->HikariConfig = { db->
HikariConfig().apply {
setDriverClassName( db.driver )
setJdbcUrl( db.url )
setUsername(db.user)
setPassword(db.password)
}
}
val db = Db(
"org.postgresql.Driver",
"jdbc:postgresql://localhost/pokemon_db",
"postgres",
"foobar")
val ds = HikariDataSource(toConfig(db))
ds.connection.use { connection->
connection.createStatement().use { st->
val sql0 = listOf(
"DROP TABLE IF EXISTS pokemons;",
"CREATE TABLE pokemons(id SERIAL PRIMARY KEY, name VARCHAR(128));").joinToString("")
st.executeUpdate(sql0)
listOf(
"INSERT INTO pokemons (name) VALUES('Pikachu');",
"INSERT INTO pokemons (name) VALUES('Charmander');"
).forEach { sql->
st.executeUpdate(sql)
}
}
}
実行する。
バージョンはこれ:
$ kotlin -version Kotlin version 2.1.0-release-394 (JRE 17.0.2+8-86)
$ kotlin psql.main.kts
psql を使って pokemon_db テーブルが意図通り作成できたかを確かめる。
$ psql -U postgres -h localhost -p 5432 -d pokemon_db
pokemon_db=# \dt
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | pokemons | table | postgres
(1 row)
pokemon_db=# SELECT * FROM pokemons;
id | name
----+------------
1 | Pikachu
2 | Charmander
(2 rows)
pokemons データベースが作成されてそこにポケモンを入れることができました。
SQL はこれ:
ALTER TABLE pokemons ADD COLUMN type VARCHAR(128) DEFAULT 'Electric';
とりあえず全部 Electric を初期値として設定することにします。
$ psql -U postgres -h localhost -p 5432 -d pokemon_db
pokemon_db=# ALTER TABLE pokemons ADD COLUMN type VARCHAR(128) DEFAULT 'Electric';
ALTER TABLE
pokemon_db=# SELECT * FROM pokemons;
id | name | type
----+------------+----------
1 | Pikachu | Electric
2 | Charmander | Electric
(2 rows)
できました。
Charamander は Fire なのでそこは修正しましょう。
pokemon_db=# UPDATE pokemons SET type='Fire' WHERE name='Charmander';
UPDATE 1
pokemon_db=# SELECT * FROM pokemons;
id | name | type
----+------------+----------
1 | Pikachu | Electric
2 | Charmander | Fire
(2 rows)
変更できました。
ここで docker run していた Postgres を停止します。 その前にデータベースはバックアップしておき、 再度 docker run したときにリストアできるようにしておきましょう。
pg_dump コマンドの説明はこちら
pokemon_db.dump ファイルにダンプデータを入れます。
$ pg_dump -U postgres -h localhost -p 5432 pokemon_db > pokemon_db.dump
内容を見てみるとプレーンテキストでコマンドが羅列されています。
$ head pokemon_db.dump
--
-- PostgreSQL database dump
--
-- Dumped from database version 17.3 (Debian 17.3-1.pgdg120+1)
-- Dumped by pg_dump version 17.3 (Ubuntu 17.3-1.pgdg24.04+1)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
それでは docker run していた Postgres を停めます。
docker ps で CONTAINER ID を確認。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1916c497ac1e postgres "docker-entrypoint.s…" 59 minutes ago Up 59 minutes 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp my-postgres
停止する。
$ docker stop 1916c497ac1e
1916c497ac1e
docker ps して Postgres が存在しないことを確認しましょう。
docker run して postgres を起動:
$ docker run --rm -d -p 5432:5432 --name my-postgres -e POSTGRES_PASSWORD=foobar postgres
pokemon_db テーブルを用意:
$ psql -U postgres -h localhost -p 5432 -d postgres
postgres=# CREATE DATABASE pokemon_db;
CREATE DATABASE
ちなみに次のように -d postgres は省略しても同じ結果になる。省略すると postgres データベースが選択される。
$ psql -U postgres -h localhost -p 5432
または
$ psql -U postgres -h localhost
-p は省略可能。省略したら 5432 がデフォルトとして使用されるようだ。
環境変数PGDATABASE、PGHOST、PGPORT、PGUSERに適当な値を設定することで、このデフォルト値を上書きすることができるらしい。
先ほどバックアップとして pg_dump しておいたデータを標準入力から psql へ渡す。
$ cat pokemon_db.dump | psql -U postgres -h localhost -p 5432
...
データベース pokemon_db を作成しないで、 dump を投入してもリストアできないので注意!
リストアできているかを確認:
$ psql -U postgres -h localhost -p 5432 -d pokemon_db
pokemon_db=# SELECT * FROM pokemons;
id | name | type
----+------------+----------
1 | Pikachu | Electric
2 | Charmander | Fire
(2 rows)
OKです。
docker run するときに 次のようにすれば postgres ユーザのパスワードをなしで利用できます。
$ docker run --rm -d -p 5432:5432 --name my-postgre -e POSTGRES_HOST_AUTH_METHOD=trust postgres
You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all connections without a password. This is not recommended.
非推奨ですが、ローカルで開発するときにはとても重宝します。