データベースサーバをコンテナでつくる

この記事では、PostgreSQLを組み込んだAlmaLinuxのOSイメージをPodmanのPodにデプロイして運用する方法について、実際の手順に基づいて詳しく説明しています。

データベースサーバをコンテナでつくる

今回の構成の一覧は以下のとおり。

ホストOSRed Hat Enterprise Linux release 8.8 (Ootpa)
コンテナpodman version 4.4.1
OSイメージAlmaLinux release 9.3 (Shamrock Pampas Cat)
データベースPostgreSQL 15.5
データベースアクセスソフトウェアpgAdmin4 Version8.5
構成一覧

コンテナでデータベースを運用する場合は、「OSイメージにデータベースを組み込んでコンテナにデプロイする方法」と「コンテナにデータベースイメージをデプロイする方法」の2つが考えられます。

以下のようなイメージのものを作っていきます。

構築イメージ

今回は前者の「OSイメージにデータベースを組み込んでコンテナにデプロイする方法」になります。そのため、ベースとなるOSイメージのpullから、Linux OSの各種サービスの設定、PODへのデプロイと構築手順は複雑ですが、コンテナ上にサーバを構築する上での基本事項が網羅されていますのであきらめずに頑張りましょう。

ベースのOSイメージを作成する

はにめに、PostgreSQLやその他必要なサービスを含んだOSのコンテナイメージを作成していきます。コンテナイメージの作成は、podman buildコマンドを使用します。

作成するコンテナイメージの内容を記述したContainerfileを作成します。

$ vi Containerfile

FROM docker.io/library/almalinux:latest

USER root

RUN echo root:root0000 | chpasswd
RUN dnf -y install openssh-server; dnf -y install openssh-clients
RUN dnf -y install rsyslog
RUN dnf -y install firewalld
RUN dnf -y install passwd
RUN dnf -y install which
RUN dnf -y module install postgresql:15/server
RUN dnf -y install httpd
RUN dnf clean all
RUN echo "Port 2222" >> /etc/ssh/sshd_config
RUN systemctl enable rsyslog
RUN systemctl enable firewalld
RUN systemctl enable httpd

作成したContainerfileを使って、OSイメージを作成します。

$ podman build -t alma_pgsql_base:0.0.0 -f Containerfile .

・・<中略>・・
STEP 11/15: RUN dnf clean all
28 files removed
--> b286af05e7e
STEP 12/15: RUN echo "Port 2222" >> /etc/ssh/sshd_config
--> 89b9769a771
STEP 13/15: RUN systemctl enable rsyslog
--> d468048dccb
STEP 14/15: RUN systemctl enable firewalld
--> 6dfaef2327b
STEP 15/15: RUN systemctl enable httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
COMMIT alma_pgsql_base:0.0.0
--> f74032019e9
Successfully tagged localhost/alma_pgsql_base:0.0.0
f74032019e9cfb71b3bf1d1ef1aaa17443c62de5ba98bc9fe122b842a783cc45

podman buildコマンドが完了したら、以下のようにローカルにイメージが保存されています。

$ podman images

REPOSITORY                   TAG         IMAGE ID      CREATED        SIZE
localhost/alma_pgsql_base    0.0.0       f74032019e9c  9 minutes ago  394 MB
docker.io/library/almalinux  latest      7407e03f7ffc  7 weeks ago    190 MB

OSイメージの起動とサービスの設定

OSイメージ上のPostreSQLデータベースのデータを永続化するため、以下のコマンドで作成されたディレクトリをコンテナにバインドします。

$ mkdir -p /opt/container/vol1

Podman Volumeの詳細は、以下を参照してください。

次に、外部ネットワークからコンテナ起動したAlmaLinuxにアクセスできるようにするため、macvlanを利用します。今回は既に作成済みのtest_macvlan(192.168.11.0/24)を使用します。

$ podman network ls
NETWORK ID    NAME          DRIVER
2f259bab93aa  podman        bridge
bb4e29995085  test_macvlan  macvlan

Podmanのmacvlanの詳細は、以下を参照してください。

作成したベースとなるOSイメージをコンテナ起動します。

$ podman run --privileged -itd --rm -v /opt/container/vol1:/opt/vol1 --net test_macvlan --ip=192.168.11.200 --name db_server -h dbsrv01.reafnex.net alma_pgsql_base:0.0.0 /sbin/init

b714bdef02231459884795cfa7115bf43ac28c2e8b339445f4ba60ff2b132191

