1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform で Nginx + Flask + PostgreSQL の 3 コンテナ構成を自動構築する

1
Last updated at Posted at 2026-04-29

Terraform を使って
Nginx / Flask / PostgreSQL の 3 コンテナ構成を自動構築する手順をまとめます。

Windows / macOS / Linux すべてで動作し、
terraform apply だけで Web アプリ環境が立ち上がります。

自学自習のためにお試しで作成。まずは手元にあるWindows環境で試してみたものになります。

🎯 アーキテクチャ

ブラウザ
   │
   ▼
Nginx (web)
   │ reverse proxy
   ▼
Flask (app)
   │ psycopg2
   ▼
PostgreSQL (pg)

📁 ディレクトリ構成

project-root/
├── main.tf
├── nginx/
│   └── default.conf
└── app/
    ├── Dockerfile
    ├── requirements.txt
    └── app.py

📝 Nginx 設定(nginx/default.conf)

nginx
server {
    listen 80;

    location / {
        proxy_pass http://app:5000;
    }
}

🐍 Flask アプリ(app/app.py)

python
from flask import Flask
import psycopg2

app = Flask(__name__)

@app.route("/")
def index():
    try:
        conn = psycopg2.connect(
            host="pg",
            port=5432,
            user="exampleuser",
            password="examplepass",
            dbname="exampledb"
        )
        cur = conn.cursor()
        cur.execute("SELECT 'DB OK' AS status;")
        result = cur.fetchone()
        return f"Connected to DB: {result[0]}"
    except Exception as e:
        return f"DB Error: {e}"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

📦 Dockerfile(app/Dockerfile)

dockerfile
FROM python:3.10-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "app.py"]

📚 requirements.txt

コード
flask
psycopg2-binary

🧱 Terraform(main.tf)

Windows でも確実に動くように abspath()depends_on を使用。

hcl
terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0.1"
    }
  }
}

provider "docker" {}

resource "docker_network" "app_net" {
  name = "app_network"
}

resource "docker_image" "postgres" {
  name = "postgres:15"
}

resource "docker_container" "postgres" {
  name  = "pg"
  image = docker_image.postgres.image_id

  env = [
    "POSTGRES_PASSWORD=examplepass",
    "POSTGRES_USER=exampleuser",
    "POSTGRES_DB=exampledb"
  ]

  networks_advanced {
    name = docker_network.app_net.name
  }

  ports {
    internal = 5432
    external = 5432
  }
}

resource "docker_image" "app" {
  name = "myapp:latest"
  build {
    context = "${path.module}/app"
  }
}

resource "docker_container" "app" {
  name  = "app"
  image = docker_image.app.image_id

  networks_advanced {
    name = docker_network.app_net.name
  }

  depends_on = [
    docker_container.postgres
  ]
}

resource "docker_image" "nginx" {
  name = "nginx:latest"
}

resource "docker_container" "nginx" {
  name  = "web"
  image = docker_image.nginx.image_id

  networks_advanced {
    name = docker_network.app_net.name
  }

  ports {
    internal = 80
    external = 8000
  }

  volumes {
    host_path      = abspath("${path.module}/nginx/default.conf")
    container_path = "/etc/nginx/conf.d/default.conf"
  }

  depends_on = [
    docker_container.app
  ]
}

▶ セットアップ

1. Terraform 初期化

コード
terraform init

2. 構築

コード
terraform apply

🌍 動作確認

ブラウザでアクセス:

コード
http://localhost:8000

表示:

コード
Connected to DB: DB OK

これが出れば成功。

🧹 クリーンアップ

コード
terraform destroy

📝 補足

  • Windows の場合、Nginx の設定ファイルは abspath() を使わないと絶対パス扱いにならずエラーになります。

  • Nginx は Flask より先に起動すると DNS 解決に失敗するため、depends_on を設定しています。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?