サーバー作業を自動化する魔法の杖:PythonのFabricでスマートにデプロイをこなそう
![]()
【Hiroki】
Yukiさん、こんにちは!
最近、自分で作ったWebアプリをVPS(仮想専用サーバー)にデプロイしてみたんですけど、毎回ターミナルを開いて、SSHでログインして、git pullして、サービスを再起動して……という手順を繰り返すのが、少しだけ手間に感じてきました。
これをもっとスマートに、自動化する方法ってないでしょうか?
![]()
【Yuki】
Hirokiくん、こんにちは。デプロイまで自分でやってみるなんて、すごく素敵だと思います。
その「繰り返し」の作業を自動化したいという気持ち、エンジニアとしてはとっても大切な感覚ですね。
そういう時は、PythonのFabricというライブラリを使ってみるのがいいかもしれません。
今日は、Fabricを使って、遠くのサーバーにある「あんなこと」や「こんなこと」を、手元のPCから魔法のように操作する方法をお話ししますね。
![]()
【Hiroki】
Fabric……。なんだか、布とか織物みたいな名前ですね。
Pythonでサーバーを操作できるんですか?
![]()
【Yuki】
ふふ、名前の由来は「糸(Thread)」を織りなすように複数のサーバーを管理する……というところから来ているのかもしれませんね。
Fabricは、一言で言うと「SSH経由でコマンドをプログラムから実行するためのライブラリ」です。
通常、僕たちはTeraTermやターミナルを使って手動でコマンドを打ち込みますが、Fabricを使えば「どのサーバーで、どんなコマンドを、どんな順番で実行するか」をPythonコードとして書き留めておくことができるんです。
![]()
【Hiroki】
なるほど! Pythonでスクリプトを書いておけば、ボタン一つでサーバーが動いてくれるイメージですね。
Fabricのインストールと準備
![]()
【Yuki】
はい、その通りです。まずはFabricを使えるように準備しましょう。
Fabricはサードパーティ製のライブラリなので、pipを使ってインストールする必要があります。
最近のFabricは「Fabric 2」や「Fabric 3」と呼ばれていたものが統合されていますので、普通にfabricを指定すれば大丈夫ですよ。
pip install fabric
![]()
【Hiroki】
インストールできました! これで準備完了ですね。
次はどうすればいいんでしょうか?
![]()
【Yuki】
まずは、一番シンプルな方法から試してみましょうか。
Pythonの対話型シェルや、短いスクリプトで、サーバーに接続してコマンドを一つ実行するだけのコードを書いてみますね。
Connectionオブジェクトでサーバーに繋いでみよう
![]()
【Yuki】
Fabricの基本は、Connection というクラスを使うことです。
これを使って、接続先のホスト名やユーザー名を指定します。
from fabric import Connection
def check_disk_space():
# 接続情報を設定します
# host にはIPアドレスやドメイン名を入れます
c = Connection(host="your-server-address.com", user="hiroki")
# サーバー上でコマンドを実行します
result = c.run("df -h", hide=True)
print(f"サーバーからの応答です:\n{result.stdout}")
if __name__ == "__main__":
check_disk_space()
![]()
【Hiroki】
わあ、たったこれだけでサーバーのディスク使用量が見られるんですね。
c.run("df -h") という部分が、実際にサーバーに送られるコマンドですね?
![]()
【Yuki】
そうです。hide=True を指定すると、実行時の標準出力を画面にそのまま出さずに、変数として受け取ることができます。
こうすることで、取得した結果をPython側で加工したり、エラーチェックをしたりすることもできるんです。
あ、接続する時にパスワードが必要な場合は、connect_kwargs という引数で渡すこともできますが、できればSSH鍵を設定しておくのが一番安全で、Fabricも使いやすくなると思います。
![]()
【Hiroki】
SSH鍵……。以前設定した気がします! それならスムーズに動かせそうです。
でも、毎回ホスト名やユーザー名をコードに書くのは、ちょっと面倒な気がしますね……。
![]()
【Yuki】
そうですよね。そこで登場するのが、fabfile.py と fabコマンド です。
これを使うと、もっと本格的な「自動化ツール」らしくなりますよ。
fabfile.py でタスクを定義する
![]()
【Yuki】
カレントディレクトリに fabfile.py という名前のファイルを作ってみてください。
そこに、実行したい処理を「タスク」として定義していきます。
タスクというのは、ただのPythonの関数なんですよ。
from fabric import task
@task
def hello(c):
print("手元のPCで実行しています")
c.run("echo 'これはリモートサーバーで実行されています'")
@task
def update_app(c):
# アプリのディレクトリに移動して git pull する想定です
with c.cd("/var/www/my-app"):
c.run("git pull origin main")
c.run("systemctl restart my-web-service")
![]()
【Hiroki】
@task というデコレータがついているんですね。
引数にある c は何ですか?
![]()
【Yuki】
この c は、先ほどの Connection オブジェクトが自動的に渡される場所です。
そして、このファイルを保存した場所で、ターミナルから fab コマンドを叩きます。
fab -H your-server-address.com hello
![]()
【Hiroki】
おっ、実行されました! -H でホストを指定して、その後にタスク名の hello を書くんですね。
これなら、複数のタスクを順番に実行するのも簡単そうです。
![]()
【Yuki】
はい。with c.cd("/path/to/dir"): のように書くことで、そのブロックの中だけディレクトリを移動した状態でコマンドを実行できるのも便利ですよね。
手動だと cd し忘れて失敗することもありますけど、プログラムならそんな心配もありません。
複数のサーバーを同時に操作する
![]()
【Hiroki】
Yukiさん、もしサーバーが2台や3台に増えた場合はどうすればいいんでしょうか?
一台ずつコマンドを叩くのはやっぱり大変ですよね。
![]()
【Yuki】
その質問、待っていました。Fabricの得意分野です。
SerialGroup や ThreadingGroup というクラスを使うと、複数のサーバーに対して一斉に処理を行うことができるんです。
例えば、3台のウェブサーバー全てでログを確認したい時は、こんな風に書けます。
from fabric import ThreadingGroup
def update_all_servers():
hosts = ["web1.example.com", "web2.example.com", "web3.example.com"]
group = ThreadingGroup(*hosts, user="hiroki")
# 全てのサーバーで同時に uptime コマンドを実行
results = group.run("uptime")
for connection, result in results.items():
print(f"{connection.host}: {result.stdout.strip()}")
![]()
【Hiroki】
ThreadingGroup……。スレッドを使って並列に実行してくれるんですね!
これならサーバーが10台あっても、一瞬で作業が終わってしまいそうです。
![]()
【Yuki】
ふふ、そうですね。
Fabricのようなツールは、誰かの作業を少しだけ楽にするために作られています。
そんな「誰かの役に立つために生まれた小さなツール」の歴史を見ると、なんだか心が温かくなるんです……。
自分が書いたコードが、遠くのサーバーで一生懸命動いているのを見ると、少しだけ、自分もそのサーバーの一部になれたような、不思議な気持ちになりませんか?
![]()
【Hiroki】
あ……。確かに、自分のプログラムがどこか遠くで誰かのために動いているって思うと、なんだかワクワクします。
Yukiさんも、そんな風に思ったりするんですね。
![]()
【Yuki】
ええ、……あ、いえ、ただの独り言です。
話を戻しましょうか。Fabricには他にも便利な機能があるんですよ。
ファイルの転送(putとget)
![]()
【Hiroki】
コマンドの実行だけじゃなくて、ファイルのやり取りもできるんですか?
例えば、設定ファイルをローカルで編集して、サーバーにアップロードしたい時とか。
![]()
【Yuki】
もちろん可能です。put と get というメソッドを使います。
scp コマンドをわざわざ別に打つ必要はありません。
@task
def deploy_config(c):
# ローカルの settings.conf をサーバーの /etc/my-app/ にコピー
c.put("settings.conf", remote="/etc/my-app/settings.conf")
# 念のため、アップロードした後にパーミッションを変更
c.run("chmod 644 /etc/my-app/settings.conf")
![]()
【Hiroki】
すごい、本当に万能ですね!
逆に、サーバーにあるログファイルをローカルに持ってくる時は get を使えばいいんですね。
![]()
【Yuki】
その通りです。
c.get(remote="/var/log/nginx/access.log", local="logs/access.log") のように書けば、手元にログを保存してじっくり解析することもできます。
エラー処理と柔軟な構成
![]()
【Hiroki】
でも、もしコマンドが失敗したらどうなるんでしょう?
例えば git pull がコンフリクトで止まっちゃった時とか……。
![]()
【Yuki】
いいところに気づきましたね。
デフォルトでは、Fabricは実行したコマンドがエラー(終了ステータスが0以外)を返すと、そこで処理を中断してしまいます。
でも、エラーが起きても無視して進めたい場合や、エラーの内容によって処理を分けたい場合もありますよね。
from fabric import task
from invoke import UnexpectedExit
@task
def safe_check(c):
try:
# 存在しないディレクトリに移動しようとしてみる
c.run("cd /non_existent_dir")
except UnexpectedExit as e:
print("エラーが発生しましたが、キャッチして処理を続行します")
print(f"エラー内容: {e}")
# あるいは warn=True を使うと例外を投げずに結果オブジェクトを返します
result = c.run("ls /tmp/missing_file", warn=True)
if result.failed:
print("ファイルが見つかりませんでしたが、想定内です")
![]()
【Hiroki】
warn=True を使うと、プログラムを止めずに進められるんですね。
これなら複雑な条件分岐も作れそうです。
Fabricと他のツールの使い分け
![]()
【Hiroki】
Yukiさん、少し気になったんですけど、「Ansible」とか「Terraform」といったツールもサーバー構成管理でよく聞きますよね。
Fabricとはどう違うんでしょうか?
![]()
【Yuki】
それはとても鋭い質問です。
Ansibleなどは「宣言型」といって、「サーバーがどういう状態であるべきか(このパッケージがインストールされている、このユーザーがいる、など)」を定義するのに向いています。
一方でFabricは「命令型」といって、「この手順で、このコマンドを実行して」という、スクリプト的な動きをさせるのが得意なんです。
![]()
【Hiroki】
なるほど。
「サーバーを新しく構築する」のはAnsible、「日々のデプロイや特定のコマンド実行を自動化する」のはFabric、という使い分けがいいのかもしれませんね。
![]()
【Yuki】
そうですね、その理解で合っていると思います。
FabricはあくまでPythonのライブラリなので、もしHirokiくんが将来、もっと複雑な自動化をしたいと思ったら、他のPythonライブラリ(例えばデータの分析用ライブラリやWebフレームワークなど)と組み合わせて、自分だけの最強の運用ツールを作ることもできるんですよ。
![]()
【Hiroki】
自分だけの運用ツール……。夢が広がります!
まとめと参考文献
![]()
【Yuki】
そろそろまとめに入りましょうか。
Fabricを使えば、SSH越しに行っていた面倒な手作業を、Pythonの力で優雅に自動化できます。
Connectionオブジェクトでサーバーに接続。run()でコマンドを実行。fabfile.pyと@taskで作業をパッケージ化。put()/get()でファイル転送。ThreadingGroupで複数サーバーを並列操作。
![]()
【Hiroki】
ありがとうございます、Yukiさん!
さっそく、次からのデプロイはFabricを使って自動化してみようと思います。
これで浮いた時間で、もっと別のプログラミングの勉強ができそうです。
![]()
【Yuki】
ふふ、そう言ってもらえると嬉しいです。
効率化して生まれた時間は、大切に使ってくださいね。
あ……もしよろしければ、もっと詳しい情報が載っている公式サイトも、後で読んでおくといいかもしれません。
英語のサイトですけど、コード例が豊富で、眺めているだけでも楽しいですよ。
Fabric Documentation (Official) Invoke (Fabricのベースとなっているタスク実行ライブラリ) Paramiko (Fabricが内部で使用しているSSHライブラリ)
![]()
【Hiroki】
ありがとうございます! 読んでみます。
また分からないことがあったら、教えてくださいね。
![]()
【Yuki】
はい、いつでもどうぞ。
……あ、Hirokiくん。作業が終わったら、たまにはゆっくり休むのも忘れないでくださいね。
夜、静かな時間にコードを書くのは楽しいですけど、無理は禁物ですから……。
![]()
【Hiroki】
はい、気をつけます! Yukiさんも、あまり夜更かししすぎないでくださいね。
![]()
【Yuki】
……そうですね。ありがとうございます。
では、今日の講義はここまでにしましょうか。
お疲れ様でした。
この記事では基礎を解説しましたが、実務においては「もっと複雑なデータを扱いたい」「独自のシステムに組み込みたい」といった、個別の課題に直面することも多いはずです。
「自分で書く時間は最小限に抑え、プロの品質でツールを完成させたい」という方は、ぜひ一度ご相談ください。
- 専門家の知見に基づいた、保守性の高いコード設計
- AIの専門家による、Gemini API等の最新AIを組み合わせた高度な自動化
- ChatGPT等が生成したコードのデバッグ・最適化
「教わる」だけでなく「形にする」パートナーとして、フリーランスエンジニアのmei_13が最短ルートでの解決をサポートします。


