mei_13のPython講座 ロゴ

【解説】サーバー作業を自動化する魔法の杖:PythonのFabricでスマートにデプロイをこなそう




サーバー作業を自動化する魔法の杖:PythonのFabricでスマートにデプロイをこなそう


Hirokiのアイコン
【Hiroki】 Yukiさん、こんにちは! 最近、自分で作ったWebアプリをVPS(仮想専用サーバー)にデプロイしてみたんですけど、毎回ターミナルを開いて、SSHでログインして、git pullして、サービスを再起動して……という手順を繰り返すのが、少しだけ手間に感じてきました。 これをもっとスマートに、自動化する方法ってないでしょうか?


Yukiのアイコン
【Yuki】 Hirokiくん、こんにちは。デプロイまで自分でやってみるなんて、すごく素敵だと思います。 その「繰り返し」の作業を自動化したいという気持ち、エンジニアとしてはとっても大切な感覚ですね。 そういう時は、PythonのFabricというライブラリを使ってみるのがいいかもしれません。 今日は、Fabricを使って、遠くのサーバーにある「あんなこと」や「こんなこと」を、手元のPCから魔法のように操作する方法をお話ししますね。


Hirokiのアイコン
【Hiroki】 Fabric……。なんだか、布とか織物みたいな名前ですね。 Pythonでサーバーを操作できるんですか?


Yukiのアイコン
【Yuki】 ふふ、名前の由来は「糸(Thread)」を織りなすように複数のサーバーを管理する……というところから来ているのかもしれませんね。 Fabricは、一言で言うと「SSH経由でコマンドをプログラムから実行するためのライブラリ」です。 通常、僕たちはTeraTermやターミナルを使って手動でコマンドを打ち込みますが、Fabricを使えば「どのサーバーで、どんなコマンドを、どんな順番で実行するか」をPythonコードとして書き留めておくことができるんです。


Hirokiのアイコン
【Hiroki】 なるほど! Pythonでスクリプトを書いておけば、ボタン一つでサーバーが動いてくれるイメージですね。

Fabricのインストールと準備


Yukiのアイコン
【Yuki】 はい、その通りです。まずはFabricを使えるように準備しましょう。 Fabricはサードパーティ製のライブラリなので、pipを使ってインストールする必要があります。 最近のFabricは「Fabric 2」や「Fabric 3」と呼ばれていたものが統合されていますので、普通にfabricを指定すれば大丈夫ですよ。

pip install fabric


Hirokiのアイコン
【Hiroki】 インストールできました! これで準備完了ですね。 次はどうすればいいんでしょうか?


Yukiのアイコン
【Yuki】 まずは、一番シンプルな方法から試してみましょうか。 Pythonの対話型シェルや、短いスクリプトで、サーバーに接続してコマンドを一つ実行するだけのコードを書いてみますね。

Connectionオブジェクトでサーバーに繋いでみよう


Yukiのアイコン
【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のアイコン
【Hiroki】 わあ、たったこれだけでサーバーのディスク使用量が見られるんですね。 c.run("df -h") という部分が、実際にサーバーに送られるコマンドですね?


Yukiのアイコン
【Yuki】 そうです。hide=True を指定すると、実行時の標準出力を画面にそのまま出さずに、変数として受け取ることができます。 こうすることで、取得した結果をPython側で加工したり、エラーチェックをしたりすることもできるんです。 あ、接続する時にパスワードが必要な場合は、connect_kwargs という引数で渡すこともできますが、できればSSH鍵を設定しておくのが一番安全で、Fabricも使いやすくなると思います。


Hirokiのアイコン
【Hiroki】 SSH鍵……。以前設定した気がします! それならスムーズに動かせそうです。 でも、毎回ホスト名やユーザー名をコードに書くのは、ちょっと面倒な気がしますね……。


Yukiのアイコン
【Yuki】 そうですよね。そこで登場するのが、fabfile.pyfabコマンド です。 これを使うと、もっと本格的な「自動化ツール」らしくなりますよ。

