MySQL のインストールはコマンド 1 つで終わります。本当の作業はそのあとです。アプリ用のユーザー、ポート 3306 をインターネットにさらさずに手元のパソコンからデータベースに届く方法、小さなサーバー向けのメモリ設定、そして手をかけなくても回るバックアップ。このガイドでは、この 4 つを Ubuntu 24.04 で扱います。すべての手順を当社の Ubuntu 24.04 イメージで実行し、以下の数値もそのサーバーで測ったものです。
コマンドは sudo を使えるユーザーで実行してください。Ubuntu の初期設定ガイドで作れます。
1. インストールする
sudo apt update
sudo apt install -y mysql-server
mysql --version
当社のサーバーではインストールに 51 秒かかり、MySQL 8.0.46 が入りました。すぐに起動し、起動のたびに自動で立ち上がり、サーバー自身でだけ待ち受けます。通常の接続は 127.0.0.1:3306、MySQL の新しい X プロトコルは 127.0.0.1:33060 です。この時点では外からは何もつながりません。
2. データベースとユーザーを作る
Ubuntu では MySQL の root アカウントがソケット認証を使うので、sudo mysql でパスワードなしにログインできます。アプリ用のデータベースとユーザーを作ります。
sudo mysql
CREATE DATABASE app CHARACTER SET utf8mb4;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'localhost';
EXIT;
アプリが接続するのと同じ方法で確かめます。
mysql -u app -p app -e "SELECT CURRENT_USER();"
app@localhost と表示されれば成功です。パスワードを間違えると ERROR 1045 (28000): Access denied for user 'app'@'localhost' になります。このユーザーは app の中では何でもでき、外のものには一切触れません。
3. 手元のパソコンから接続する:SSH トンネル
DBeaver、MySQL Workbench、mysql コマンドなどのデスクトップクライアントを手元で使う場合も、ポートは開けません。SSH で転送します。
ssh -L 3307:127.0.0.1:3306 deploy@YOUR.SERVER.IP
NAT プランでは -p とダッシュボードの専用 SSH ポートを付けてください。このウィンドウを開いている間、クライアントはホスト 127.0.0.1、ポート 3307、ユーザー app に向けます。手元側を 3307 にしたのは、パソコンで動いているかもしれない MySQL とぶつからないようにするためです。テストでは、トンネル経由ではすぐに応答があり、サーバーのアドレスの 3306 への直接接続は拒否されました。
4. 別のサーバーからの直接アクセス
アプリが 2 台目のサーバーで動いていて、直接つなぐ必要がある場合もあります。その場合、データベース側には専用 IPv4 付きのプランが必要です。NAT プランが転送するのは SSH のポートだけだからです。変更は 3 つで、どれもアプリサーバーのアドレス(ここでは 203.0.113.20)に限定します。
sudo sed -i 's/^bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
sudo ufw allow from 203.0.113.20 to any port 3306 proto tcp
CREATE USER 'app'@'203.0.113.20' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'203.0.113.20';
ufw がまだ有効でなければ、先に SSH を許可(sudo ufw allow OpenSSH)してから sudo ufw enable を実行してください。詳しくは ufw ガイドをご覧ください。
2 つの鍵を別々に確かめました。ファイアウォールのルールはあるが対応する MySQL ユーザーがない状態では、サーバーは error 1130: Host '…' is not allowed to connect to this MySQL server で拒否しました。ユーザーを追加すると接続できました。ファイアウォールのルールを外すと、接続は単にタイムアウトしました。インターネット上のほかのアドレスはすべて、このタイムアウトになります。
5. RAM を節約する
自前のデータがないアイドル状態で、MySQL 8.0 は当社のサーバー上で 383 MB を使っていました。その大半は Performance Schema で、メモリを先に確保する診断機能です。小さな VPS ではこれをオフにし、メインのキャッシュの大きさを自分で決めます。
sudo tee /etc/mysql/mysql.conf.d/zz-small-vps.cnf >/dev/null <<'EOF'
[mysqld]
performance_schema = OFF
innodb_buffer_pool_size = 256M
max_connections = 50
EOF
sudo systemctl restart mysql
ps -o rss= -C mysqld
再起動後は 165 MB になりました。buffer pool はデータとインデックスをキャッシュするもので、アプリも同居する 2 GB のサーバーなら 256 MB が目安です。データベースがサーバーの主役で、キャッシュより大きくなったら増やしてください。max_connections = 50 は、コネクションプールを使うアプリ 1 つには十分すぎる値です。performance_schema の統計は使えなくなるので、遅いクエリを詳しく調べる必要が出たら元に戻してください。
6. 毎晩のバックアップ
mysqldump --single-transaction は、アプリを止めずに InnoDB テーブルの一貫したコピーを取ります。小さなスクリプトにまとめます。
sudo tee /usr/local/bin/mysql-backup >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
mkdir -p /var/backups/mysql
mysqldump --single-transaction --routines --triggers app | gzip > /var/backups/mysql/app-$(date +%F).sql.gz
find /var/backups/mysql -name 'app-*.sql.gz' -mtime +14 -delete
EOF
sudo chmod 755 /usr/local/bin/mysql-backup
echo '0 3 * * * root /usr/local/bin/mysql-backup' | sudo tee /etc/cron.d/mysql-backup
sudo /usr/local/bin/mysql-backup && sudo ls -l /var/backups/mysql
各行には理由があります。
umask 077で、ダンプを root だけが読めるようにします(-rw-------)。全データが入っているからです。pipefailで、mysqldumpが失敗したらスクリプト全体も失敗します。これがないと、gzipが中身のない小さなアーカイブを書いて成功と報告してしまいます。わざとコマンドを壊して試したところ、スクリプトは想定どおりコード 2 で終了しました。find … -mtime +14 -deleteで、2 週間分のコピーを残します。- スクリプトは root で動くので、
mysqldumpはソケットでログインし、パスワードをファイルに置かずに済みます。
一度も戻したことのないバックアップは、まだバックアップとは言えません。一時的なデータベースに復元して、中身を確かめましょう。
sudo mysql -e "CREATE DATABASE app_restore"
gunzip -c /var/backups/mysql/app-2026-10-25.sql.gz | sudo mysql app_restore
sudo mysql -e "SHOW TABLES FROM app_restore"
sudo mysql -e "DROP DATABASE app_restore"
テストでは、復元したテーブルに元と同じ行が入っていました。同じディスク上のコピーでは、サーバーを失ったときに守れません。ときどき scp や restic で別のマシンに取り出してください。Managed Backups を使えば、サーバー全体の毎日の復元ポイントがさらに加わります。
どのプランを選ぶか
Micro(2 vCPU、2 GB、25 GB、月 $5)なら、上のように調整した MySQL と Web アプリを載せられます。データベース自体が数 GB を超えたら、4 GB、35 GB で月 $8 の Small にして buffer pool を 1 GB 以上にできます。どちらも NAT プランで、手順 3 の SSH トンネルはそのまま使えます。手順 4 には専用 IPv4 が必要で、Micro-IP は月 $10 です。
PostgreSQL のほうがよければ、PostgreSQL ガイドが同じ流れで説明しています。すべてのプランは VPS にあり、支払いは Base、Ethereum、Polygon 上の USDT、USDC、ETH です。
コメント
まだコメントはありません。最初になりましょう。