$ podman ps
CONTAINER ID  IMAGE                            COMMAND     CREATED         STATUS         PORTS       NAMES
b714bdef0223  localhost/alma_pgsql_base:0.0.0  /sbin/init  33 seconds ago  Up 33 seconds              db_server

起動したコンテナにログインします。

$ podman exec -it db_server /bin/bash

[root@dbsrv01 /]# hostname
dbsrv01.reafnex.net
[root@dbsrv01 /]# hostname -i
192.168.11.200

コンテナ起動したAlmaLinux OSのファイヤーウォールを設定します。今回必要となるポートは、SSH(2222)ポートとPostgreSQLデータベース(5432)ポートを開放します。

その他、pgAdmin4にWEBアクセスするためhttp(80)ポートも開放します。

[root@dbsrv01 /]# firewall-cmd --add-port=2222/tcp --zone=public --permanent
success
[root@dbsrv01 /]# firewall-cmd --add-port=5432/tcp --zone=public --permanent
success
[root@dbsrv01 /]# firewall-cmd --add-service=http --zone=public --permanent
success
[root@dbsrv01 /]# firewall-cmd --reload
success
[root@dbsrv01 /]# firewall-cmd --list-all
public
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: cockpit dhcpv6-client http ssh
  ports: 2222/tcp 5432/tcp
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

この時点で、外部からteratermなどを利用してコンテナ起動されたAlmaLinux OSに直接ログインすることができるようになります。また、外部から「http://192.168.11.200」にアクセスすることで、以下の画面が表示されるはずです。

PostgreSQLデータベースの設定

ここからは、Postgresqlデータベースの初期設定をしていきます。Redhat系のLinuxでは、セットアップユーティリティが利用できます。以下のコマンドを実行しましょう。

[root@dbsrv01 ~]# postgresql-setup --initdb
 * Initializing database in '/var/lib/pgsql/data'
 * Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log

セットアップユーティリティの処理が終わると、/var/lib/pgsql配下にPostgreSQLデータベースの設定ファイルとデータスペースが作成されます。

ただし、PostgreSQLデータベースのデータスペースなどはコンテナ内作成されているため、コンテナを停止してしまうと全て消えてしまします。一時的にデータベースを利用するだけの場合、これでも十分ですが、今回はデータスペースを永続化するための設定を施していきます。

PostgreSQLデータベースは、postgresユーザで実行されます。postgresユーザのパスワードを設定しましょう。

[root@dbsrv01 vol1]# passwd postgres
Changing password for user postgres.
New password:
BAD PASSWORD: The password contains the user name in some form
Retype new password:
passwd: all authentication tokens updated successfully.

セットアップユーティリティが作成した/var/lib配下のpgsqlディレクトリを、ホストサーバからバインドされた/opt/vol1/pstgresqlディレクトリ内にコピーします。その際、ファイル等の所有権やパーミッションの設定値には注意が必要です。

