<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Flask  |  takeHo（たけほ）のへなちょこ台帳</title>
	<atom:link href="https://blog.takeho.com/tag/flask/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.takeho.com</link>
	<description>いわゆる自由帳ってところです。</description>
	<lastBuildDate>Wed, 16 Sep 2026 09:22:35 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6</generator>

<image>
	<url>https://blog.takeho.com/wp-content/uploads/2024/08/icon-150x150.png</url>
	<title>Flask  |  takeHo（たけほ）のへなちょこ台帳</title>
	<link>https://blog.takeho.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Rocky Linuxで初めてのPython Webアプリ開発―Flask・Gunicorn・Apacheの環境構築をコマンドごとに解説</title>
		<link>https://blog.takeho.com/o008odgrqz2gfjy0z7wx43kdvrxxk973/</link>
					<comments>https://blog.takeho.com/o008odgrqz2gfjy0z7wx43kdvrxxk973/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 09:40:00 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Flask]]></category>
		<category><![CDATA[Gunicorn]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=2001</guid>

					<description><![CDATA[PythonでWebアプリを作ってみたいと思っても、最初は「Pythonを入れた後に何をすればよいのか」「Apacheだけでは動かないのか」「FlaskとGunicornは何が違うのか」と迷いやすいものです。 この記事で [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>PythonでWebアプリを作ってみたいと思っても、最初は「Pythonを入れた後に何をすればよいのか」「Apacheだけでは動かないのか」「FlaskとGunicornは何が違うのか」と迷いやすいものです。</p>



<p>この記事では、Rocky Linux上にPythonの実行環境を用意し、Flaskで作ったWebアプリをApache経由で公開するまでを、初めて学ぶ人向けに説明します。例として使うホスト名と設置先は次のとおりです。</p>



<pre class="wp-block-code"><code>ホスト名：python.example.com
設置先：/var/www/html/python.example.com</code></pre>



<p>実際に試す場合は、<code>python.example.com</code>を自分のドメインへ読み替えてください。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2"><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">PythonとPHPではWebアプリの動かし方が少し違う</a></li><li><a href="#toc2" tabindex="0">Flaskを選ぶ理由</a></li><li><a href="#toc3" tabindex="0">1．Rocky Linuxを更新する</a></li><li><a href="#toc4" tabindex="0">2．Pythonとpipをインストールする</a></li><li><a href="#toc5" tabindex="0">3．Webアプリ用ディレクトリを作る</a></li><li><a href="#toc6" tabindex="0">4．Pythonの仮想環境を作る</a></li><li><a href="#toc7" tabindex="0">5．pipを更新してFlaskとGunicornを入れる</a></li><li><a href="#toc8" tabindex="0">6．最小のFlaskアプリを作る</a></li><li><a href="#toc9" tabindex="0">7．開発用サーバーで確認する</a></li><li><a href="#toc10" tabindex="0">8．Gunicornで起動する</a></li><li><a href="#toc11" tabindex="0">9．Apacheでpython.example.comだけを転送する</a></li><li><a href="#toc12" tabindex="0">10．Apacheの設定を確認して反映する</a></li><li><a href="#toc13" tabindex="0">11．本番ではGunicornをsystemdへ登録する</a><ol><li><a href="#toc14" tabindex="0">systemd設定の意味</a></li></ol></li><li><a href="#toc15" tabindex="0">12．サービスを登録して起動する</a></li><li><a href="#toc16" tabindex="0">13．プログラム更新後の反映とログ確認</a></li><li><a href="#toc17" tabindex="0">よくあるトラブル</a><ol><li><a href="#toc18" tabindex="0">502 Proxy Errorが表示される</a></li><li><a href="#toc19" tabindex="0">Address already in useと表示される</a></li><li><a href="#toc20" tabindex="0">Apacheの既存サイトまで転送される</a></li></ol></li><li><a href="#toc21" tabindex="0">まとめ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">PythonとPHPではWebアプリの動かし方が少し違う</span></h2>



<p>PHPはApacheがPHPファイルを直接読み込み、処理結果を返す構成がよく使われます。一方、PythonのWebアプリでは、ApacheがPythonファイルを直接実行するのではなく、Gunicornというアプリケーションサーバーへアクセスを転送する構成が一般的です。</p>



<pre class="wp-block-code"><code>ブラウザ
  ↓
Apache
  ↓
Gunicorn
  ↓
Flaskで作ったPythonアプリ</code></pre>



<p>それぞれの役割を簡単に整理すると、FlaskはWebアプリを作るためのフレームワーク、Gunicornは作成したアプリを常時動かすサーバー、ApacheはインターネットからのHTTP・HTTPSアクセスを受け付ける入口です。</p>



<h2 class="wp-block-heading"><span id="toc2">Flaskを選ぶ理由</span></h2>



<p>PythonにはDjango、Flask、FastAPIなどのWebフレームワークがあります。初めて小さなWebアプリを作る場合は、構成が単純で必要な機能を少しずつ追加できるFlaskが分かりやすいでしょう。</p>



<ul class="wp-block-list">
<li>Flask：小規模なWebサイト、学習、簡単な業務アプリ向け</li>



<li>Django：ログインや管理画面を含む大きめのサービス向け</li>



<li>FastAPI：スマートフォンアプリや外部サービス向けのAPI開発に向く</li>
</ul>



<p>今回はFlaskを使います。</p>



<h2 class="wp-block-heading"><span id="toc3">1．Rocky Linuxを更新する</span></h2>



<pre class="wp-block-code"><code>sudo dnf update -y</code></pre>



<p><code>sudo</code>は管理者権限でコマンドを実行する指定です。<code>dnf</code>はRocky Linuxでソフトウェアを管理する仕組み、<code>update</code>はインストール済みパッケージを更新する操作です。<code>-y</code>を付けると、途中の確認へ自動的にyesと回答します。</p>



<p>本番サーバーでは更新による影響がないか確認してから実行してください。</p>



<h2 class="wp-block-heading"><span id="toc4">2．Pythonとpipをインストールする</span></h2>



<pre class="wp-block-code"><code>sudo dnf install -y python3 python3-pip</code></pre>



<p><code>install</code>はパッケージのインストール、<code>python3</code>はPython本体、<code>python3-pip</code>はPython用パッケージ管理ツールです。pipを使うことでFlaskやGunicornを追加できます。</p>



<p>インストール後にバージョンを確認します。</p>



<pre class="wp-block-code"><code>python3 --version
pip3 --version</code></pre>



<p><code>--version</code>はインストールされているバージョンを表示する指定です。バージョン番号が表示されれば、Pythonを実行できる状態です。</p>



<h2 class="wp-block-heading"><span id="toc5">3．Webアプリ用ディレクトリを作る</span></h2>



<pre class="wp-block-code"><code>sudo mkdir -p /var/www/html/python.example.com
sudo chown -R rocky:rocky /var/www/html/python.example.com
cd /var/www/html/python.example.com</code></pre>



<p><code>mkdir</code>はディレクトリを作るコマンドです。<code>-p</code>を付けると、途中のディレクトリが存在しない場合もまとめて作成します。</p>



<p><code>chown</code>は所有者を変更するコマンドです。<code>-R</code>は内部のファイルやディレクトリにも再帰的に設定する指定です。ここではRocky Linuxへログインしているユーザー名を<code>rocky</code>としています。別のユーザーを使っている場合は読み替えてください。</p>



<p><code>cd</code>は作業するディレクトリを移動するコマンドです。</p>



<h2 class="wp-block-heading"><span id="toc6">4．Pythonの仮想環境を作る</span></h2>



<pre class="wp-block-code"><code>python3 -m venv venv</code></pre>



<p><code>python3</code>でPython 3を起動し、<code>-m venv</code>で仮想環境を作る標準機能を呼び出しています。最後の<code>venv</code>は作成するディレクトリ名です。</p>



<p>仮想環境とは、Webアプリ専用のPython環境です。OS全体へFlaskなどを直接インストールせず、アプリごとに使用するパッケージとバージョンを分けられます。</p>



<p>続いて仮想環境を有効にします。</p>



<pre class="wp-block-code"><code>source venv/bin/activate</code></pre>



<p><code>source</code>は指定した設定ファイルを現在のシェルへ読み込むコマンドです。実行後、プロンプトの先頭に<code>(venv)</code>と表示されれば有効になっています。</p>



<p>仮想環境を終了するときは次を実行します。</p>



<pre class="wp-block-code"><code>deactivate</code></pre>



<p>SSHで再ログインした後は仮想環境が解除されていますが、作り直す必要はありません。アプリのディレクトリへ移動し、再び<code>source venv/bin/activate</code>を実行します。</p>



<h2 class="wp-block-heading"><span id="toc7">5．pipを更新してFlaskとGunicornを入れる</span></h2>



<pre class="wp-block-code"><code>python -m pip install --upgrade pip
pip install flask gunicorn</code></pre>



<p><code>python -m pip</code>は、現在有効になっているPython環境のpipを実行する書き方です。<code>install</code>はインストール、<code>--upgrade</code>は既に入っているパッケージを新しいバージョンへ更新する指定です。</p>



<p>2行目ではFlaskとGunicornを仮想環境内へインストールしています。</p>



<ul class="wp-block-list">
<li><code>flask</code>：URLとPythonの処理を結び付け、Web画面を作るフレームワーク</li>



<li><code>gunicorn</code>：Flaskアプリを本番サーバーで動かすためのWSGIサーバー</li>
</ul>



<h2 class="wp-block-heading"><span id="toc8">6．最小のFlaskアプリを作る</span></h2>



<p><code>/var/www/html/python.example.com/app.py</code>を次の内容で作成します。</p>



<pre class="wp-block-code"><code>from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "Python Webアプリが動いています"

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8000)</code></pre>



<p><code>from flask import Flask</code>はFlask本体を読み込みます。<code>app = Flask(__name__)</code>はWebアプリを作成する処理です。</p>



<p><code>@app.route("/")</code>は、トップページのURLへアクセスされたときに、その直後の関数を実行する指定です。<code>return</code>でブラウザへ返す内容を指定しています。</p>



<p>最後の<code>app.run()</code>は、app.pyを直接実行した場合に127.0.0.1の8000番ポートで開発用サーバーを起動する処理です。127.0.0.1は同じサーバー内部からだけ接続できるアドレスです。</p>



<h2 class="wp-block-heading"><span id="toc9">7．開発用サーバーで確認する</span></h2>



<pre class="wp-block-code"><code>cd /var/www/html/python.example.com
source venv/bin/activate
python app.py</code></pre>



<p>別のSSH接続から次を実行します。</p>



<pre class="wp-block-code"><code>curl http://127.0.0.1:8000/</code></pre>



<p><code>curl</code>はコマンド上からHTTPアクセスを行うツールです。「Python Webアプリが動いています」と返れば、Flaskアプリは正常に動いています。</p>



<p>開発用サーバーは確認には便利ですが、本番公開を目的としたものではありません。本番ではGunicornを使います。</p>



<h2 class="wp-block-heading"><span id="toc10">8．Gunicornで起動する</span></h2>



<pre class="wp-block-code"><code>gunicorn --bind 127.0.0.1:8000 app:app</code></pre>



<p><code>gunicorn</code>はアプリケーションサーバーを起動するコマンドです。<code>--bind 127.0.0.1:8000</code>は、同じサーバー内部の8000番ポートで待ち受ける指定です。</p>



<p>最後の<code>app:app</code>は、コロンの左側がファイル名<code>app.py</code>、右側がファイル内で作成した<code>app</code>変数を示します。</p>



<p>すでに8000番ポートが使用されている場合は「Address already in use」と表示されます。使用中のプロセスは次のコマンドで確認できます。</p>



<pre class="wp-block-code"><code>sudo ss -lntp | grep :8000</code></pre>



<p><code>ss</code>は通信ポートの使用状況を調べるコマンド、<code>-lntp</code>は待ち受け中のTCPポートとプロセスを数値表示する指定です。<code>grep :8000</code>で8000番を含む行だけに絞っています。</p>



<h2 class="wp-block-heading"><span id="toc11">9．Apacheでpython.example.comだけを転送する</span></h2>



<p>Rocky LinuxではApacheのサービス名とパッケージ名は<code>httpd</code>です。</p>



<pre class="wp-block-code"><code>sudo dnf install -y httpd
sudo systemctl enable --now httpd</code></pre>



<p><code>systemctl</code>はサービスを管理するコマンドです。<code>enable</code>はOS起動時の自動起動を有効にし、<code>--now</code>は自動起動の設定と同時に、その場でサービスも起動します。</p>



<p><code>/etc/httpd/conf.d/python.example.com.conf</code>を作り、次の設定を記載します。</p>



<pre class="wp-block-code"><code>&lt;VirtualHost *:80&gt;
    ServerName python.example.com

    ErrorLog /var/log/httpd/python.example.com-error.log
    CustomLog /var/log/httpd/python.example.com-access.log combined

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8000/
    ProxyPassReverse / http://127.0.0.1:8000/
&lt;/VirtualHost&gt;</code></pre>



<p><code>VirtualHost *:80</code>はHTTPの80番ポート用設定、<code>ServerName</code>は対象のホスト名です。ProxyPassをこのVirtualHostの中へ記載することで、<code>python.example.com</code>へのアクセスだけがGunicornへ転送されます。他のホストには影響しません。</p>



<p><code>ProxyPreserveHost On</code>は、ブラウザから送られたホスト名を転送先へ引き継ぎます。<code>ProxyPass</code>はApacheからGunicornへ転送する設定、<code>ProxyPassReverse</code>はGunicornから返された応答ヘッダーを外部公開用に調整する設定です。</p>



<p>この構成ではApacheがファイルを直接表示しないため、基本的に<code>DocumentRoot</code>は必要ありません。ページの内容はFlaskが返します。</p>



<h2 class="wp-block-heading"><span id="toc12">10．Apacheの設定を確認して反映する</span></h2>



<pre class="wp-block-code"><code>sudo apachectl configtest
sudo systemctl reload httpd</code></pre>



<p><code>apachectl configtest</code>はApache設定の文法確認です。「Syntax OK」と表示されたことを確認してから反映します。</p>



<p><code>reload</code>はサービスを停止せずに設定を読み直す操作です。設定に誤りがある状態でいきなり再起動するより、安全に確認できます。</p>



<p>Rocky LinuxでSELinuxが有効な場合は、ApacheからGunicornへのネットワーク接続を許可します。</p>



<pre class="wp-block-code"><code>sudo setsebool -P httpd_can_network_connect 1</code></pre>



<p><code>setsebool</code>はSELinuxの許可項目を変更するコマンドです。<code>-P</code>を付けると再起動後も設定が維持されます。実際に転送するホストはApacheのVirtualHost設定で指定した<code>python.example.com</code>だけです。</p>



<h2 class="wp-block-heading"><span id="toc13">11．本番ではGunicornをsystemdへ登録する</span></h2>



<p>次のようなコマンドでGunicornをバックグラウンド起動することもできます。</p>



<pre class="wp-block-code"><code>gunicorn --bind 127.0.0.1:8000 --daemon app:app</code></pre>



<p>ただし、手動起動ではサーバー再起動後に自動で立ち上がらず、異常終了時の復旧やログ確認も面倒です。本番ではsystemdへサービスとして登録します。</p>



<p>サービス名は任意ですが、何の処理か分かりやすい<code>gunicorn-python-example.service</code>とします。</p>



<pre class="wp-block-code"><code>sudo vi /etc/systemd/system/gunicorn-python-example.service</code></pre>



<p>ファイルへ次を記載します。</p>



<pre class="wp-block-code"><code>&#91;Unit]
Description=Gunicorn for python.example.com
After=network.target

&#91;Service]
User=rocky
Group=rocky
WorkingDirectory=/var/www/html/python.example.com

ExecStart=/var/www/html/python.example.com/venv/bin/gunicorn     --workers 2     --bind 127.0.0.1:8000     app:app

Restart=always
RestartSec=5

&#91;Install]
WantedBy=multi-user.target</code></pre>



<h3 class="wp-block-heading"><span id="toc14">systemd設定の意味</span></h3>



<ul class="wp-block-list">
<li><code>Description</code>：サービスの説明</li>



<li><code>After=network.target</code>：ネットワークの準備後に起動</li>



<li><code>User</code>と<code>Group</code>：Gunicornを実行するLinuxユーザーとグループ</li>



<li><code>WorkingDirectory</code>：アプリの作業ディレクトリ</li>



<li><code>ExecStart</code>：実際に起動するGunicornのコマンド</li>



<li><code>--workers 2</code>：リクエストを処理するワーカープロセスを2つ起動</li>



<li><code>Restart=always</code>：Gunicornが停止した場合に再起動</li>



<li><code>RestartSec=5</code>：再起動まで5秒待機</li>



<li><code>WantedBy=multi-user.target</code>：通常のサーバー起動時に利用するサービスとして登録</li>
</ul>



<p>仮想環境を<code>source</code>で有効にしなくても、ExecStartで仮想環境内のGunicornをフルパス指定しているため、正しい環境が使用されます。</p>



<h2 class="wp-block-heading"><span id="toc15">12．サービスを登録して起動する</span></h2>



<pre class="wp-block-code"><code>sudo systemctl daemon-reload
sudo systemctl enable --now gunicorn-python-example</code></pre>



<p><code>daemon-reload</code>は新しく作成・変更したsystemd設定を読み直す操作です。設定ファイルを編集しただけではsystemdへ反映されないため、必ず実行します。</p>



<p><code>enable --now</code>により、自動起動の有効化と現在の起動を同時に行います。状態は次で確認できます。</p>



<pre class="wp-block-code"><code>sudo systemctl status gunicorn-python-example</code></pre>



<p><code>active (running)</code>と表示されれば起動しています。</p>



<h2 class="wp-block-heading"><span id="toc16">13．プログラム更新後の反映とログ確認</span></h2>



<p><code>app.py</code>などを変更した後は、Gunicornを再起動します。</p>



<pre class="wp-block-code"><code>sudo systemctl restart gunicorn-python-example</code></pre>



<p>Pythonプログラムだけを変更した場合、Apacheを再起動する必要はありません。ApacheのVirtualHost設定を変更した場合だけ、構文確認後にApacheをreloadします。</p>



<p>Gunicornのログを直近100件確認する場合は次を実行します。</p>



<pre class="wp-block-code"><code>sudo journalctl -u gunicorn-python-example -n 100</code></pre>



<p>リアルタイムで確認する場合は次のとおりです。</p>



<pre class="wp-block-code"><code>sudo journalctl -u gunicorn-python-example -f</code></pre>



<p><code>journalctl</code>はsystemdが管理するログを表示するコマンドです。<code>-u</code>は対象サービス、<code>-n 100</code>は直近100件、<code>-f</code>は新しいログを継続表示する指定です。</p>



<h2 class="wp-block-heading"><span id="toc17">よくあるトラブル</span></h2>



<h3 class="wp-block-heading"><span id="toc18">502 Proxy Errorが表示される</span></h3>



<p>ApacheからGunicornへ接続できていない可能性があります。Gunicornの状態、8000番ポート、SELinuxを順番に確認します。</p>



<pre class="wp-block-code"><code>sudo systemctl status gunicorn-python-example
sudo ss -lntp | grep :8000
sudo journalctl -u gunicorn-python-example -n 100</code></pre>



<h3 class="wp-block-heading"><span id="toc19">Address already in useと表示される</span></h3>



<p>手動で起動したGunicornが残っている、または別のアプリが8000番ポートを使っています。使用中のプロセスを確認し、同じアプリを二重に起動しないようにします。</p>



<h3 class="wp-block-heading"><span id="toc20">Apacheの既存サイトまで転送される</span></h3>



<p><code>ProxyPass</code>がVirtualHostの外側に書かれていないか確認します。<code>python.example.com</code>のVirtualHost内だけに記載すれば、このホストだけが転送対象になります。</p>



<h2 class="wp-block-heading"><span id="toc21">まとめ</span></h2>



<p>Pythonのコード自体は比較的読みやすい一方、Webアプリを本番公開するにはFlask、Gunicorn、Apache、systemdの役割を理解する必要があります。最初は登場人物が多く見えますが、それぞれの役割は明確です。</p>



<ul class="wp-block-list">
<li>Flask：Webアプリの処理を作る</li>



<li>Gunicorn：Flaskアプリを本番環境で動かす</li>



<li>Apache：外部からのアクセスを受け付けてGunicornへ転送する</li>



<li>systemd：Gunicornの起動、停止、自動起動、再起動、ログを管理する</li>
</ul>



<p>まずはトップページに文字を表示する最小アプリを動かし、仕組みを確認してからHTMLテンプレート、MySQL、投稿フォーム、ログイン機能などを追加していくと理解しやすくなります。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/o008odgrqz2gfjy0z7wx43kdvrxxk973/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