fabfile.py でタスクを定義する


Yukiのアイコン
【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のアイコン
【Hiroki】 @task というデコレータがついているんですね。 引数にある c は何ですか?


Yukiのアイコン
【Yuki】 この c は、先ほどの Connection オブジェクトが自動的に渡される場所です。 そして、このファイルを保存した場所で、ターミナルから fab コマンドを叩きます。

fab -H your-server-address.com hello


Hirokiのアイコン
【Hiroki】 おっ、実行されました! -H でホストを指定して、その後にタスク名の hello を書くんですね。 これなら、複数のタスクを順番に実行するのも簡単そうです。


Yukiのアイコン
【Yuki】 はい。with c.cd("/path/to/dir"): のように書くことで、そのブロックの中だけディレクトリを移動した状態でコマンドを実行できるのも便利ですよね。 手動だと cd し忘れて失敗することもありますけど、プログラムならそんな心配もありません。

複数のサーバーを同時に操作する


Hirokiのアイコン
【Hiroki】 Yukiさん、もしサーバーが2台や3台に増えた場合はどうすればいいんでしょうか? 一台ずつコマンドを叩くのはやっぱり大変ですよね。


Yukiのアイコン
【Yuki】 その質問、待っていました。Fabricの得意分野です。 SerialGroupThreadingGroup というクラスを使うと、複数のサーバーに対して一斉に処理を行うことができるんです。 例えば、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のアイコン
【Hiroki】 ThreadingGroup……。スレッドを使って並列に実行してくれるんですね! これならサーバーが10台あっても、一瞬で作業が終わってしまいそうです。


Yukiのアイコン
【Yuki】 ふふ、そうですね。 Fabricのようなツールは、誰かの作業を少しだけ楽にするために作られています。 そんな「誰かの役に立つために生まれた小さなツール」の歴史を見ると、なんだか心が温かくなるんです……。 自分が書いたコードが、遠くのサーバーで一生懸命動いているのを見ると、少しだけ、自分もそのサーバーの一部になれたような、不思議な気持ちになりませんか?


Hirokiのアイコン
【Hiroki】 あ……。確かに、自分のプログラムがどこか遠くで誰かのために動いているって思うと、なんだかワクワクします。 Yukiさんも、そんな風に思ったりするんですね。


Yukiのアイコン
【Yuki】 ええ、……あ、いえ、ただの独り言です。 話を戻しましょうか。Fabricには他にも便利な機能があるんですよ。

ファイルの転送(putとget)


Hirokiのアイコン
【Hiroki】 コマンドの実行だけじゃなくて、ファイルのやり取りもできるんですか? 例えば、設定ファイルをローカルで編集して、サーバーにアップロードしたい時とか。


Yukiのアイコン
【Yuki】 もちろん可能です。putget というメソッドを使います。 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のアイコン
【Hiroki】 すごい、本当に万能ですね! 逆に、サーバーにあるログファイルをローカルに持ってくる時は get を使えばいいんですね。


Yukiのアイコン
【Yuki】 その通りです。 c.get(remote="/var/log/nginx/access.log", local="logs/access.log") のように書けば、手元にログを保存してじっくり解析することもできます。

エラー処理と柔軟な構成


Hirokiのアイコン
【Hiroki】 でも、もしコマンドが失敗したらどうなるんでしょう? 例えば git pull がコンフリクトで止まっちゃった時とか……。


Yukiのアイコン
【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のアイコン
【Hiroki】 warn=True を使うと、プログラムを止めずに進められるんですね。 これなら複雑な条件分岐も作れそうです。

Fabricと他のツールの使い分け


Hirokiのアイコン
【Hiroki】 Yukiさん、少し気になったんですけど、「Ansible」とか「Terraform」といったツールもサーバー構成管理でよく聞きますよね。 Fabricとはどう違うんでしょうか?