[root@dbsrv01 vol1]# cd /opt/vol1/
[root@dbsrv01 vol1]# mkdir postgresql
[root@dbsrv01 vol1]# chown postgres:postgres ./postgresql
[root@dbsrv01 vol1]# ls -l
total 0
drwxr-xr-x 2 postgres postgres 6 Jan 21 09:24 postgresql
[root@dbsrv01 vol1]# su postgres
bash-5.1$ pwd
cd /opt/vol1/postgresql
bash-5.1$ cp -r /var/lib/pgsql/* ./
bash-5.1$ exit

ポイントは、postgresユーザでpgsqlディレクトリを/opt/vol1/pstgresqlディレクトリの下にコピーすることです。これにより、ファイルなどの所有権やパーミッションの設定値が維持されます。

次に、systemdでPostgreSQLデータベースを起動するための設定を行います。PostgreSQLデータベースのサービス設定ファイルの環境変数を以下のように修正します。PGDATA環境変数は、先ほど/opt/vol1/pstgresqlにコピーしたpgsqlディレクトリ配下のdataディレクトリを指すように設定します。

[root@dbsrv01 postgresql]# vi /usr/lib/systemd/system/postgresql.service

#Environment=PGDATA=/var/lib/pgsql/data
Environment=PGDATA=/opt/vol1/postgresql/data

これでデータスペースなどの永続化の設定変更が完了しました。

PostgreSQLデータベースに外部からアクセスできるように、以下を修正または追加していきます。

[root@dbsrv01 data]# vi /opt/vol1/postgresql/data/postgresql.conf

#listen_addresses = 'localhost'         # what IP address(es) to listen on;
listen_addresses = '*'

[root@dbsrv01 data]# vi /opt/vol1/postgresql/data/pg_hba.conf

# IPv4 local connections:
#host    all             all             127.0.0.1/32            ident
host     all             all             127.0.0.1/32            md5
host     all             all             0.0.0.0/0               md5

これで一通りの設定が完了しましたので、PostgreSQLデータベースを起動していきましょう。

[root@dbsrv01 data]# systemctl enable postgresql
Created symlink /etc/systemd/system/multi-user.target.wants/postgresql.service → /usr/lib/systemd/system/postgresql.service.
[root@dbsrv01 data]# systemctl start postgresql
[root@dbsrv01 data]# systemctl status postgresql
● postgresql.service - PostgreSQL database server
     Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; preset: disabled)
     Active: active (running) since Sun 2024-01-21 09:44:03 UTC; 5s ago
    Process: 490 ExecStartPre=/usr/libexec/postgresql-check-db-dir postgresql (code=exited, status=0/SUCCESS)
   Main PID: 492 (postmaster)
     CGroup: /machine.slice/libpod-b714bdef02231459884795cfa7115bf43ac28c2e8b339445f4ba60ff2b132191.scope/system.slice/postgresql.service
             tq492 /usr/bin/postmaster -D /opt/vol1/postgresql/data
             tq493 "postgres: logger "
             tq494 "postgres: checkpointer "
             tq495 "postgres: background writer "
             tq497 "postgres: walwriter "
             tq498 "postgres: autovacuum launcher "
             mq499 "postgres: logical replication launcher "

Jan 21 09:44:03 dbsrv01.reafnex.net systemd[1]: Starting PostgreSQL database server...
Jan 21 09:44:03 dbsrv01.reafnex.net postmaster[492]: 2024-01-21 09:44:03.362 UTC [492] LOG:  redirecting log output to logging collector process
Jan 21 09:44:03 dbsrv01.reafnex.net postmaster[492]: 2024-01-21 09:44:03.362 UTC [492] HINT:  Future log output will appear in directory "log".
Jan 21 09:44:03 dbsrv01.reafnex.net systemd[1]: Started PostgreSQL database server.

無事にPostgreSQLデータベースが起動しました。

pgAdminをインストールする

pgAdminは、データベースアクセスアプリケーションであり、PstgreSQLデータベースをGUIベースで操作することが可能な便利なアプリケーションです。

pgAdminをdnf(yum)でインストールするため、外部のリポジトリを追加します。wgetコマンドを利用するためdnf(yum)でインストールします。

[root@dbsrv01 data]# dnf -y install wget
[root@dbsrv01 data]# cd
[root@dbsrv01 ~]# wget https://ftp.postgresql.org/pub/pgadmin/pgadmin4/yum/pgadmin4-redhat-repo-2-1.noarch.rpm

[root@dbsrv01 ~]# rpm -ihv pgadmin4-redhat-repo-2-1.noarch.rpm

外部リポジトリが追加できたので、pgAdmin4をdnf(yum)でインストールします。

[root@dbsrv01 ~]# yum -y install pgadmin4-web

pgAdmin4の初期設定を行うため、以下のユーティリティを実行します。Emailは、pgAdmin4画面のログイン時に利用するpgAdminユーザに紐づけされるものであり、適当なメールアドレスでも問題はありません。

ただし、一度作成したpgAdminユーザのメールアドレスは変更できないため注意してください。pgAdminユーザのパスワードは、後に変更することは可能です。

[root@dbsrv01 ~]# /usr/pgadmin4/bin/setup-web.sh
Setting up pgAdmin 4 in web mode on a Redhat based platform...
Creating configuration database...
NOTE: Configuring authentication for SERVER mode.

Enter the email address and password to use for the initial pgAdmin user account:

Email address: admin@reafnex.net
Password:
Retype password:
pgAdmin 4 - Application Initialisation
======================================

Creating storage and log directories...
Configuring SELinux...
/usr/pgadmin4/bin/setup-web.sh: line 96: setsebool: command not found
/usr/pgadmin4/bin/setup-web.sh: line 97: setsebool: command not found
/usr/pgadmin4/bin/setup-web.sh: line 98: semanage: command not found
/usr/pgadmin4/bin/setup-web.sh: line 99: restorecon: command not found
/usr/pgadmin4/bin/setup-web.sh: line 100: semanage: command not found
/usr/pgadmin4/bin/setup-web.sh: line 101: restorecon: command not found
/usr/pgadmin4/bin/setup-web.sh: line 122: pgrep: command not found
The Apache web server is not running. We can enable and start the web server for you to finish pgAdmin 4 installation. Continue (y/n)? y
Apache successfully enabled.
Apache successfully started.
You can now start using pgAdmin 4 in web mode at http://127.0.0.1/pgadmin4

pgAdminの設定を反映するため、WEBサーバを再起動します。

[root@dbsrv01 ~]# systemctl restart httpd

ブラウザから「http://192.168.11.200/pgadmin4」にアクセスして、以下のような画面が表示されたら設定完了です。

以上で、コンテナイメージの設定はすべて完了です。

作成したコンテナイメージをPODにデプロイする

PODの利用方法の詳細については、以下を参照してください。

まずは、ホストサーバにログインして起動中のコンテナイメージを保存しましょう。保存が完了したら起動中のコンテナを停止/削除します。

$ podman ps
CONTAINER ID  IMAGE                            COMMAND     CREATED      STATUS      PORTS       NAMES
b714bdef0223  localhost/alma_pgsql_base:0.0.0  /sbin/init  2 hours ago  Up 2 hours              db_server

$ podman commit b714bdef0223 dbserver:1.0.0
Getting image source signatures
Copying blob 342efb67861c skipped: already exists
Copying blob cddc473da427 skipped: already exists
Copying blob 165a3ae35d07 skipped: already exists
Copying blob a9301f628d08 skipped: already exists
Copying blob e5f4da3e8c83 skipped: already exists
Copying blob 26a8d1f5fa91 skipped: already exists
Copying blob c864ed21603c skipped: already exists
Copying blob dd8624433dad skipped: already exists
Copying blob b44e782c1218 skipped: already exists
Copying blob dad8ad78a543 skipped: already exists
Copying blob ebbee48b905f skipped: already exists
Copying blob 5f70bf18a086 skipped: already exists
Copying blob 5f70bf18a086 skipped: already exists
Copying blob 32764b6d3031 skipped: already exists
Copying blob 9166a461bc16 done
Copying config cf03cad3a9 done
Writing manifest to image destination
Storing signatures
cf03cad3a9c01adb2490d0abd6e48db2008c85aeccaee7c573a36587d49390a1

$ podman images
REPOSITORY                   TAG               IMAGE ID      CREATED             SIZE
localhost/dbserver           1.0.0             cf03cad3a9c0  About a minute ago  909 MB
localhost/podman-pause       4.4.1-1695119471  9be731681a2b  4 minutes ago       735 kB
localhost/alma_pgsql_base    0.0.0             f74032019e9c  3 hours ago         394 MB
docker.io/library/almalinux  latest            7407e03f7ffc  7 weeks ago         190 MB

$ podman stop db_server

$ podman ps
CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES

PODの作成とコンテナイメージのデプロイ

PODを作成して、保存したコンテナイメージ(dbserver:1.0.0)をPODにデプロイしていきます。

$ podman pod create --name dbserver-pod --share net
b3f28335444622d8a875ead474b50653c5597bd6b60ef449629b6139c41a1271

$ podman pod ls
POD ID        NAME          STATUS      CREATED        INFRA ID      # OF CONTAINERS
b3f283354446  dbserver-pod  Created     6 seconds ago  339ccbaaefd9  1

$ podman run --pod dbserver-pod --privileged -itd --rm -v /opt/container/vol1:/opt/vol1 --net test_macvlan --ip=192.168.11.200 --name db_server -h dbsrv01.reafnex.net  dbserver:1.0.0 /sbin/init
66e042d7df147ea9049d5c5a95afd64c3a4490f6228248cef3f590ebdd411593

$ podman pod start dbserver-pod
b3f28335444622d8a875ead474b50653c5597bd6b60ef449629b6139c41a1271

$ podman pod ls
POD ID        NAME          STATUS      CREATED         INFRA ID      # OF CONTAINERS
b3f283354446  dbserver-pod  Running     11 minutes ago  339ccbaaefd9  2

POD及び保存したコンテナイメージが起動されました。

PODの設定ファイルを作成する

起動中のPODの設定ファイル(YAMLファイル)を作成します。

$ podman generate kube dbserver-pod > dbserver-pod.yaml
WARN[0000] Truncation Annotation: "sha256:f007720235c27bfd4d03d078ce19c1bbb467e82a86ed763e76e9d5ff348985b6" to "sha256:f007720235c27bfd4d03d078ce19c1bbb467e82a86ed763e76e9d5ff": Kubernetes only allows 63 characters

$ ls
Containerfile  dbserver-pod.yaml

PODの設定ファイル(YAMLファイル)が作成できたので、ここで一旦起動中のPODを停止/削除します。

$ podman pod stop dbserver-pod
b3f28335444622d8a875ead474b50653c5597bd6b60ef449629b6139c41a1271

$ podman pod rm dbserver-pod
b3f28335444622d8a875ead474b50653c5597bd6b60ef449629b6139c41a1271

$ podman pod ls
POD ID      NAME        STATUS      CREATED     INFRA ID    # OF CONTAINERS

PODの設定ファイルを使ってデプロイする

PODの設定ファイルを使って、先ほど削除したPOD環境を再度デプロイしていきます。

$ podman kube play --network test_macvlan --ip=192.168.11.200 dbserver-pod.yaml
WARN[0000] No more static macs left using a random one
Pod:
570b7d281de162b841a7e4f38b01eff3eb09c56734c89bf9ce2b578d589149c6
Container:
27a5d72b72e98091af2cef4db9629625ddb54bbaaf035675a98d00bae53444d5

$ podman pod ls
POD ID        NAME          STATUS      CREATED         INFRA ID      # OF CONTAINERS
570b7d281de1  dbserver-pod  Running     30 seconds ago  35aafe2578e6  2

無事にPODをデプロイすることができました。

pgAdmin4の初期設定

pgAdmin4から構築されたばかりのPostgreSQLデータベースに接続するためには、postgresユーザでログインすることになります。

postgresユーザにはパスワードが未設定であるため、PODのAlmaLinuxにログインしてpostgresユーザのパスワードを設定します。今回のpostgresユーザのパスワードは「postgres」に設定していますが、セキュリティの観点で任意に設定してください。

設定できたらログアウトします。

[root@dbsrv01 ~]# su postgres
bash-5.1$ psql
could not change directory to "/root": Permission denied
psql (15.5)
Type "help" for help.

postgres=# alter role postgres with password 'postgres';
ALTER ROLE
postgres=# \q

ブラウザから「http://192.168.11.200/pgadmin4」にアクセスし、pgAdmin4の初期設定で設定したメールアドレスとパスワードを使用してログインします。ログインが完了すると以下の画面が表示されます。

この段階では、PostgreSQLデータベースには接続されていないため、操作するデータベースを設定します。左のメニューにある「Severs」を右クリックして「登録」→「サーバ」の順に選択します。

「登録・サーバ」ウィンドウが表示されるので、「General」タブから名前(任意)を設定します。

「接続」タブから「ホスト名/アドレス」と「ユーザ名」、「パスワード」を設定します。まだ構築したばかりのデータベースであるため、ユーザ名は「postgres」を入力し、PostgreSQLデータベースでpostgresユーザに設定したパスワードを入力します。

ポート番号及びその他の設定項目はデフォルトのままとします。

入力が終わったら、「保存」ボタンを押して設定を保存します。以下のようにダッシュボードが表示されたらpgAdmin4からPostgreSQLデータベースへの接続は完了です。

まとめ

少々長くなりましたが、いかがでしたでしょうか。

今回は、PostgreSQLデータベースを含んだAlmaLinux OSのコンテナをPODにデプロイして運用する方法について解説しました。また、データベースアクセスアプリケーションであるpgAdmin4のインストール方法や、データベースのデータ永続化についても順を追って紹介しました。

今回のモチベーションは、データベースをコンテナで運用することにありました。

コンテナでデータベースを運用する場合には、「OSイメージにデータベースを組み込んでコンテナにデプロイする方法」と「コンテナにデータベースイメージをデプロイする方法」の2つの選択肢がありますが、今回は前者を詳細に取り上げました。

さらに、今回の手順にはLinuxサーバOSのサービス設定も含まれており、これによりオンプレミスのデータベースサーバの構築方法にも応用可能です。

今回の手順を応用すれば、コンテナ上で様々な用途のサーバを構築するスキルを身につけることができるでしょう。

参考になれば幸いです。

システムのお悩みについてご相談ください

本サイトの掲載内容に関するお問い合わせは、こちらから承ります。
SOHOのシステム運用管理に関するお悩みごとについて、なんでもお気兼ねなくご相談ください。
現役システムエンジニアのスタッフが、ボランティアでご相談にご対応させていただきます。
FastAPI

前の記事

FastAPIって何?