はじめに
仕事の都合で GoogleCloudを触り始めた、GoogleCloud歴 4か月の駆け出しエンジニアです。
GoogleCloudのCloud Shell(AWSでもほぼ同機能のCloud Shellがあります)上で、コンテナを起動してデプロイしてみることに挑戦してみました。
構成概要図
- Cloud Shellでコンテナ起動した際のイメージ図
ハンズオン
今回は「四方に回転させたPDFを出力」する、アプリケーションを構築するものとします。
1.Google Cloudにてプロジェクト作成
- 今回はハンズオンということもあり、オーナー権限にて構築を実施しております。
参照ブログ:AWS Lambda から Gemini APIを利用した呼出しハンズオン
2.PDF出力先のGCSバケットの作成
- 「マネジメントコンソール」画面から「GCS」画面へ遷移します。
- 「バケットを作成」を選択し、新規バケットを作成する。
設定内容 | 値 | 例 |
---|---|---|
バケット名 | ${バケット名} | before-change-bucket |
3.Cloud Shellの準備
3.1.事前準備
-
マネジメントコンソール右上 [>.] アイコンより、Cloud Shellの起動し以下コマンドを実施する。
-
Cloud Shellでディレクトリ作成
mkdir ${フォルダ名} cd ${フォルダ名} touch app.py touch Dockerfile touch requirements.txt # 仮想環境を作成 python3 -m venv venv # 仮想環境を有効化 source venv/bin/activate
3.2.「app.py」について
3.2.1.処理フロー
項番 | 処理内容 | 出力ファイル |
---|---|---|
1 | PDF作成 | test.pdf |
2 | 90°、180°、270°のPDF保存 | rotated_0.pdf,rotated_90.pdf,rotated_180.pdf,rotated_270.pdf |
3 | 4つのPDFをマージ | merged_output.pdf |
4 | GCSアップロード | gs://${2.PDF出力先のGCS}/merged_output.pdf |
3.2.2.「app.py」コード
※生成AIにて構築
- 74行目の
gcs_bucket = "${PDF出力先のGCS名}"
は、「2.PDF出力先のGCSの作成」で作成したバケット名を入力
import os
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from PyPDF2 import PdfReader, PdfWriter, PdfMerger
from google.cloud import storage
def create_test_pdf(filename):
""" テスト用のPDFを作成 """
c = canvas.Canvas(filename, pagesize=letter)
c.drawString(100, 750, "This is a test PDF")
c.drawString(100, 700, "Created for rotation testing")
c.save()
def rotate_pdf(input_path, output_path, rotation):
""" 指定した角度でPDFを回転 """
reader = PdfReader(input_path)
writer = PdfWriter()
for page in reader.pages:
page.rotate(rotation)
writer.add_page(page)
with open(output_path, "wb") as output_file:
writer.write(output_file)
def merge_pdfs(output_filename, pdf_files):
""" PDF をマージする """
merger = PdfMerger()
for pdf in pdf_files:
print(f"Adding {pdf} to merged PDF")
merger.append(pdf)
merger.write(output_filename)
merger.close()
print(f"Successfully merged into {output_filename}")
def upload_to_gcs(bucket_name, source_file_name, destination_blob_name):
"""GCS バケットにファイルをアップロード"""
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(destination_blob_name)
blob.upload_from_filename(source_file_name)
print(f"Uploaded {source_file_name} to gs://{bucket_name}/{destination_blob_name}")
def main():
print("📌 回転したテスト用PDF作成 + マージ + GCSアップロード スクリプト")
# テスト用PDFの作成
test_pdf = "test.pdf"
create_test_pdf(test_pdf)
print(f"✅ テスト用PDFを作成しました: {test_pdf}")
# 回転角度のリスト
rotations = [0, 90, 180, 270]
rotated_pdfs = []
# 各回転角度でPDFを作成
for rotation in rotations:
output_file = f"rotated_{rotation}.pdf"
rotate_pdf(test_pdf, output_file, rotation)
rotated_pdfs.append(output_file)
print(f"✅ {rotation}度回転したPDFを作成しました: {output_file}")
print("📌 すべての回転PDFの作成が完了しました。")
# PDF をマージ
merged_pdf = "merged_output.pdf"
merge_pdfs(merged_pdf, rotated_pdfs)
print(f"✅ マージしたPDFを作成しました: {merged_pdf}")
# GCS にアップロード
gcs_bucket = "${PDF出力先のGCS名}" # 🔹 ここにGCSのバケット名を指定
gcs_destination = "merged_output.pdf" # GCS上の保存名
upload_to_gcs(gcs_bucket, merged_pdf, gcs_destination)
if __name__ == "__main__":
main()
3.3.「requirements.txt」について
3.3.1.ライブラリ内容
項番 | 記載名 | 主な内容 |
---|---|---|
1 | PyPDF2 | PDF の読み込み、ページの回転、マージ、保存などを行うライブラリ |
2 | reportlab | PDF の生成、テキストや画像の描画を行うライブラリ |
3 | google-cloud-storage | Google Cloud Storage (GCS) へのファイルアップロードを行うライブラリ |
3.3.2.「requirements.txt」コード
PyPDF2==3.0.1
reportlab==3.6.12
google-cloud-storage
3.4.「Dockerfile」について
- このままだと「Python 3.12」で構築され、PDFを生成するための「reportrab」の「freetype」関連のパッケージが不足してエラーとなる。
そのため「Python 3.10」で環境を構築する。
3.4.1.「Dockerfile」コード
# Python 3.10 をベースにしたコンテナ
FROM python:3.10
# 必要なライブラリをインストール
RUN apt-get update && apt-get install -y \
libfreetype6-dev libjpeg-dev libpng-dev \
&& rm -rf /var/lib/apt/lists/*
# 作業ディレクトリを設定
WORKDIR /app
# requirements.txt をコンテナ内にコピー
COPY requirements.txt .
# pip をアップグレードし、必要なライブラリをインストール
RUN pip install --upgrade pip setuptools wheel \
&& pip install -r requirements.txt
# デフォルトのコマンド(対話シェル)
CMD [ "python3" ]
4.ビルドの準備
4.1.Dockerイメージをビルド
- Dockerfileに基づき「Python 3.10」の環境を持つ 「my-python-env」というイメージを作成
cd ${フォルダ名} docker build -t my-python-env .
4.2.コンテナを起動・コンテナ内移動
-
Cloud Shell のディレクトリ(${フォルダ名))をコンテナで利用するため、「-v」オプションで「/app」にマウントしてファイル共有をする。
-
「-v」により、Cloud Shell のファイルを直接コンテナ内でも操作可能となり、コンテナ内で出力されたPDFも、コンテナ終了後でもローカルに残せる。
-
以下コマンドを実行することで、コンテナ内のシェルに入る。
docker run --rm -it -v $(pwd):/app my-python-env /bin/bash
-
動作確認
・Pythonのバージョン確認
・reportlabの稼働確認python --version python -c "import reportlab; print(reportlab.Version)"
5.アプリ実行
-
仮想環境の有効化
python app.py
-
コンテナの起動・終了コマンド
今回「–rm」オプションで起動しているため、「exit」したらコンテナは削除される挙動をとります。 -
Cloud Shellは一定時間操作がないと自動で停止するため、コンテナを放置しても自動で停止しますが、念のため停止させましょう。
項番 | 内容 | コマンド |
---|---|---|
1 | 起動 | docker run –rm -it -v $(pwd):/app my-python-env /bin/bash |
2 | 終了 | exit |
6.実行結果
6.1.コンソールでの見え方
root@76be6a0c3061:/app# python app.py
📌 回転したテスト用PDF作成 + マージ + GCSアップロード スクリプト
✅ テスト用PDFを作成しました: test.pdf
✅ 0度回転したPDFを作成しました: rotated_0.pdf
✅ 90度回転したPDFを作成しました: rotated_90.pdf
✅ 180度回転したPDFを作成しました: rotated_180.pdf
✅ 270度回転したPDFを作成しました: rotated_270.pdf
📌 すべての回転PDFの作成が完了しました。
Adding rotated_0.pdf to merged PDF
Adding rotated_90.pdf to merged PDF
Adding rotated_180.pdf to merged PDF
Adding rotated_270.pdf to merged PDF
Successfully merged into merged_output.pdf
✅ マージしたPDFを作成しました: merged_output.pdf
Uploaded merged_output.pdf to gs://before-change-bucket/merged_output.pdf
6.2.GCSのフォルダ構成
-
「GCS」にもオブジェクトが作成されていることが画面からもわかります。
-
作成されたPDFの内容。それぞれ90度ずつ4枚作成されています。
おわりに
得られた知見
- GoogleCloud Shellでのコンテナ実行方法
- Cloud Shell 上での Docker の使い方
今後の課題
- AWS環境でも同様の手順をハンズオンする。
- Cloud Shellだけでなく、Cloud Run や Cloud Functions へのデプロイに挑戦する。