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.
非推奨ですが、ローカルで開発するときにはとても重宝します。