はじめに
DockerでLAMP環境を構築する場合の備忘録です。
ToDoリストを表示するアプリです。
環境変数を使用する場合
ディレクトリ構成
$ ls -Ra
.:
. .. .env Dockerfile compose.yaml db src
./db:
. .. init
./db/init:
. .. init.sql
./src:
. .. todo_list.php
ファイル
.env 環境変数の値を記述する
MYSQL_ROOT_PASSWORD=rootpass
MYSQL_DATABASE=example_database
MYSQL_USER=example_user
MYSQL_PASSWORD=password
MYSQL_TABLE=todo_list
Dockerfile apacheを含むPHPを使用
FROM php:8.5.2-apache
RUN apt update && apt install -y libonig-dev && docker-php-ext-install pdo_mysql
compose.yaml
services:
db:
image: mysql:9.5.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
TZ: Asia/Tokyo
LANG: ja_JP.UTF-8
LC_ALL: ja_JP.UTF-8
command:
--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
volumes:
- db-data:/var/lib/mysql
- ./db/init:/docker-entrypoint-initdb.d
php:
build: .
depends_on:
- db
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_TABLE: ${MYSQL_TABLE}
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
volumes:
db-data:
MySQLの日本語対応のため
TZ: Asia/Tokyo
LANG: ja_JP.UTF-8
LC_ALL: ja_JP.UTF-8
command:
--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
データベースの初期設定のため
- ./db/init:/docker-entrypoint-initdb.d
init.sql データベースの初期化用のコマンド
CREATE DATABASE IF NOT EXISTS example_database;
use example_database;
CREATE TABLE IF NOT EXISTS todo_list(
item_id INT AUTO_INCREMENT,
content VARCHAR(255),
PRIMARY KEY(item_id)
);
INSERT INTO todo_list (content) VALUES ("消しゴムを買う");
INSERT INTO todo_list (content) VALUES ("銀行で家賃を振り込む");
INSERT INTO todo_list (content) VALUES ("洗濯機の修理を依頼する");
todo_list.php
<?php
$user = getenv('MYSQL_USER');
$password = getenv('MYSQL_PASSWORD');
$database = getenv('MYSQL_DATABASE');
$table = getenv('MYSQL_TABLE');
$dsn = "mysql:host=db;dbname={$database};charset=utf8";
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ToDoリスト</title>
</head>
<body>
<div>
<?php
try {
$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM $table";
$stm = $pdo->prepare($sql);
$stm->execute();
$result = $stm->fetchAll(PDO::FETCH_ASSOC);
echo "<table border='1'>";
echo "<thead><tr>";
echo "<th>", "ID", "</th>";
echo "<th>", "ToDo", "</th>";
echo "</tr></thead>";
echo "<tbody>";
foreach ($result as $row){
echo "<tr>";
echo "<td>", $row['item_id'], "</td>";
echo "<td>", $row['content'], "</td>";
echo "</tr>";
}
echo "</tbody>";
echo "</table>";
} catch (Exception $e) {
echo '<span class="error">エラーがありました。</span><br>';
echo $e->getMessage();
exit();
}
?>
</div>
</body>
</html>
パスワードにsecretsを使用する場合
ディレクトリ構成
$ ls -Ra
.:
. .. .env Dockerfile compose.yaml db mysql_password.txt mysql_root_password.txt src
./db:
. .. init
./db/init:
. .. init.sql
./src:
. .. dbsample.php todo_list.php
ファイル
.env 環境変数の値を記述する
MYSQL_DATABASE=example_database
MYSQL_USER=example_user
MYSQL_TABLE=todo_list
Dockerfile apacheを含むPHPを使用
FROM php:8.5.2-apache
RUN apt update && apt install -y libonig-dev && docker-php-ext-install pdo_mysql
compose.yaml
services:
db:
image: mysql:9.5.0
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD_FILE: /run/secrets/mysql_password
TZ: Asia/Tokyo
LANG: ja_JP.UTF-8
LC_ALL: ja_JP.UTF-8
command:
--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
secrets:
- mysql_password
- mysql_root_password
volumes:
- db-data:/var/lib/mysql
- ./db/init:/docker-entrypoint-initdb.d
php:
build: .
depends_on:
- db
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD_FILE: /run/secrets/mysql_password
MYSQL_TABLE: ${MYSQL_TABLE}
secrets:
- mysql_password
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
volumes:
db-data:
secrets:
mysql_password:
file: ./mysql_password.txt
mysql_root_password:
file: ./mysql_root_password.txt
init.sql データベースの初期化用のコマンド
CREATE DATABASE IF NOT EXISTS example_database;
use example_database;
CREATE TABLE IF NOT EXISTS todo_list(
item_id INT AUTO_INCREMENT,
content VARCHAR(255),
PRIMARY KEY(item_id)
);
INSERT INTO todo_list (content) VALUES ("消しゴムを買う");
INSERT INTO todo_list (content) VALUES ("銀行で家賃を振り込む");
INSERT INTO todo_list (content) VALUES ("洗濯機の修理を依頼する");
todo_list.php
<?php
$password_file = getenv('MYSQL_PASSWORD_FILE');
$user = getenv('MYSQL_USER');
$password = rtrim(file_get_contents($password_file));
$database = getenv('MYSQL_DATABASE');
$table = getenv('MYSQL_TABLE');
$dsn = "mysql:host=db;dbname={$database};charset=utf8";
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ToDoリスト</title>
</head>
<body>
<div>
<?php
try {
$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM $table";
$stm = $pdo->prepare($sql);
$stm->execute();
$result = $stm->fetchAll(PDO::FETCH_ASSOC);
echo "<table border='1'>";
echo "<thead><tr>";
echo "<th>", "ID", "</th>";
echo "<th>", "ToDo", "</th>";
echo "</tr></thead>";
echo "<tbody>";
foreach ($result as $row){
echo "<tr>";
echo "<td>", $row['item_id'], "</td>";
echo "<td>", $row['content'], "</td>";
echo "</tr>";
}
echo "</tbody>";
echo "</table>";
} catch (Exception $e) {
echo '<span class="error">エラーがありました。</span><br>';
echo $e->getMessage();
exit();
}
?>
</div>
</body>
</html>
環境変数 MYSQL_PASSWORD_FILEにパスワードファイルのパスを設定しているので、そのファイルからパスワードを読み出す。
$password_file = getenv('MYSQL_PASSWORD_FILE');
$password = rtrim(file_get_contents($password_file));