ボタン1つでさくらに更新を反映
— デプロイアプリを作った記録
これまで、サイトを更新するたびに「送る用フォルダを作る」「scp でサーバーに送る」「SSH でログインしてコマンドを打つ」という手順を毎回繰り返していました。その手間を減らすため、さくらサーバー用の「ボタン1つでデプロイする」アプリを作り、今日までに起きたトラブルと解決策を具体的にまとめます。
1. これまでの手間:更新のたびに3段階の作業
「デプロイの記録」で書いたように、さくらのVPSには scp でプログラムを送り、サーバー上で venv や gunicorn を扱う形で公開しています。コードを直すたびに、次のような流れを手動でやっていました。
- 自分のPCで PowerShell を開き、build_deploy_bundle.ps1 を実行して「送る用フォルダ」(make-001-deploy)を作る。
- 同じ PowerShell で scp -r make-001-deploy ubuntu@サーバーIP:~ を実行。パスワードを入力して転送が終わるまで待つ。
- もう一つの PowerShell でサーバーに SSH ログインし、rm -rf make-001 や mv make-001-deploy make-001、venv の作り直し、systemctl restart などを1行ずつ打つ。
コマンドを打ち間違えたり、手順を忘れたりするリスクもあり、「更新のたびにこの手間を繰り返すのはつらい」と感じていました。
2. ボタン1つでデプロイするアプリを作った
AIアシスタントに「さくらにボタン一つで更新ファイルをアップロードするアプリがほしい」と依頼し、次のような構成で用意してもらいました。
- deploy_launcher.py … ダブルクリックで起動するウィンドウ。中央に「デプロイする」ボタンがあり、押すと 1/3 バンドル作成 → 2/3 scp アップロード → 3/3 サーバー上で差し替え・再起動まで一気に実行する。
- deploy_one_click.ps1 … 実際にバンドル作成・scp・ssh を実行する PowerShell スクリプト。ランチャーから呼ばれる。
- deploy_config.json … サーバーの host・user・サービス名を書いておく設定ファイル。
「デプロイする」を1回押し、パスワードを聞かれたら入力するだけなので、手動で3段階の作業をしなくてよくなり、更新の手間が大きく減りました。
3. 遭遇したトラブルと解決策
運用していくうちに、いくつか重大な問題や表示の不具合にぶつかり、その都度修正を入れました。
3.1 「AI生成ファイル紹介」の登録データが消えた
事象:デプロイアプリで更新したあと、サイトの「AI生成ファイル紹介」に登録されていた作品情報がすべて消えていた。
原因:サーバー側の処理で rm -rf make-001 のあと mv make-001-deploy make-001 としており、サーバーにあった make-001/data/(shared_files.db と shared_uploads フォルダ)がまとめて削除されていた。送るバンドルには「空の data/」しか含まれておらず、上書きで既存の登録データが失われていた。
対応:3/3 のサーバー用スクリプトを変更。「差し替えの前」に make-001/data を make-001-data-backup に退避し、「差し替えの後」にそのバックアップを make-001/data に戻すようにした。これでデプロイを繰り返しても、登録作品情報は消えなくなった。
3.2 デプロイは成功したのに Web に反映されない・サービスが起動しない
事象:「デプロイが完了しました」と表示されるが、ブラウザでサイトを開いても更新が一切反映されない。サーバーで systemctl status aiaicursor を確認すると、Active: activating (auto-restart) や Failed with result 'exit-code' となっていた。
原因:ログに Address already in use(ポート 5000 が使用中) と出ていた。以前の gunicorn プロセスが残ったままだったため、新しい gunicorn が 5000 番にバインドできず、起動に失敗し続けていた。
対応:デプロイスクリプトのサーバー側で、サービスを止めたあとに pkill -9 -f gunicorn で gunicorn をすべて終了し、sleep 4 でポートが空くのを待ってから systemctl start するようにした。手動で対処する場合は、サーバーで sudo systemctl stop aiaicursor → pkill -9 -f gunicorn → sleep 3 → sudo systemctl start aiaicursor の順で実行する。
3.3 「更新」の日時だけ変わり、その他の変更が画面に反映されない
事象:デプロイ後、画面で変わるのは「更新: 2026-03-02 17:20」のような日時だけで、テンプレートや機能の変更が一切反映されていないように見えた。
原因(1):デプロイの 1/3 が終わった時点でスクリプトが終了しており、2/3(scp)と 3/3(サーバー処理)が実行されていなかった。バンドル作成直後の終了コード判定で誤って終了していた。
対応:終了コードで即終了する条件をやめ、「make-001-deploy フォルダが存在するか」だけを見て 2/3 に進むように変更した。
原因(2):編集したファイルを保存せずに「デプロイする」を押しており、バンドルに古いコードが含まれていた。
対応:ランチャーに「変更したファイルは先に保存してから」という注意を表示(実行開始時のログに表示)。デプロイ前に「すべて保存」する習慣をつけると防げる。
あわせて、HTML をキャッシュしないように app.py に Cache-Control: no-store, no-cache を付与し、デプロイ後にブラウザで古いキャッシュが表示されにくくした。
3.4 3/3 のサーバー処理で「set: command not found」「cd: $'~\r': No such file or directory」
事象:2/3 まで進んだあと、3/3 でサーバーに渡したスクリプトが bash で実行されると set: command not found や cd: $'~\r': No such file or directory といったエラーになり、デプロイが失敗する。
原因:PowerShell から ssh にスクリプトを渡す際、(1) 文字コードの先頭に BOM(バイト順マーク)が付き、set が set と解釈されていた。(2) 改行が Windows の CRLF(\r\n)のまま渡り、bash 側で cd ~ が cd ~\r のように解釈されていた。
対応:スクリプト送信前に、BOM を除去し、CRLF を LF に変換してから ssh に渡すように変更。あわせて、PowerShell の標準出力エンコーディングを BOM なし UTF-8 に統一した。
3.5 「sudo: a terminal is required to read the password」で 3/3 が失敗
事象:3/3 で sudo systemctl start aiaicursor を実行する際、ssh 経由ではパスワードを入力する画面(TTY)がないため、sudo がパスワードを聞けずにエラーで終了する。
対応:サーバー側で初回だけ、sudo visudo を実行し、次の1行を追加した。
ubuntu ALL=(ALL) NOPASSWD: /bin/systemctl start aiaicursor, /bin/systemctl stop aiaicursor
(ubuntu は SSH でログインするユーザー名に合わせる。)これで、デプロイスクリプトから sudo -n systemctl start aiaicursor を実行してもパスワードなしで通るようになった。
3.6 ランチャーの「デプロイする」ボタンがつぶれて見えない・起動するとすぐ消える
事象:deploy_launcher.py をダブルクリックすると、ボタンが極端に細長くつぶれて文字が読めない。別の環境では、起動直後にウィンドウが閉じてしまう。
原因:レイアウトの順序で、ボタンを作る時点では do_deploy がまだ定義されておらず、NameError でクラッシュしてウィンドウが閉じていた。また、ログ領域が expand で下まで伸び、ボタンに割り当てられる高さがほとんどなくなってつぶれていた。
対応:do_deploy と append を先に定義し、そのあとでボタンを作成するように並べ替えた。ボタンには height=2 と width=18 を指定して最低サイズを確保し、ボタン上の注意文は削除して表示をすっきりさせた。
4. いまの運用:ボタン1つで完了
上記の修正の結果、次のように運用できるようになりました。
- 初回だけ:サーバーで visudo の NOPASSWD 1行を追加。必要なら「更新を反映する手順.md」のとおりに SSH キーを登録し、パスワード入力も省略可能にする。
- 通常の更新時:変更を保存したあと、deploy_launcher.py を起動して「デプロイする」を1回押す。パスワードを聞かれたら入力(SSH キーを設定済みなら不要)。DEPLOY_OK と Done. が出たら完了。ブラウザで https://aiaicursor.com を Ctrl+Shift+R で確認する。
「AI生成ファイル紹介」の登録データは、デプロイのたびに data/ を退避・復元しているため消えません。毎回の更新が、以前のような手動の3段階作業ではなく、ボタン1つで済むようになり、手間が大きく減りました。
「デプロイの記録」では、さくらに初めてデプロイしたときの流れ(scp、venv、gunicorn、nginx、HTTPS、systemd)を書いています。ここでは、その後の「更新を楽にする」ためにデプロイアプリを導入し、起きたトラブルと対処をまとめました。
← 立ち上げストーリー
← プログラム構築の記録
← デプロイの記録
← デプロイでまたハマった話
← ログイン設定の記録
← 改善記録
← ファイル紹介の使い方
← OGP・SEOの記録
← 統合ログインの設計・経緯
← Search Console・サイトマップ
← 環境変数・.env の管理
← Git 入門・インストール
← インストール後に Git で行う設定
← カード神経衰弱の記録
← 異世界シューティングの記録
← 異世界シューティングの難易度
← 異世界戦記(全画面・迷路レイアウト)の記録
← 複数人でのゲーム進行
← 異世界衰弱(不具合の修正)
← 異世界衰弱(機能別フローチャート)
← 異世界ポイントの活用について
← 異世界ポイント市場の実装記録