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?

Docker初心者がフルスタックアプリを構築してみた【React/Hono/PostgreSQL/Docker】

1
Posted at

はじめに

Dockerの理解を目的に、フルスタックアプリコンテナで動かしてみました!
その過程で気づいたことや困ったことを紹介します。

↓今回作成したアプリのリポジトリ

作ったもの

学習内容と学習時間を記録できるシンプルなアプリです。

学習記録アプリ

スクリーンショット 2026-07-04 9.42.17.png
学習内容、学習時間を入力し、登録ボタンを押すとDBに学習記録が登録されます。

技術スタック

  • React(TypeScript)
  • Hono(TypeScript)
  • PostgreSQL
  • Docker

アーキテクチャ

image.png

フロントエンドバックエンドデータベースのコンテナをそれぞれ立ち上げています。

ディレクトリ構造

project/
├── docker-compose.yml
├── backend/
│   ├── Dockerfile
│   └── src/
└── frontend/
    ├── Dockerfile
    └── src/

フロントエンド、バックエンドはそれぞれDockerfileを書き、データベースは配布されているPostgreSQLのイメージを使用しています。
そして、docker-compose.ymlで三つのコンテナを立ち上げるための設定を記述しています。

Dockerfile, docker-compose.yml

frontend/Dockerfile
FROM node:20-alpine

WORKDIR /app

COPY . .

RUN npm install

EXPOSE 5173

CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]

フロントエンドのコードをコンテナ内にコピーし、コンテナ内の5173番ポートでアプリを立ち上げる設定を書いています。

backend/Dockerfile
FROM node:22-alpine

WORKDIR /app

COPY . .

RUN npm install

EXPOSE 3000

CMD ["sh", "-c", "npx drizzle-kit generate && npx drizzle-kit migrate && npm run dev"]

こちらも同じようにバックエンドのコードをコピーして、コンテナ内の3000番ポートで立ち上げる設定です。

また、立ち上げる前にマイグレーションをおこなっています。後ほど記載しますが、このマイグレーションで詰まりました。

docker-compose.yml
version: "3.8"
services:
  client:
    build: ./frontend
    container_name: my-container
    ports:
      - "5173:5173"
    depends_on:
      - api
    volumes:
      - ./frontend:/app
      - /app/node_modules

  api:
    build: ./backend
    environment:
      DATABASE_URL: postgresql://user:password@db:5432/mydatabase
    container_name: api
    ports:
      - "3000:3000"
    depends_on:
      - db
    volumes:
      - ./backend:/app
      - /app/node_modules

  db:
    image: postgres:16-alpine
    container_name: my-postgre-db
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydatabase
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  db_data:

Dockerfileと配布されているPostgreSQLのイメージを元にコンテナを三つ作成する設定が書かれています。

Dockerfileにはコンテナ内のどのポートを使うかという設定のみでしたが、ここではそのコンテナ内のポートと自分のPCのローカルホストを繋ぐためのポートマッピングをおこなっています。

また、正しい順番で立ち上がって欲しいので、depends_onでコンテナの依存関係を指定しています。これは、データベースよりも先にapiコンテナが作成されてしまった場合、マイグレーションに失敗してしまうためです。

難しかったところ

マイグレーションに失敗した

マイグレーションがうまくいかず、データベースが使えませんでした。結論から言うと、使っていたDATABASE_URLが原因でした。

エラーが発生したURL

DATABASE_URL=postgresql://user:password@localhost:5432/mydatabase

修正後のURL

DATABASE_URL=postgresql://user:password@db:5432/mydatabase

どういうことかというと、マイグレーションはこのURLを元にバックエンドから実行されます。(backend/Dockerfileに書いた設定)
なので、localhost:5432とはバックエンドのlocalhost:5432を指します。ですが、下の図を見たらわかるように参照したいのはdbコンテナのlocalhost:5432です。

image.png

よって、DATABASE_URLではdb:5432と指定する必要があります。(docker-compose.ymlで決めた名前)

学び・気づき

コンテナごとにlocalhost:5432がある

「難しかったところ」で述べたようにコンテナは一つのPCみたいなものなので、それぞれにlocalhostが存在します。それを踏まえた宛先の指定が必要であることを学びました。

なぜDockerが便利なのかがわかった

今までは実際に触ったことがなかったので、「環境を統一できるから便利」と何となくの認識でした。
しかし、今回実際にコンテナを立ててみて、Node.jsのバージョンはDockerfileで指定されているし、パッケージのバージョンはもちろんpackage-lock.jsonで指定されているのでバージョンずれが起きようがないことを知り、便利さを実感しました。
これで別PCやサーバーで使うとしてもgit cloneしてdocker compose upするだけで同じ開発環境を再現することができます。

Dockerfile, Docker Imageを理解できた

こちらも実際に触るまでは何となく設計図みたいなイメージはあったのですが、DockerfileDocker Imageの違いをわかっていませんでした。
実際にDockerfile, Docker Imageの中身を見てみたことでどんな違いがあるのかはっきり理解することができました。どちらも設計図ですが、Docker Imageの方はより具体的な内容になっていて、jsonで書かれています。

今度の展望

デプロイ

今回作成したアプリを実際にEC2などにデプロイすることでDockerコンテナのデプロイを体験してみたいです。

Docker Hub

PostgreSQLのイメージを使うことにしかDocker Hubを使ったことがないので、今回作成したイメージをDocker Hubに保存してみたいです。

マルチステージビルド

実務を想定してマルチステージビルドを採用したデプロイをおこなってみたいです。開発環境にしか必要ないファイルを実行用コンテナに含めないことで軽量にするという考え方らしいです。

↓マルチステージビルドの説明

参考文献

おわりに

今回のアプリはLTで発表したのですが、誰かに発表することを目的にするとものすごく理解が深まるように感じました。
今後も積極的にLTに参加して知識を増やしていきたいです!

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?