目的
あるレンタルサーバーで PostgreSQL7.4 を使用しているシステムがあったのですが、そのレンタルサーバーでは PostgreSQL のサービスが終了することになり、急遽 PostgreSQL を自前で用意する必要があったので、Docker で PostgreSQL を構築しました。
PostgreSQL の過去のバージョン
PostgreSQL は過去のバージョンを遡るとソースコードでは 6.0 ぐらいまでダウンロードすることができるのですが、オフィシャルで用意されている Docker イメージは、11.21 以降しかなく、7.4 をソースからビルドするしかない状況です。
実際に構築を進めていくと 7.4 のStableでは initdb がエラーになってしまいうまく動作しないことが分かったため、8.0 をソースからビルドすることにしました。
PostgreSQL 8.0 は 7.4 と互換性があるようで、システムもソースコード(SQL文)を変更することなく使用することができました。
アプローチ
構築手段としてまずは、CentOS8 の Docker image でコンテナを作成し、その中に Developer tools をインストールして PostgreSQL のソースを git から clone して構築しようと思います。
なぜ、CentOS8 なのかという事なのですが、以前に CentOS8 を使った Docker コンテナを作ったことがあり、これをベースにしようと考えたからです。
ビルド用ディレクトリ構成
docker/
docker-compose.yml
pgsql-8.0/
centos-gpg-keys-8-3.el8.noarch.rpm
Dockerfile
pgsql/ <-- PostgreSQL のデータディレクトリ
Tokyo
PostgreSQL のデータディレクトリをホスト側の領域に持たせることで、データベースの永続化を行います。コンテナを再ビルドしてもデータが保持されます。
Dockerfile
# CentOS のイメージ
FROM centos:centos8
#Dockerfile作成者
MAINTAINER ishida
#タイムゾーンの設定
COPY Tokyo /etc/localtime
# DNS の追加
RUN echo "nameserver 8.8.8.8" >> /etc/resolv.conf
# リポジトリ変更
COPY centos-gpg-keys-8-3.el8.noarch.rpm /tmp
RUN rpm -i '/tmp/centos-gpg-keys-8-3.el8.noarch.rpm'
RUN dnf -y --disablerepo '*' --enablerepo=extras swap centos-linux-repos centos-stream-repos
RUN dnf -y distro-sync
RUN echo "baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/" >> /etc/yum.repos.d/CentOS-Base.repo
RUN yum list
RUN yum -y update
# 開発環境をインストール
RUN dnf makecache --refresh
RUN dnf clean all
RUN dnf update -y
RUN yum groupinstall -y 'Development Tools'
RUN dnf install -y vim
RUN dnf install -y cmake3
RUN dnf install -y clang
RUN dnf install -y git
RUN dnf install -y readline-devel
#
# ユーザー作成
#
# インストール先ディレクトリを作成
RUN mkdir -p /usr/local/pgsql
RUN mkdir -p /var/lib/pgsql
# postgres ユーザーを作成
RUN /usr/sbin/useradd postgres -d /usr/local/pgsql
# ディレクトリのオーナーを変更
RUN chown -R postgres /usr/local/pgsql
# パスを追加
RUN echo -e "export PATH=\$PATH:/usr/local/pgsql/bin" >> /etc/bashrc
#
# PostgreSQL ビルド
#
# ソース用のディレクトリを作成
RUN mkdir -p /usr/local/src
# PostgreSQL をクローン
WORKDIR /usr/local/src
RUN git clone https://git.postgresql.org/git/postgresql.git
WORKDIR /usr/local/src/postgresql
RUN git branch -a
# RUN git checkout REL7_4_STABLE
RUN git checkout REL8_0_STABLE
# PostgreSQL をビルド
RUN sh configure --without-readline
RUN make
RUN make install
#
# PostgreSQL 初期設定
#
RUN echo -e "su - postgres -c '(/usr/local/pgsql/bin/initdb --encoding=EUC-JP --no-locale -D /var/lib/pgsql/data)'" > /root/init.sh
RUN chmod o+x /root/init.sh
CMD sh /root/init.sh
#
# PostreSQL 起動設定
#
# PostgreSQL 起動
RUN mkdir /var/lib/pgsql/log
RUN chown postgres:postgres /var/lib/pgsql/log
RUN echo -e "su - postgres -c '(pg_ctl -D /var/lib/pgsql/data -l /var/lib/pgsql/log/pgsql.log start)' \n cd /root\n /bin/bash" > /root/session.sh
#httpd,tomcat6の起動スクリプトの権限設定
RUN chmod o+x /root/session.sh
#公開ポート
EXPOSE 5432
#PostgreSQLの起動スクリプトの実行
CMD sh /root/session.sh
docker-compose.yaml
#
# PostgreSQL 8.0 container
#
pgsql-8.0:
container_name: pgsql-8.0
# restart: always
stdin_open: true
tty: true
ports:
- "5432:5432"
build:
context: pgsql-8.0
dockerfile: Dockerfile
args:
uid: ${UID}
gid: ${GID}
environment:
POSTGRES_USER: 'postgres'
POSTGRES_PASSWORD: 'postgres'
TZ: 'Asia/Tokyo'
volumes:
- ./pgsql-8.0/pgsql:/var/lib/pgsql
network_mode: bridge
実行結果
$ docker-compose up pgsql-8.0
.
.
.
Step 40/43 : RUN echo -e "su - postgres -c '(pg_ctl -D /var/lib/pgsql/data -l /var/lib/pgsql/log/pgsql.log start)' \n cd /root\n /bin/bash" > /root/session.sh
---> Running in 0c7cef14d38f
Removing intermediate container 0c7cef14d38f
---> d42518ff88ca
Step 41/43 : RUN chmod o+x /root/session.sh
---> Running in 9b31fed6d858
Removing intermediate container 9b31fed6d858
---> d355a87c2217
Step 42/43 : EXPOSE 5432
---> Running in d1a2ce48b3f1
Removing intermediate container d1a2ce48b3f1
---> 6cf85d6999de
Step 43/43 : CMD sh /root/session.sh
---> Running in 2a4ab7f9d8de
Removing intermediate container 2a4ab7f9d8de
---> 63d7eabae0e1
[Warning] One or more build-args [uid gid] were not consumed
Successfully built 63d7eabae0e1
Successfully tagged system_pgsql-8.0:latest
WARNING: Image for service pgsql-8.0 was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating pgsql-8.0 ... done
Attaching to pgsql-8.0
pgsql-8.0 | pg_ctl: another postmaster may be running; trying to start postmaster anyway
pgsql-8.0 | pg_ctl: could not start postmaster
pgsql-8.0 | Examine the log output.
おわりに
データベースの様に性能がクリティカルなものを仮想化して運用するという点については再検討が必要ですが、過去のバージョンの環境を簡単に用意したり、1つのサーバーで複数の環境を用意したりする場合は利便性が高い為、性能とのトレードオフと考えればよいかと思います。
意外と過去のバージョンのまま動作しているシステムなどが、多く存在している為、Docker で過去のシステムを再現する手法を持っておくのは良いことだと思います。