
「dockerから逃げるな!」
前回の内容でPostgreSQLのコンテナを作ったということで、
もうある程度コンパクトなシステムも簡単に構築できるんじゃない?
という気運が一気に高まってまいりました。
そこで今回はPHP+PostgreSQL+Apacheの組み合わせで、
「ブラウザアクセスをApacheが受け付けし、PHPから他のPostgreSQLコンテナに検索をする」
という一連の動作を実行していきます!
目次
やりたいこと
・PHP+ApacheとPostgreSQLコンテナの2台体制
・webコンテナにブラウザアクセスをすると、PostgreSQLコンテナに検索をする
・2つのコンテナに必要な個別ファイルはなるべき整理整頓する
構成について
ディレクトリ構成
[プロジェクト]/
├── docker-compose.yml
├── web/
│ ├── Dockerfile
│ └── source/var/www/html/
│ └── index.php
├── db/
│ ├── Dockerfile
│ └── initdb/
│ └── init.sql
今回2つのコンテナを構築・初期設定するため、
初期設定用のファイルを整理する意味でwebフォルダ、dbフォルダにそれぞれ配備することにしました。
※同じフォルダに置くとゴチャゴチャしそうなので。。。
webの方はdbに接続するテスト用のphpを用意してます。
docker-compose.ymlの中身
services:
web:
build:
context: ./web
dockerfile: Dockerfile
container_name: php8-202506
ports:
- "8080:80"
networks:
- php-postgres-network
db:
build:
context: ./db
dockerfile: Dockerfile
container_name: postgres16-202506
# 接続情報
environment:
POSTGRES_USER: testuser
POSTGRES_PASSWORD: test
POSTGRES_DB: pref
ports:
- "5432:5432" # ホストの5432 → コンテナの5432
networks:
- php-postgres-network
# データの初期化(SQLファイル実行)
volumes:
- ./db/initdb:/docker-entrypoint-initdb.d
command:
- "postgres"
- "-c"
- "log_min_duration_statement=0"
networks:
php-postgres-network:
”context"を初めて使うんですが、"image"と使わずに構築する際、作業ディレクトリを指定する者になります。
各種Dockerfileの中身
FROM php:8.3-apache
RUN apt-get update && apt-get install -y \
libpq-dev \
&& docker-php-ext-install pdo_pgsql pgsql
COPY ./source/var/www/html/ /var/www/html/
通常のコンテナイメージだとpgsql周りがないので必要なライブラリをインストールしつつ、
テスト用のphpを配備します。
FROM postgres:16
DB側は特にDokcerfileにする必要はなかったんですが、
バラバラだと統一感がないと思い作ってます。
webコンテナのindex.php(DB接続用テストファイル)の中身
<?php
$host = 'db'; // コンテナ名(=ホスト名)
$dbname = 'pref';
$user = 'testuser';
$pass = 'test';
$dsn = "pgsql:host=$host;dbname=$dbname";
try {
$pdo = new PDO($dsn, $user, $pass);
$stmt = $pdo->query('SELECT * FROM pref');
echo "<h1>都道府県リスト</h1>";
echo "<table border='1' cellpadding='8'>";
echo "<tr>";
// カラム名の表示
$columnCount = $stmt->columnCount();
for ($i = 0; $i < $columnCount; $i++) {
$col = $stmt->getColumnMeta($i);
echo "<th>" . htmlspecialchars($col['name']) . "</th>";
}
echo "</tr>";
// データの表示
foreach ($stmt as $row) {
echo "<tr>";
foreach ($row as $value) {
echo "<td>" . htmlspecialchars($value) . "</td>";
}
echo "</tr>";
}
echo "</table>";
} catch (PDOException $e) {
echo "❌ DB接続またはクエリ失敗: " . $e->getMessage();
}
?>
後述するinit.sqlで作成した都道府県のテーブルから情報を取得して表示します。
init.sqlの中身
--都道府県テーブル
CREATE TABLE prefectures(
prefectures_id varchar(2) PRIMARY KEY
,prefectures_name varchar(50)
,regist_date timestamp DEFAULT now()
,update_date timestamp DEFAULT now()
,del_flg smallint DEFAULT 0
);
--市区町村テーブル
CREATE TABLE municipalities(
prefectures_id varchar(2)
,municipalities_id varchar(4)
,municipalities_name varchar(50)
,regist_date timestamp DEFAULT now()
,update_date timestamp DEFAULT now()
,del_flg smallint DEFAULT 0
,FOREIGN KEY(prefectures_id) REFERENCES prefectures(prefectures_id)
,PRIMARY KEY(prefectures_id,municipalities_id)
);
--都道府県
INSERT INTO prefectures(prefectures_id,prefectures_name) VALUES('01','北海道');
...
--市区町村
INSERT INTO municipalities(prefectures_id,municipalities_id,municipalities_name) VALUES('01','1002','札幌市');
...
用意するDBは前回と同じです。
構成と検証
コンテナの構築
cd [docker-compose.ymlを作成したディレクトリ]
docker compose up -d
動作の検証
docker-compose.ymlで指定したとおり、ブラウザからlocalhost:8080にアクセスして動作を確認します。

無事表示ができてます!

トラブルシューティング
前に作ったコンテナが上書きされたり干渉する?
コンテナ名が以前作ったコンテナを重複していたりすると、不意に鑑賞していつの間にか上書きされていたりします。。。
気づいた時にはぐちゃぐちゃになってしまうので、「docker compose -p プロジェクト名 up -d」とプロジェクト名を区別して構築した方が良さそう。
まとめ
わりと形になってきたのでは?
コンパクトではあるんですが、webシステムの簡単なベースが構築できるまで進みました。
甘いところはあると思いつつ、細かい調整をすることでだいぶ仕上がっていくような感触があります。
docker-compose.ymlで構築しだすと、この便利さが日々身に沁みますね。
最初docker触り出した時も同じ感想でしたが、使い続けるとそのありがたみが増していく感じです。
ここまではwindows環境でやってきたので、次はLinux環境かな。。。