Yukiのアイコン
【Yuki】 それはとても鋭い質問です。 Ansibleなどは「宣言型」といって、「サーバーがどういう状態であるべきか(このパッケージがインストールされている、このユーザーがいる、など)」を定義するのに向いています。 一方でFabricは「命令型」といって、「この手順で、このコマンドを実行して」という、スクリプト的な動きをさせるのが得意なんです。


Hirokiのアイコン
【Hiroki】 なるほど。 「サーバーを新しく構築する」のはAnsible、「日々のデプロイや特定のコマンド実行を自動化する」のはFabric、という使い分けがいいのかもしれませんね。


Yukiのアイコン
【Yuki】 そうですね、その理解で合っていると思います。 FabricはあくまでPythonのライブラリなので、もしHirokiくんが将来、もっと複雑な自動化をしたいと思ったら、他のPythonライブラリ(例えばデータの分析用ライブラリやWebフレームワークなど)と組み合わせて、自分だけの最強の運用ツールを作ることもできるんですよ。


Hirokiのアイコン
【Hiroki】 自分だけの運用ツール……。夢が広がります!

まとめと参考文献


Yukiのアイコン
【Yuki】 そろそろまとめに入りましょうか。 Fabricを使えば、SSH越しに行っていた面倒な手作業を、Pythonの力で優雅に自動化できます。

  • Connection オブジェクトでサーバーに接続。
  • run() でコマンドを実行。
  • fabfile.py@task で作業をパッケージ化。
  • put() / get() でファイル転送。
  • ThreadingGroup で複数サーバーを並列操作。


Hirokiのアイコン
【Hiroki】 ありがとうございます、Yukiさん! さっそく、次からのデプロイはFabricを使って自動化してみようと思います。 これで浮いた時間で、もっと別のプログラミングの勉強ができそうです。


Yukiのアイコン
【Yuki】 ふふ、そう言ってもらえると嬉しいです。 効率化して生まれた時間は、大切に使ってくださいね。 あ……もしよろしければ、もっと詳しい情報が載っている公式サイトも、後で読んでおくといいかもしれません。 英語のサイトですけど、コード例が豊富で、眺めているだけでも楽しいですよ。

Fabric Documentation (Official) Invoke (Fabricのベースとなっているタスク実行ライブラリ) Paramiko (Fabricが内部で使用しているSSHライブラリ)


Hirokiのアイコン
【Hiroki】 ありがとうございます! 読んでみます。 また分からないことがあったら、教えてくださいね。


Yukiのアイコン
【Yuki】 はい、いつでもどうぞ。 ……あ、Hirokiくん。作業が終わったら、たまにはゆっくり休むのも忘れないでくださいね。 夜、静かな時間にコードを書くのは楽しいですけど、無理は禁物ですから……。


Hirokiのアイコン
【Hiroki】 はい、気をつけます! Yukiさんも、あまり夜更かししすぎないでくださいね。


Yukiのアイコン
【Yuki】 ……そうですね。ありがとうございます。 では、今日の講義はここまでにしましょうか。 お疲れ様でした。



< ELK Stack
コラム一覧に戻る
Netmiko >

この記事では基礎を解説しましたが、実務においては「もっと複雑なデータを扱いたい」「独自のシステムに組み込みたい」といった、個別の課題に直面することも多いはずです。

「自分で書く時間は最小限に抑え、プロの品質でツールを完成させたい」という方は、ぜひ一度ご相談ください。

「教わる」だけでなく「形にする」パートナーとして、フリーランスエンジニアのmei_13が最短ルートでの解決をサポートします。

➡ ココナラで制作・相談を依頼する(見積もり無料)


初心者から始められるPythonレッスン

プログラミング未経験者・初心者歓迎!
月額4,000円で質問し放題!!
● 完全オンライン
● 翌日までには必ず返信
● 挫折しない独自の学習メソッド
● 圧倒的高評価!!
テキストベースで時間を選ばない
● 高品質なサンプルコード
詳細はこちら
興味がある方はまず質問だけでもどうぞ!



AIアシスタント Yuki