”今”から始めるdocker入門 PHP+PostgreSQL+Apache環境の構築!

前回の内容で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にアクセスして動作を確認します。

無事表示ができてます!

DBの初期構築が遅いことによって接続エラーが出る場合があります。。。

トラブルシューティング

前に作ったコンテナが上書きされたり干渉する?

コンテナ名が以前作ったコンテナを重複していたりすると、不意に鑑賞していつの間にか上書きされていたりします。。。
気づいた時にはぐちゃぐちゃになってしまうので、「docker compose -p プロジェクト名 up -d」とプロジェクト名を区別して構築した方が良さそう。

まとめ

わりと形になってきたのでは?

コンパクトではあるんですが、webシステムの簡単なベースが構築できるまで進みました。
甘いところはあると思いつつ、細かい調整をすることでだいぶ仕上がっていくような感触があります。

docker-compose.ymlで構築しだすと、この便利さが日々身に沁みますね。
最初docker触り出した時も同じ感想でしたが、使い続けるとそのありがたみが増していく感じです。

ここまではwindows環境でやってきたので、次はLinux環境かな。。。

スポンサーリンク
おすすめの記事