ターミナルから psql
コマンドを使って外部の PostgreSQL サーバに接続したいが、 psql
コマンドを使うためには作業マシンに PostgreSQL をインストールしなければならない。
作業マシンに PostgreSQL をインストールすると何が起きるかというと、 createuser
のような「PostgreSQL っぽくない名前のコマンド1」がインストールされてしまう。これがあまり好きではなく、この理由のため自分は作業マシンに PostgreSQL をインストールしたくない。
しかし、外部の PostgreSQL サーバと接続するために psql
コマンドだけは使いたい。
こういうときは、Docker の出番である。
alias psql="docker run --rm -it --net=host postgres:12 psql"
psql
コマンドは Docker コンテナの中で動かすことにして、シェルの alias で普通の psql
コマンドとして使えるようにしている。
※ --net=host
はなくても構わないのだけど、これがあると同じ端末内の別の Docker コンテナで PostgreSQL サーバが動いていてポートがマッピングされている場合に「ホスト名 localhost
」としてアクセスできるようになる。
コンテナ内に環境を閉じ込めることで psql
以外のコマンドはホスト側に露出することがなくなり、いい感じなった。
AWS CLI もそう 2 だけど、コマンドを Docker コンテナの中に閉じ込めて実行するというスタイルは当たり前になっていくのかもしれない。
[追記] pg_dump
や pg_restore
が欲しくなった場合
pg_dump
や pg_restore
が欲しくなった場合も同様に alias を追加すれば良い。
$ alias pg_dump='docker run --rm -it -v $(pwd):/tmp -w /tmp --net=host postgres:12 pg_dump'
$ alias pg_restore='docker run --rm -it -v $(pwd):/tmp -w /tmp --net=host postgres:12 pg_restore'
使うときはこう。
$ pg_dump -Fc --no-acl --no-owner -U <username> -h <host> <database> -f data.dump
$ pg_restore -Fc -U <username> -h <host> -d <database> data.dump
ただし注意点として、 pg_dump
を Docker コンテナで動かす場合は標準出力を使わずに -f
オプションでファイルに書き出す必要がある。どうやら -t
オプションでコンテナに擬似 TTY を割り当てた状態で標準出力でホストに直接ファイルを書き出すと改行コード周りがおかしくなってしまうらしく、リストア時に pg_restore: error: could not read from input file: end of file
というエラーが出てしまう。かといって -t
を外すと今度はパスワードプロンプトに入力することができなくなってしまう。
[追記] 結果をファイルに出力したい場合
クエリ実行結果をファイルに出力したい場合、上記の alias だと -t
が付いているせいでリダイレクトがうまくいかない。
alias を使わずに以下のようにすると出力できる。
$ PGPASSWORD=<password> docker run --rm postgres:12 psql -h <host> -U <username> <database> -c "SELECT ..." -A -F $'\t' > out.tsv