どうも、ケニー(tsujikenzo)です。このシリーズでは、Docker入門をお届けしています。
前回は「Docker Compose中編」で、Docker Composeで複数のコンテナの起動と連携を、YMLファイルで指定しました。便利ですね。
今回は、最終回です。Docker Composeの応用編をお届けします。
取得したデータを永続化(Redis/PostgreSQL などの実データやログを保存)する
コンテナは使い捨てが前提なので、停止・削除すると中のデータも消えてしまいます。 なので「保存場所(コンテナ内/外)」を理解する必要があります。
取得したデータを永続化するということは、「コンテナが消えてもデータが消えない場所に保存する」ということです。
保存場所の選択肢は大きく3つです。
- コンテナの中に保存する
- ホスト(PC)側に保存する(例:
C:\Users\Kenzo\Desktop\data) - ボリュームに保存する(Dockerが場所を決めて管理する)
実運用では、DBやログのように「自然に増え続けるデータ」を扱うため、 コンテナの外に保存する仕組みが必須になります。
ボリュームとは
ボリュームは、コンテナのライフサイクルと独立してデータを残せる保存領域です。
コンテナを削除しても、ボリュームを消さない限りデータは残ります。
代表的な使いどころ
- RedisやPostgreSQLなど →
/dataや/var/lib/postgresql/dataをマウント - アプリのCSV →
.:/appのようにローカルへ出力
ボリュームの使い方
docker-compose.yml で volumes を指定すればOKです。
services:
app:
build: .
depends_on:
- redis
redis:
image: redis:7
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
redis-data:volumes:セクションでボリューム名を定義します。- Redisコンテナの
/dataをボリュームにマウントします。
ボリュームを消したい場合
docker compose down -v(-v を付けると関連ボリュームも削除されます)
Pythonアプリの取得数を500件に増やそう
それでは、scraper.py を修正して、ページネーション(複数ページの順次リクエスト)に対応し、500件以上の書籍タイトルを取得できるようにします。
import requests
from bs4 import BeautifulSoup
import redis
def smart_scraper(max_books=500):
r = redis.Redis(host='redis', port=6379, db=0)
base_url = "https://books.toscrape.com/"
current_url = base_url
books_fetched = 0
while current_url and books_fetched < max_books:
response = requests.get(current_url)
soup = BeautifulSoup(response.text, 'html.parser')
books = soup.find_all('article', class_='product_pod')
for book in books:
title = book.h3.a['title']
detail_url = book.h3.a['href']
if r.sismember('visited_urls', detail_url):
print(f"スキップ: 既に取得済み {title}")
continue
print(f"取得中...: {title}")
r.sadd('visited_urls', detail_url)
with open("results.csv", "a") as f:
f.write(f"{title}\n")
books_fetched += 1
if books_fetched >= max_books:
break
next_btn = soup.find('li', class_='next')
if next_btn and books_fetched < max_books:
next_href = next_btn.a['href']
if current_url == base_url:
current_url = base_url + next_href
else:
import urllib.parse
current_url = urllib.parse.urljoin(current_url, next_href)
else:
break
if __name__ == "__main__":
smart_scraper()max_books=500で最大500冊だけ取得します(必要に応じて数値を調整してください)。- 「次のページ」がなくなるまでページネーションし、タイトルをcsvファイルに追記します。
- Redisで重複チェックしますので、途中で中断→再実行しても、既に取得済みのURLはスキップされます。
実行する
それでは、実行してみましょう。docker compose up –build で起動(コンテナ内で scraper.py が動く)します。

データは取れているようです。
ボリュームの確認
一度、Ctrl+Cでコンテナを停止しましょう。
以下のコマンドで、ボリューム一覧を確認します。
docker volume lsボリュームが作成されているようです。

ボリュームの詳細は、以下のコマンドで確認できます。
docker volume inspect desktop_redis-data詳細の中の「Mountpoint」 が実際の保存先(この場合、わたしのローカルPC)です。

ちなみに、SCARDやSRANDMEMBERなどのRedisコマンドで、データベースの操作が可能です。(今回は割愛します)

環境変数の使い方(.env)
よく使う設定値(APIキーや接続先URLなど)は、.envファイルでまとめて管理できます。
Docker Composeは自動で.envを読み込むので、コードに直接書かずに済むのが便利です。
たとえば、今回の図書サイトのURLを `.env` に書くと以下のようになります。
BASE_URL=https://books.toscrape.com/.env は 自動で読み込まれますが、コンテナに渡すかどうかで、用途が違います。
- 自動で読む .env: Composeファイル内の変数置換用
- コンテナに渡す: env_file: .env(または environment:)が必要
#docker-compose.yml
services:
app:
build: .
env_file:
- .env
depends_on:
- redis
redis:
image: redis:7
ports:
- "6379:6379"つまり、Pythonアプリ内で記述していたスクレイピング先のURLを削除して、.envファイルのBASE_URLを使うなら、docker-compose.yml内に記述する必要があるということです。
まとめ
以上で、「ノンプログラマーのためのDocker入門 Docker Compose後編」をお送りしました。
ここまで理解していれば、AIにも指示が出せるかと思います。
時代の変化に振り落とされないように、ついていきましょう!



