こんにちは
もう年の瀬ですね
年末年始で時間があるので、Dockerをもう一度勉強したいと思っています
なので、今回はあえてVM上にdocker-composeを利用して、独自ドメインでWebサイトを公開する流れを書いてみます
(つい先日までサーバー上にyumなどでApacheなどのwebサーバーを別途インストールしないと、DockerでNginxイメージを利用していても、Webサイトを外部公開できないと思っていたのは内緒
■環境
プラットフォーム:Vagrant
VM:AlmaLinux9
Web構成:Nginx + PHP-FPM + MySQL
ドメイン:www.example.com
■手順
※前提としてVagrantでAlmaLinux9のサーバーを1台構築しておいてください
1. git のインストール
※使わないですが念のためインストールしています
dnf install git
2. dockerのインストール
・レポジトリの追加
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
・docker-ce のインストール
sudo dnf -y install docker-ce docker-ce-cli containerd.io
・バージョンの確認
docker --version
→ Docker version 29.1.3 のように出力されればOK
・docker の起動
sudo systemctl start docker
・自動化設定
sudo systemctl enable docker
・起動確認
systemctl status docker
→ active (running) になっていればOK
3. docker-composeのインストール
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
・実行権限の付与
sudo chmod +x /usr/local/bin/docker-compose
・バージョン確認
/usr/local/bin/docker-compose --version
→ Docker Compose version v5.0.1 のように出力されればOK
4. docker-composeの作成
全体のディレクトリ構成は下記です
※かなり長いので読み飛ばしていただいて問題ございません
.
├── README.md
├── app
│ ├── Dockerfile
│ ├── conf
│ │ ├── disable_display_error.ini
│ │ └── zz-docker.conf
│ └── src
│ ├── common
│ │ └── db_connect.php
│ ├── css
│ │ └── user_list.css
│ ├── get_all_users.php
│ └── index.php
├── db
│ ├── Dockerfile
│ ├── conf
│ │ └── my.cnf
│ ├── data
│ └── sql
│ └── init.sql
├── docker-compose.yml
└── web
├── Dockerfile
└── conf
└── www.example.com.conf
docker-compose.yml
version: "3.9"
services:
web01:
build:
context: ./
dockerfile: web/Dockerfile
container_name: web01-container
volumes:
- ./app/src:/var/www/vhosts/www.example.com/public_html
depends_on:
- app01
ports:
- "80:80"
app01:
build:
context: ./
dockerfile: app/Dockerfile
container_name: app01-container
volumes:
- ./app/src:/var/www/vhosts/www.example.com/public_html
restart: always
ports:
- "9000:9000"
db01:
build:
context: ./
dockerfile: db/Dockerfile
container_name: db01-container
env_file: .env/db_env_file
restart: always
volumes:
- ./db/data:/var/lib/mysql
- ./db/conf/my.cnf:/etc/my.cnf
ports:
- "3307:3306"
./env/db_env_file
MYSQL_ROOT_PASSWORD=Testtest991!
→ MySQLコンテナのrootユーザー用パスワードを記載しています
app/Dockerfile
FROM php:8.0.30-fpm
#php.ini用confファイルコピー
COPY ./app/conf/disable_display_error.ini /usr/local/etc/php/conf.d/
#php-fpm用confファイルコピー
COPY ./app/conf/zz-docker.conf /usr/local/etc/php-fpm.d/
RUN groupmod -g 1000 www-data
RUN usermod -u 1000 www-data
#ドキュメントルート作成
RUN apt-get update -y && \
apt-get install -y vim less && \
docker-php-ext-install pdo_mysql && \
mkdir -p /var/www/vhosts/www.example.com/public_html
COPY ./app/src /var/www/vhosts/www.example.com/public_html
# ユーザー切り替え
USER www-data
#作業ディレクトリ設定
WORKDIR /var/www/vhosts/www.example.com/public_html
#ポート開放
EXPOSE 9000
→ php-fpm用のDockerfileとなり、ドキュメントルート(/var/www/vhosts/www.example.com/public_html)の作成などを実行しています
app/conf/disable_display_error.ini
display_errors = Off log_errors = true
→ phpのエラー内容がブラウザ上に出力されないようにしています
app/conf/zz-docker.conf
[global] daemonize = no [www] listen = 9000 pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 35
→ php-fpmのチューニング用confファイルです
app/src/common/db_connect.php
<?php
const DSN = 'mysql:host=db01;dbname=test_db';
const USERNAME = 'root';
const PASSWORD = 'Testtest991!';
try {
function db_connect(){
$dbh = new PDO(DSN,USERNAME, PASSWORD, [
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]);
return $dbh;
}
} catch (PDOException $e) {
echo 'ERROR: Could not connect'.$e->getMessage();
}
→ MySQLコンテナへ接続するためのコードです
app/src/css/user_list.css
body {
margin: 0;
font-family: 'Segoe UI', sans-serif;
background-color: #f5f5f5;
display: flex;
justify-content: center;
padding: 40px 0;
}
/* コンテナ */
.container {
background: #fff;
padding: 30px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
width: 90%;
max-width: 800px;
}
/* 見出し */
h2 {
margin: 0 0 20px;
font-size: 24px;
color: #333;
text-align: center;
}
/* テーブル */
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
thead th {
background-color: #f0f0f0;
padding: 10px;
font-weight: 600;
text-align: left;
border-bottom: 2px solid #ddd;
}
tbody td {
padding: 10px;
border-bottom: 1px solid #eee;
}
tbody tr:hover {
background-color: #fafafa;
}
→ 最低限のcssですが、なくても問題ないです
app/src/get_all_users.php
<?php
//DBへ接続
require_once "./common/db_connect.php";
$dbh = db_connect();
//すべてのユーザーを取得
$sql = ("SELECT * FROM users ORDER BY id DESC");
$stmt = $dbh->prepare($sql);
$stmt->execute();
$users = $stmt->fetchAll();
?>
→ MySQLコンテナへ接続し、登録済みのユーザー情報を取得しています
app/src/index.php
<?php session_start();
//ユーザー一覧を取得
require_once './get_all_users.php';
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ユーザー一覧ページ</title>
<link rel="stylesheet" href="./css/user_list.css">
</head>
<body>
<div class="container">
<h2>ユーザー一覧</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>ユーザー名</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td><?= htmlspecialchars($user['id']) ?></td>
<td><?= htmlspecialchars($user['name']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</body>
</html>
→ 独自ドメインでアクセスすると表示される画面であり、dbから取得したユーザーIDと名前が表示されるようにしています
db/Dockerfile
FROM mysql:8.0 COPY db/sql /docker-entrypoint-initdb.d COPY db/conf/my.cnf /etc/my.cnf EXPOSE 3306
→ 3306番ポートでMySQLを公開するようにしており、後述する init.sql ファイルをコンテナ内にコピーすることで、コンテナ起動時に自動的にDBの作成やデータの投入を実行しています
db/conf/my.cnf
# For advice on how to change settings please see # http://dev.mysql.com/doc/refman/8.0/en/server-configuration-defaults.html [mysqld] # # Remove leading # and set to the amount of RAM for the most important data # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. # innodb_buffer_pool_size = 128M # # Remove the leading "# " to disable binary logging # Binary logging captures changes between backups and is enabled by # default. It's default setting is log_bin=binlog # disable_log_bin # # Remove leading # to set options mainly useful for reporting servers. # The server defaults are faster for transactions and fast SELECTs. # Adjust sizes as needed, experiment to find the optimal values. # join_buffer_size = 128M # sort_buffer_size = 2M # read_rnd_buffer_size = 2M # # Remove leading # to revert to previous value for default_authentication_plugin, # this will increase compatibility with older clients. For background, see: # https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_default_authentication_plugin default-authentication-plugin=mysql_native_password datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid #sql_mode='' sql_mode='NO_ENGINE_SUBSTITUTION' log-error=/var/log/mysqld_error.log general_log general_log_file=/var/log/mysqld_general.log
→ MySQL用のconfファイルです
db/data
→ データ永続化のためにMySQLコンテナのDBディレクトリ配下をローカルにbindマウントしています
db/sql/init.sql
CREATE DATABASE test_db; CREATE TABLE test_db.users (id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, name VARCHAR(50) NOT NULL); INSERT INTO test_db.users (id, name) VALUES (1, 'test01'); INSERT INTO test_db.users (id, name) VALUES (2, 'test02'); INSERT INTO test_db.users (id, name) VALUES (3, 'test03'); INSERT INTO test_db.users (id, name) VALUES (4, 'test04');
→DBとテーブルの作成、および初期データを投入しています
web/Dockerfile
FROM nginx:1.25.0 #confファイルのコピー COPY ./web/conf/www.example.com.conf /etc/nginx/conf.d #ドキュメントルート作成 RUN mkdir -p /var/www/vhosts/www.example.com/public_html EXPOSE 80
→ nginxコンテナを作成しています
web/conf/www.example.com.conf
server {
listen 80;
server_name www.example.com;
root /var/www/vhosts/www.example.com/public_html;
index index.php;
access_log /var/log/nginx/www.example.com_access.log main;
error_log /var/log/nginx/www.example.com_error.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
index index.php;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass app01:9000;
}
}
→ www.example.com で独自ドメインを設定しており、.php 拡張子のファイルはphp-fpm用コンテナ(app01)へプロキシするようにしています
5. docker-compose の起動
・Dockerfileのビルド
docker-compose build --no-cache
→ 初回ビルドなので –no-cache は不要ですが、念のためつけています
・起動
docker-compose up -d
→ VMのスペックによってはかなり時間がかかるかもしれません
・確認
docker container ps -a
→ nginx_php-fpm_mysql_docker のプレフィックスがついたコンテナが3種類起動していればOKです
6. ブラウザから確認
・ローカルのhostsファイルで名前解決
[VMのIPアドレス] www.example.com
・ブラウザからアクセス
http://www.example.com/
→下記のように独ドメインでアクセスできること + DB内のユーザー情報が画面上の表示されていればOK
■まとめ
いかがでしたでしょうか?
最近では基本的にはECSなどのマネージドサービスを利用した公開が多いかと思いますが、まだまだVM上に直接公開していることもあると思うので、その際にこの記事が何かの助けになれば幸いです
