こんにちは、たねやつです。
新しい技術を学ぶとき、チュートリアルをなぞるだけだとモチベーションが続かないことがありますよね。そこで今回は、「手元のRaspberry Piに自作アプリを自動でデプロイする」という具体的なゴールを設定して、モダンな開発手法であるCI/CDを学んでいくシリーズを始めたいと思います。
最終的には、コードをGitLabにプッシュするだけで、テスト、Dockerイメージのビルド、そしてRaspberry Pi上のKubernetesへのデプロイが全自動で行われる環境を目指します。
第1回は、その第一歩として、なぜCI/CDが必要なのかに触れつつ、開発環境であるWSL上でDockerを使ってFastAPIとPostgreSQLのアプリケーションを立ち上げるところまでを解説します。
この記事でできること
- CI/CDの基本的な概念とメリットがわかる。
- WSL(Windows Subsystem for Linux)にDocker CEをインストールし、開発環境を構築できる。
docker composeを使い、FastAPIとPostgreSQLを連携させたWebアプリケーションを起動できる。
事前に必要なもの
Windows PC
- WSL2がインストールおよび設定済みであること。(本記事ではUbuntuを想定)
テキストエディタ
- VSCodeなど、コードが書けるエディタ。
CI/CDとは? なぜ必要なのか?
CI/CDは、継続的インテグレーション (Continuous Integration) と 継続的デリバリー/デプロイ (Continuous Delivery/Deployment) の略です。
CI (継続的インテグレーション): 開発者が書いたコードを頻繁にメインのリポジトリにマージし、そのたびに自動でビルドやテストを実行する仕組みです。これにより、問題を早期に発見できます。
CD (継続的デリバリー/デプロイ): CIを通過したコードを、自動的に本番環境(またはステージング環境)へリリースできるようにする仕組みです。手作業によるミスをなくし、迅速に新機能をユーザーに届けることができます。
これを導入することで、「手元では動いたのに、サーバーに上げたら動かない…」「リリース作業が毎回緊張する…」といった開発のよくある悩みから解放され、より創造的な作業に集中できるようになります。
アプリケーションの構成
今回CI/CDパイプラインに乗せていくのは、シンプルなAPIサーバーです。
- バックエンド: FastAPI (PythonのWebフレームワーク)
- データベース: PostgreSQL
この2つをDockerコンテナとして起動し、連携させます。
開発環境の構築手順
それでは、実際にWSL上で開発環境を構築していきましょう。
1. WSLにDocker CEをインストール
以前の記事を参考に
3. 作業ディレクトリの作成
まず、作業用のディレクトリ(例えば cicd-learning)を作成し、その中に移動します。
mkdir cicd-learning cd cicd-learning
4. FastAPIアプリケーションの準備
srcというディレクトリを作成し、その中にFastAPIのコードと必要なライブラリを記述したファイルを作成します。
mkdir src
src/requirements.txt: 必要なPythonライブラリを列挙します。
fastapi uvicorn[standard] sqlalchemy psycopg2-binary
src/main.py: APIサーバー本体のコードです。
import os from fastapi import FastAPI, Depends, HTTPException from sqlalchemy import create_engine, text from sqlalchemy.orm import sessionmaker, Session from sqlalchemy.exc import OperationalError import time # 環境変数からデータベースURLを取得 DATABASE_URL = os.getenv("DATABASE_URL") # データベースエンジンを作成 engine = create_engine(DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) app = FastAPI() # DB接続を試みる関数 def try_db_connection(): for i in range(10): # 10回リトライ try: with engine.connect() as connection: connection.execute(text("SELECT 1")) print("Database connection successful.") return except OperationalError as e: print(f"Database connection failed. Retrying... ({i+1}/10)") time.sleep(3) raise Exception("Could not connect to the database.") # アプリケーション起動時にDB接続を確認 @app.on_event("startup") def on_startup(): try_db_connection() # DBセッションを取得するためのDependency def get_db(): db = SessionLocal() try: yield db finally: db.close() @app.get("/") def read_root(): return {"message": "Hello from FastAPI with PostgreSQL!"} @app.get("/db-check") def db_check(db: Session = Depends(get_db)): try: result = db.execute(text("SELECT 1")).scalar() return {"db_status": "ok", "result": result} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.get("/db-version") def db_version(db: Session = Depends(get_db)): try: result = db.execute(text("SELECT version()")).scalar() return {"db_version": result} except Exception as e: raise HTTPException(status_code=500, detail=str(e))
5. Dockerfileの作成
次に、FastAPIアプリケーションをコンテナ化するための設計図であるDockerfileを作成します。
Dockerfile:
# Pythonの公式イメージをベースにする FROM python:3.9-slim # 作業ディレクトリを設定 WORKDIR /app # 必要なライブラリをインストール COPY src/requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # アプリケーションのソースコードをコピー COPY ./src /app/src # コンテナ起動時に実行するコマンド CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
6. docker-compose.ymlの作成
apiサービスとdbサービスをまとめて起動・連携させるために、docker-compose.ymlを作成します。
docker-compose.yml:
version: '3.8' services: api: build: . ports: - "8000:8000" volumes: - ./src:/app/src environment: - DATABASE_URL=postgresql://user:password@db:5432/mydatabase depends_on: db: condition: service_healthy command: uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload db: image: postgres:15 environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=password - POSTGRES_DB=mydatabase volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d mydatabase"] interval: 5s timeout: 5s retries: 5 volumes: postgres_data:
7. コンテナの起動
全てのファイルが準備できたら、以下のコマンドでコンテナを起動します。docker-composeではなくdocker compose(ハイフンなし)である点に注意してください。
docker compose up --build
初回はDockerイメージのビルドに少し時間がかかります。コンソールにDatabase connection successful.やApplication startup complete.といったログが表示されれば成功です。
8. 動作確認
ブラウザで http://localhost:8000 にアクセスしてみてください。
{"message":"Hello from FastAPI with PostgreSQL!"} と表示されれば、APIサーバーは正常に動いています。
次に、http://localhost:8000/db-check にアクセスします。
{"db_status":"ok","result":1} と表示されれば、PostgreSQLとの接続も成功しています。
最後に、新しいエンドポイント http://localhost:8000/db-version にアクセスします。
{"db_version":"PostgreSQL 15..."} のように、PostgreSQLのバージョン情報が表示されれば完璧です。
最後に
今回は、CI/CD学習の第一歩として、WSL上にDocker CEを直接インストールし、FastAPI+PostgreSQLの実行環境を構築しました。docker composeを使うことで、複数のサービスが連携するアプリケーションも簡単に立ち上げることができました。
しかし、ここまではまだ手作業での実行です。次回は、いよいよGitLab CI/CDを導入し、コードをプッシュしたら自動でDockerイメージがビルドされる、CIパイプラインの構築に挑戦します。お楽しみに!