DockerでRedisを使いこなす!コンテナでのデプロイ方法

DockerでRedisを使いこなす!コンテナでのデプロイ方法

はじめに

今日のソフトウェア開発において、スケーラビリティ、高速性、そして柔軟性は不可欠な要素です。インメモリデータストアの代表格であるRedisは、その高速なデータ処理能力と多様なデータ構造により、キャッシュ、セッション管理、リアルタイム分析、メッセージキューなど、多岐にわたるアプリケーションで活用されています。一方で、Dockerはアプリケーションのデプロイ、管理、実行を劇的に簡素化するコンテナ技術のデファクトスタンダードです。

この2つの強力なツールを組み合わせることで、開発者はRedisのポテンシャルを最大限に引き出しつつ、環境構築の複雑さから解放され、再現性の高い開発・運用環境を構築できます。本記事では、「DockerでRedisを使いこなす!」をテーマに、Redisコンテナの基本的な起動から、データの永続化、Docker Composeによる複数コンテナ管理、セキュリティ設定、さらには実際のアプリケーションとの連携まで、詳細かつ網羅的に解説します。

約5000語にわたるこのガイドを通して、あなたはRedisとDockerの連携に関する深い知識を習得し、堅牢で効率的なシステム構築のための強力な一歩を踏み出せるでしょう。初心者の方から、さらにスキルアップを目指す経験者の方まで、幅広く役立つ内容を目指します。

さあ、DockerとRedisの世界へ飛び込みましょう!


第1章: DockerとRedisの基本理解

DockerとRedisを効果的に連携させるためには、それぞれの技術の基本的な概念をしっかりと理解することが重要です。この章では、両者の核心に迫り、なぜこれらを組み合わせることが強力なのかを探ります。

1.1 Dockerの基本

Dockerは、コンテナという単位でアプリケーションとその依存関係をパッケージ化し、あらゆる環境で一貫した動作を可能にするプラットフォームです。

1.1.1 コンテナとは何か? 仮想マシンとの違い

  • コンテナ: アプリケーションとその実行に必要なもの(コード、ランタイム、システムツール、ライブラリ、設定など)をすべて含んだ、軽量で独立した実行環境です。ホストOSのカーネルを共有するため、仮想マシンに比べて起動が速く、リソース消費も少ないのが特徴です。隔離性があり、アプリケーション間の競合を防ぎます。
  • 仮想マシン (VM): ホストOSの上にハイパーバイザーを介してゲストOS(完全なOS)を起動し、その上でアプリケーションを実行するものです。各VMは独立したOSを持つため、リソース消費が大きく、起動もコンテナより遅いです。しかし、完全なOSレベルの隔離が保証されます。

主要な違い:

特徴 コンテナ 仮想マシン
隔離レベル OSカーネルを共有、プロセスレベルの隔離 各VMが独自のOSを持つ、OSレベルの隔離
リソース 軽量、効率的 重い、リソース消費が大きい
起動時間 秒単位 分単位
ポータビリティ イメージとして簡単に共有・移動可能 VMイメージも共有可能だが、コンテナより重い
用途 マイクロサービス、CI/CD、開発環境 サーバー仮想化、複数のOSを実行

1.1.2 Docker Engine, Docker Hub, Dockerfile, Docker Composeの概念

  • Docker Engine: Dockerの中核をなすサービスで、コンテナのビルド、実行、管理を行います。クライアント(CLI)からのコマンドを受け取り、デーモンが実際の処理を実行します。
  • Docker Hub: Dockerイメージを共有・公開するためのクラウドベースのレジストリサービスです。Redisのような公式イメージや、コミュニティが作成したイメージをダウンロード(pull)したり、自身のイメージをアップロード(push)したりできます。
  • Dockerfile: Dockerイメージを自動的に構築するための一連の命令を記述したテキストファイルです。これを使えば、アプリケーションの実行環境をコードとして定義し、バージョン管理することが可能です。
  • Docker Compose: 複数のDockerコンテナで構成されるアプリケーションを、単一のYAMLファイル (docker-compose.yml) で定義し、まとめて管理するためのツールです。これにより、複雑なマルチコンテナアプリケーションの起動、停止、ビルドなどを簡単に行うことができます。

1.1.3 Dockerのインストール方法 (OS別概要)

Dockerは、Windows、macOS、Linuxの主要なOSにインストールできます。

  • Windows / macOS: Docker Desktopをインストールするのが最も簡単です。これにはDocker Engine、Docker CLI、Docker Compose、Kubernetesなどの必要なツールがすべて含まれています。
  • Linux: 各ディストリビューション(Ubuntu, CentOSなど)の公式パッケージマネージャーを通じてインストールする方法が推奨されます。

インストール方法の詳細については、Docker公式ドキュメントを参照してください。

1.2 Redisの基本

Redis (Remote Dictionary Server) は、高性能なオープンソースのインメモリデータ構造ストアです。一般的には「キーバリュー型データベース」に分類されますが、単なるキーバリュー以上の機能を持っています。

1.2.1 Redisとは何か? (概要、特徴、用途)

  • 概要: データをメインメモリに保持することで、非常に高速な読み書きを実現します。データの永続化オプションも提供しており、障害時にもデータを復旧できます。
  • 特徴:
    • インメモリ: データの大部分をRAMに保持するため、HDDやSSDへのアクセスがボトルネックになる従来のデータベースよりも圧倒的に高速です。
    • 多様なデータ構造: 単純な文字列(String)だけでなく、ハッシュ(Hash)、リスト(List)、セット(Set)、ソート済みセット(Sorted Set)など、様々なデータ構造をサポートしています。これにより、幅広いデータモデルに対応できます。
    • 永続化: RDB(スナップショット)とAOF(追記ログ)の2種類の永続化メカニズムを提供し、メモリ上のデータをディスクに保存してデータ損失を防ぎます。
    • Pub/Sub機能: パブリッシュ/サブスクライブモデルをサポートしており、リアルタイムなメッセージングシステムを構築できます。
    • トランザクション: 複数のコマンドをアトミックに実行する機能があります。
    • Luaスクリプト: サーバーサイドでアトミックなスクリプトを実行できます。
  • 用途:
    • キャッシュ: 最も一般的な用途。頻繁にアクセスされるデータをRedisに保存し、データベースへの負荷を軽減します。
    • セッションストア: Webアプリケーションのユーザーセッション情報を保存し、分散環境でのセッション共有を可能にします。
    • リアルタイムアナリティクス: 瞬時のデータ集計やランキング表示など。
    • メッセージキュー/ブローカー: Producer/Consumerモデルでの非同期通信。
    • レートリミッター: APIのアクセス制限など。
    • リードボード/ランキング: ソート済みセットを利用。

1.2.2 Redisのデータ構造 (String, Hash, List, Set, Sorted Set)

Redisが提供する主要なデータ構造は以下の通りです。

  1. String: 最も基本的なデータ型。テキスト、数値、バイナリデータなどを保存できます。単一のキーに対して単一の値を関連付けます。
    • 例: SET user:1:name "Alice", GET user:1:name
  2. Hash: オブジェクトを表現するのに適しています。単一のキーに対して複数のフィールドと値を関連付けます。
  3. List: 挿入順序が保持される文字列のコレクションです。キューやスタックとして使用できます。
    • 例: LPUSH messages "Hello", RPUSH messages "World", LRANGE messages 0 -1
  4. Set: 順序を持たない、一意な文字列のコレクションです。集合演算(和集合、積集合、差集合)が可能です。
    • 例: SADD tags "web" "backend" "database", SMEMBERS tags
  5. Sorted Set: セットと同様に一意な文字列のコレクションですが、各メンバーにスコア(浮動小数点数)が関連付けられ、そのスコアに基づいてソートされます。ランキングや優先度キューに最適です。
    • 例: ZADD leaderboard 100 "Alice" 150 "Bob", ZRANGE leaderboard 0 -1 WITHSCORES

これらのデータ構造を使いこなすことで、Redisは多様なアプリケーションロジックを効率的にサポートします。

1.3 なぜDockerでRedisを使うのか?

DockerとRedisを組み合わせることで、開発者と運用者の双方に多くのメリットがもたらされます。

  • 環境構築の容易さ: Dockerイメージを使えば、Redisを数秒で起動できます。OSの依存関係やライブラリのインストールに悩む必要がなくなります。
  • 再現性と移植性: Dockerイメージはどこで実行しても同じ環境を提供します。開発、テスト、本番環境で全く同じRedisインスタンスが動作することを保証し、”私のマシンでは動いたのに…”という問題を解消します。
  • 分離性: Redisを他のアプリケーションやサービスから分離されたコンテナ内で実行することで、互いの依存関係や設定の衝突を防ぎます。各サービスが独立して動作するため、システムの安定性が向上します。
  • リソース管理: DockerはCPU、メモリ、ネットワーク帯域などのリソースをコンテナごとに制限・管理できます。これにより、Redisが必要とするリソースを適切に割り当て、他のサービスへの影響を最小限に抑えられます。
  • スケーラビリティとマイクロサービスとの親和性: Docker ComposeやKubernetesのようなオーケストレーションツールと組み合わせることで、Redisコンテナのスケールアウトや、マイクロサービスアーキテクチャ内での動的なデプロイが容易になります。
  • 開発・テスト環境の効率化: 開発者はローカルマシン上で本番に近いRedis環境を簡単に構築し、アプリケーションとの連携をテストできます。CI/CDパイプラインにも組み込みやすく、自動テストの信頼性を高めます。
  • バージョン管理: 特定のRedisバージョンをピンポイントで利用でき、バージョンアップ時の影響を最小限に抑えながらテストを進めることができます。

これらの理由から、DockerコンテナでRedisを運用することは、現代のソフトウェア開発・運用におけるベストプラクティスの一つと言えるでしょう。


第2章: Redisコンテナの基本的な起動方法

この章では、Dockerを使ってRedisコンテナを起動し、操作する最も基本的な手順を学びます。

2.1 Docker HubからのRedisイメージの取得

Docker Hubには、Redisの公式イメージが公開されています。このイメージを使用することで、簡単にRedisサーバーを起動できます。

まず、Redisイメージをローカルにダウンロードします。

bash
docker pull redis

このコマンドは、redis:latest、つまり利用可能な最新の安定版Redisイメージをダウンロードします。

タグの選択 (latest, stable, specific versions)

latest タグは常に最新の安定版を指しますが、本番環境では特定のバージョンを指定することを強く推奨します。これにより、予期せぬバージョンアップによる互換性の問題を避けることができます。

  • 特定のバージョンを指定する場合:
    bash
    docker pull redis:6.2.7 # Redis 6.2.7 をダウンロード
    docker pull redis:alpine # 軽量版のRedisイメージ (Alpine Linuxベース)

    alpine バージョンはイメージサイズが非常に小さいため、ディスクスペースやネットワーク帯域が限られる環境で特に有用です。機能面での大きな違いはありません。

ダウンロードが完了したイメージは、以下のコマンドで確認できます。

bash
docker images

2.2 Redisコンテナの単体起動

イメージがダウンロードできたら、いよいよRedisコンテナを起動します。

docker run コマンドの詳細解説

Redisコンテナを起動するには docker run コマンドを使用します。このコマンドには様々なオプションがあり、コンテナの動作を細かく制御できます。

基本的な構文: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

主要なオプション:

  • -d, --detach: コンテナをバックグラウンドで実行します。これにより、ターミナルが占有されることなく、他の作業を続けることができます。
  • -p, --publish: ホストOSとコンテナ間でポートをマッピングします。構文は ホストポート:コンテナポート です。Redisのデフォルトポートは6379です。
  • --name: コンテナにわかりやすい名前を付けます。名前を付けることで、docker psdocker stopdocker rm などのコマンドでコンテナを識別しやすくなります。
  • -v, --volume: ホストOSのディレクトリやDockerボリュームをコンテナ内にマウントし、データの永続化を可能にします。このオプションについては次章で詳しく解説します。
  • --rm: コンテナが停止した際に自動的に削除します。一時的なテスト用途に適しています。本番環境での永続的なコンテナには使用しません。
  • --network: コンテナを特定のDockerネットワークに接続します。

例: 基本的なRedisコンテナの起動

それでは、Redisコンテナを起動してみましょう。

bash
docker run -d --name my-redis -p 6379:6379 redis

このコマンドの意味:

  • docker run: Dockerコンテナを起動する。
  • -d: コンテナをデタッチモード(バックグラウンド)で実行する。
  • --name my-redis: このコンテナに my-redis という名前を付ける。
  • -p 6379:6379: ホストOSのポート6379を、コンテナ内部のポート6379にマッピングする。これにより、ホストOSから localhost:6379 でRedisにアクセスできるようになります。
  • redis: 起動するイメージ名(ここでは redis:latest がデフォルトで使われます)。

コンテナが正常に起動したか確認するには、以下のコマンドを実行します。

bash
docker ps

STATUS 列が Up となっていれば、コンテナは正常に動作しています。

2.3 起動したRedisコンテナへの接続

Redisコンテナが起動したら、実際にデータを保存したり取得したりしてみましょう。

redis-cli の利用

Redisにアクセスするためのクライアントツールとして redis-cli があります。これをホストから直接、またはコンテナ内で使用できます。

A. ホストOSから redis-cli を使って接続する

ホストOSに redis-cli がインストールされている場合、先ほどポートマッピング (-p 6379:6379) を行ったので、直接接続できます。

bash
redis-cli -h 127.0.0.1 -p 6379

もしホストOSに redis-cli がインストールされていない場合、一時的に別のDockerコンテナを起動して接続することも可能です。

“`bash
docker run -it –rm –network host redis redis-cli # ホストネットワークを利用

または、コンテナ名で指定

docker run -it –rm –link my-redis:redis redis redis-cli -h redis -p 6379
``
*補足:
–network hostは直接ホストのネットワークスタックに接続するため、ホストのlocalhost:6379にアクセスできます。–linkは古い機能ですが、Docker Composeを使う場合はサービス名で名前解決ができます。単体コンテナの場合はIPアドレスか、後述のdocker exec`がより一般的です。*

B. Redisコンテナ内部から redis-cli を使って接続する

docker exec コマンドを使うと、起動中のコンテナ内で任意のコマンドを実行できます。

bash
docker exec -it my-redis redis-cli

このコマンドの意味:

  • docker exec: 起動中のコンテナ内でコマンドを実行する。
  • -it: インタラクティブモードで、擬似TTYを割り当てる。これにより、通常のターミナルセッションのように操作できます。
  • my-redis: コマンドを実行する対象のコンテナ名。
  • redis-cli: コンテナ内で実行するコマンド。

簡単なRedisコマンドの実行

redis-cli プロンプトが表示されたら、いくつかのRedisコマンドを試してみましょう。

  1. 接続確認:
    redis
    PING
    PONG
  2. データの保存: SET コマンドでキーと値を保存します。
    redis
    SET mykey "Hello Docker Redis!"
    OK
  3. データの取得: GET コマンドでキーに対応する値を取得します。
    redis
    GET mykey
    "Hello Docker Redis!"
  4. 保存したキーの確認:
    redis
    KEYS *
    1) "mykey"
  5. 終了:
    redis
    exit

これで、Redisコンテナが正常に動作し、データの読み書きができることを確認できました。

2.4 コンテナの停止、再起動、削除

不要になったコンテナは適切に管理することが重要です。

  • コンテナの停止:
    bash
    docker stop my-redis

    これはコンテナに終了シグナル (SIGTERM) を送信し、プロセスがクリーンに終了するのを待ちます。
    もしすぐに停止したい場合は docker kill my-redis を使いますが、これはSIGKILLを送信するため、データが失われる可能性があります。

  • コンテナの再起動:
    bash
    docker restart my-redis

    停止中のコンテナを再起動します。

  • コンテナの削除:
    コンテナを削除する前に、必ず停止しておく必要があります。
    bash
    docker rm my-redis

    もし起動中のコンテナを強制的に削除したい場合は、-f (force) オプションを使用します。
    bash
    docker rm -f my-redis

コンテナを削除しても、イメージは残ります。イメージを削除するには docker rmi コマンドを使用します。
bash
docker rmi redis # redisイメージを削除 (ただし、そのイメージを使っているコンテナが残っていると削除できない)

この章では、Redisコンテナの最も基本的な操作を学びました。次の章では、より実用的な「データの永続化」について深く掘り下げていきます。


第3章: Redisデータの永続化と管理

Dockerコンテナは本質的に揮発性です。つまり、コンテナが停止・削除されると、そのコンテナ内で保存されたデータは失われます。Redisのようなデータベースでは、データが失われることは許されません。この章では、Redisデータを永続化するためのDockerのメカニズムと、Redis自身の永続化オプションについて解説します。

3.1 なぜデータの永続化が必要なのか?

前述の通り、コンテナは一時的な実行環境であり、アプリケーションの実行に必要な最小限のファイルシステムを持ちます。コンテナを停止したり削除したりすると、コンテナ内のファイルシステムへの変更は失われます。これは開発やテスト環境では便利ですが、データベースのように永続的にデータを保持する必要がある場合は大きな問題となります。

Redisのデータはデフォルトでメモリ上に存在するため、コンテナがクラッシュしたり、停止されたりすると、メモリ上のデータは消えてしまいます。これを防ぐためには、データをディスクに保存する仕組みが必要です。Dockerは、ホストOSのファイルシステムとコンテナ内のファイルシステムをリンクさせることで、この問題を解決します。

3.2 Docker Volumeによる永続化

Dockerでは、データの永続化のために主に「Docker Volume (ボリューム)」と「Bind Mount (バインドマウント)」の2つの方法を提供しています。

3.2.1 名前付きボリューム (Named Volumes)

名前付きボリュームは、Docker自身が管理するボリュームです。ホストOS上の特定のパスに保存されますが、ユーザーがそのパスを直接意識する必要はありません。

メリット:
* Dockerによる管理: Dockerがボリュームの作成、管理、場所の決定を行うため、ユーザーは煩わしさから解放されます。
* ポータビリティ: ボリュームはDockerによって管理されるため、Windows、macOS、Linux間で同じように動作します。
* バックアップ・移植の容易さ: docker volume cp (未実装) や外部ツールを使ってボリュームをバックアップしたり、別のホストに移動させたりするのが比較的容易です。
* データの共有: 複数のコンテナ間で同じボリュームを共有することも可能です。

名前付きボリュームの作成と使用:

  1. ボリュームの作成: docker volume create コマンドで名前付きボリュームを作成します。
    bash
    docker volume create my-redis-data
  2. Redisコンテナでの利用: docker run -v オプションを使って、作成したボリュームをRedisコンテナのデータディレクトリ (/data) にマウントします。
    bash
    docker run -d --name my-redis-persistent -p 6379:6379 -v my-redis-data:/data redis

    このコマンドを実行すると、Redisは /data ディレクトリに永続化されたデータを保存するようになります。my-redis-data ボリュームは、ホストOS上のDocker管理下の領域に保存されます。

  3. ボリュームの確認:

    • 既存のボリュームを一覧表示する:
      bash
      docker volume ls
    • 特定のボリュームの詳細情報を表示する:
      bash
      docker volume inspect my-redis-data

      Mountpoint フィールドが、ホストOS上の実際の保存パスを示します(例: /var/lib/docker/volumes/my-redis-data/_data)。
  4. ボリュームの削除:
    ボリュームを削除する前に、そのボリュームを使用しているコンテナがすべて停止または削除されていることを確認してください。
    bash
    docker volume rm my-redis-data

3.2.2 バインドマウント (Bind Mounts)

バインドマウントは、ホストOS上の特定のディレクトリをコンテナ内のディレクトリに直接マッピングする方法です。

メリット:
* シンプルさ: ホストOS上の既存のディレクトリをそのまま利用できるため、設定が直感的です。
* 開発用途に便利: ホストOSで編集したファイルを、コンテナ内でリアルタイムに反映させたい場合(例: 設定ファイル、ソースコード)に非常に適しています。

注意点:
* 権限の問題: ホストOS上のディレクトリの権限が適切に設定されていないと、コンテナ内のプロセスがファイルにアクセスできない場合があります。
* OS依存性: ホストOSのファイルシステム構造に依存するため、移植性が名前付きボリュームより劣る場合があります。

バインドマウントの使用:

  1. ホストOSにディレクトリを作成: まず、ホストOSの任意の場所にデータを保存するためのディレクトリを作成します。
    bash
    mkdir -p ~/docker-redis-data

    (-p オプションは、必要な親ディレクトリも作成します。)

  2. Redisコンテナでの利用: docker run -v オプションを使って、ホストOSのディレクトリをRedisコンテナのデータディレクトリ (/data) にマウントします。
    bash
    docker run -d --name my-redis-bind-mount -p 6379:6379 -v ~/docker-redis-data:/data redis

    このコマンドにより、Redisが /data に書き込むデータは、ホストOSの ~/docker-redis-data ディレクトリに直接保存されます。

どちらを選ぶべきか?:

  • 名前付きボリューム: データの永続化が必要な本番環境、複数のコンテナでデータを共有したい場合、ポータビリティを重視する場合に推奨されます。
  • バインドマウント: 開発環境で設定ファイルを変更しながら試したい場合、ソースコードをコンテナと共有したい場合など、ホストOSから直接データにアクセス・管理したい場合に便利です。

Redisのデータ永続化には、名前付きボリュームが一般的に推奨されます。

3.3 Redisの永続化オプション

Dockerの永続化メカニズムに加えて、Redis自身もデータをディスクに保存する永続化機能を持っています。これらを適切に設定することで、より堅牢なデータ保護が可能になります。Redisは主に以下の2つの永続化方法を提供します。

3.3.1 RDB (Redis Database Backup): スナップショット

RDBは、ある時点でのRedisのメモリ上のデータをディスクにバイナリ形式でスナップショットとして保存する機能です。

  • 特徴:
    • 設定された時間間隔とキーの変更数に基づいて自動的に保存されます。
    • 高速なリカバリが可能です(バイナリ形式のため読み込みが速い)。
    • ファイルサイズが比較的小さいです。
    • 直近のデータ変更が失われる可能性があります(スナップショット間隔の分)。
  • 設定: redis.conf ファイルで設定します。
    # 900秒(15分)以内に1回でもキーが変更されたら保存
    save 900 1
    # 300秒(5分)以内に10回以上キーが変更されたら保存
    save 300 10
    # 60秒(1分)以内に10000回以上キーが変更されたら保存
    save 60 10000

    これらの設定はデフォルトで有効になっています。スナップショットファイル (dump.rdb) は /data ディレクトリに保存されます。

3.3.2 AOF (Append Only File): コマンドログ

AOFは、Redisサーバーへの書き込みコマンドをすべてログとしてファイルに追記していく方式です。

  • 特徴:
    • RDBよりも高いデータ整合性を提供します(直近の書き込みまで保存されるため)。
    • ファイルサイズは大きくなる傾向があります。
    • リカバリに時間がかかることがあります(コマンドを再実行するため)。
    • 設定により、書き込み頻度(毎秒、毎書き込みなど)を調整できます。
  • 設定: redis.conf ファイルでAOFを有効にし、同期オプションを設定します。
    appendonly yes
    # appendfsync always # すべての書き込みを即座にディスクに同期(最も安全だが性能が低い)
    appendfsync everysec # 毎秒同期(デフォルト、推奨)
    # appendfsync no # 同期しない(OSに任せる、最も性能が良いが安全性が低い)

    AOFファイル (appendonly.aof) も /data ディレクトリに保存されます。

RDBとAOFの選択:

  • データ損失を最小限に抑えたい場合: appendonly yesappendfsync everysec でAOFを有効にするのが一般的です。
  • 高速な起動とバックアップを重視する場合: RDBを利用します。
  • 両方を組み合わせる: 多くのプロダクション環境では、両方の永続化メカニズムを有効にして、最大限のデータ保護とリカバリ速度のバランスを取ります。RedisはRDBとAOFの両方が有効な場合、AOFを優先してデータをロードします。

redis.conf を利用した設定 (コンテナ内で設定ファイルをマウントする方法)

Redisの永続化オプションやその他の設定(認証パスワードなど)は、redis.conf ファイルで制御します。このファイルをDockerコンテナに適用するには、バインドマウントを利用するのが一般的です。

  1. ホストOSに redis.conf ファイルを作成:
    例えば、以下のような内容で my-redis.conf ファイルを作成します。
    “`conf
    # my-redis.conf
    # RDB永続化設定 (デフォルトで有効)
    save 900 1
    save 300 10
    save 60 10000

    AOF永続化を有効化

    appendonly yes
    appendfsync everysec

    Redisのデフォルトポート

    port 6379

    認証パスワードを設定 (セキュリティの強化)

    requirepass your_strong_password_here

    最大メモリ制限 (例: 256MB)

    maxmemory 256mb

    maxmemory-policy noeviction

    ``
    maxmemorymaxmemory-policy` は、メモリが一杯になった際の挙動を定義します。本番環境では非常に重要です。)

  2. Redisコンテナ起動時に設定ファイルをマウント:
    ホストOSの my-redis.conf をコンテナ内の /usr/local/etc/redis/redis.conf にマウントし、その設定ファイルを使ってRedisを起動します。
    bash
    docker run -d --name my-redis-custom -p 6379:6379 \
    -v ~/docker-redis-data:/data \
    -v ~/my-redis.conf:/usr/local/etc/redis/redis.conf \
    redis redis-server /usr/local/etc/redis/redis.conf

    • -v ~/my-redis.conf:/usr/local/etc/redis/redis.conf: ホストの my-redis.conf をコンテナ内の所定のパスにマウントします。
    • redis-server /usr/local/etc/redis/redis.conf: Redisコンテナの起動コマンドを上書きし、マウントした設定ファイルを指定してRedisサーバーを起動します。

これで、カスタマイズされた設定でRedisコンテナを起動し、データの永続化も適切に行うことができるようになりました。パスワード設定については、第5章でさらに詳しく解説します。


第4章: Docker Composeを使ったRedis環境の構築

単一のRedisコンテナを起動するだけなら docker run で十分ですが、実際のアプリケーションではWebサーバー、アプリケーションサーバー、データベースなど、複数のサービスが連携して動作することがほとんどです。Docker Composeは、このようなマルチコンテナアプリケーションの定義と管理を劇的に簡素化します。

4.1 Docker Composeとは何か?

Docker Composeは、複数のDockerコンテナで構成されるアプリケーションを定義・実行するためのツールです。YAML形式のファイル (docker-compose.yml) を使って、各サービスのイメージ、ポートマッピング、ボリューム、ネットワーク、依存関係などを一元的に記述できます。

Docker Composeの主な利点:
* 単一ファイルでの定義: アプリケーション全体の構成が docker-compose.yml ファイルにまとまり、可読性と管理性が向上します。
* 一貫した環境: 同じ docker-compose.yml ファイルを使えば、開発者間で全く同じ環境を簡単に共有・再現できます。
* 簡単な起動・停止: docker-compose up コマンド一つで、定義されたすべてのサービスを起動し、サービス間のネットワーク接続も自動的に設定されます。docker-compose down で全てのサービスを停止・削除できます。
* サービス間の名前解決: Docker Composeは独自のネットワークを構築し、サービス名を使って他のサービスにアクセスできます(例: アプリケーションコンテナから redis というホスト名でRedisコンテナに接続)。

4.2 Docker Composeのインストール (概要)

Docker Desktopをインストールしている場合、Docker Composeはすでに含まれています。Linux環境では、別途インストールが必要になる場合がありますが、多くの場合は公式ドキュメントに従って簡単にインストールできます。

  • 確認コマンド:
    bash
    docker compose version # 新しい構文
    # または
    docker-compose --version # 古い構文 (Pythonベース)

    現在のDocker推奨は docker compose (Docker CLIプラグインとして統合されたもの) ですが、古い docker-compose も依然として広く使われています。本記事では docker compose の構文を使用します。

4.3 基本的な docker-compose.yml の作成

Redisサービスのみを含むシンプルな docker-compose.yml ファイルを作成してみましょう。

  1. プロジェクトディレクトリの作成:
    bash
    mkdir my-redis-compose
    cd my-redis-compose

  2. docker-compose.yml ファイルの作成:
    my-redis-compose ディレクトリ内に docker-compose.yml という名前のファイルを作成し、以下の内容を記述します。

    “`yaml

    docker-compose.yml

    version: ‘3.8’ # Docker Composeファイルのバージョン。最新の推奨バージョンを使用。

    services:
    # Redisサービスを定義
    redis:
    image: redis:6.2.7 # 使用するRedisイメージのバージョンを指定 (latestではなく特定バージョンを推奨)
    container_name: my-redis-server # コンテナ名を指定 (任意)
    ports:
    – “6379:6379” # ホストの6379ポートをコンテナの6379ポートにマッピング
    volumes:
    # 名前付きボリューム ‘redis-data’ をコンテナの /data ディレクトリにマッピング
    – redis-data:/data
    restart: always # コンテナが終了した場合に常に再起動する設定 (本番環境向け)

    ボリュームの定義

    volumes:
    redis-data: # ‘redis-data’ という名前のボリュームを定義
    driver: local # ローカルストレージを使用 (デフォルト)
    “`

各セクションの解説:

  • version: '3.8': Docker Composeファイルの書式バージョンを指定します。新しい機能を利用するために最新版が推奨されます。
  • services: アプリケーションを構成する各サービスを定義するセクションです。
    • redis: サービス名です。この名前は、同じComposeファイル内の他のサービスからRedisにアクセスする際のホスト名として利用できます。
    • image: redis:6.2.7: このサービスで使用するDockerイメージを指定します。
    • container_name: my-redis-server: 生成されるコンテナのカスタム名を指定します。指定しない場合、Docker Composeが自動的に名前を生成します。
    • ports: - "6379:6379": ホストOSのポートとコンテナのポートをマッピングします。
    • volumes: - redis-data:/data: redis-data という名前付きボリュームを、コンテナ内の /data ディレクトリにマウントします。Redisはこの /data ディレクトリに永続化ファイルを保存します。
    • restart: always: コンテナが停止したり、Dockerデーモンが再起動されたりした場合に、常にコンテナを再起動するポリシーを設定します。本番環境で推奨される設定です。
  • volumes: services セクションで参照される名前付きボリュームを定義します。
    • redis-data:: redis-data というボリュームを定義します。Dockerがこれを管理します。
    • driver: local: ボリュームのストレージドライバーを指定します。local がデフォルトで、ホストのローカルファイルシステムに保存されます。

4.4 Docker Composeコマンド

docker-compose.yml ファイルを作成したら、以下のコマンドを使ってサービスを管理します。

  1. サービスを起動する:
    docker-compose.yml ファイルがあるディレクトリで実行します。
    bash
    docker compose up -d

    • up: 定義されたすべてのサービスを起動します。
    • -d: デタッチモードでバックグラウンドで実行します。

    初回実行時には、指定されたRedisイメージがダウンロードされ、コンテナが作成・起動されます。永続化のために redis-data ボリュームも自動的に作成されます。

  2. 起動中のサービスを確認する:
    bash
    docker compose ps

    これで、my-redis-server コンテナが Up 状態であることを確認できます。

  3. Redisに接続する:
    ホストOSから redis-cli を使って接続できます。
    bash
    redis-cli -h 127.0.0.1 -p 6379

    または、Docker Composeで起動したRedisコンテナ内で redis-cli を実行することもできます。
    bash
    docker compose exec redis redis-cli

    • exec redis: redis サービス(コンテナ)内でコマンドを実行します。
  4. サービスからのログを表示する:
    bash
    docker compose logs -f redis # redisサービスのログをリアルタイムで表示

    docker compose logs は、デフォルトですべてのサービスのログを表示します。 -f でフォローモードに、特定のサービス名でフィルターできます。

  5. サービスを停止する:
    bash
    docker compose stop

    定義されたすべてのサービスを停止します。

  6. サービスを停止し、リソース(コンテナ、ネットワーク、ボリューム)を削除する:
    bash
    docker compose down

    • down: up コマンドで作成されたコンテナ、ネットワークを停止・削除します。
    • 重要: デフォルトでは名前付きボリューム(redis-dataなど)は削除されません。データを保持したままコンテナだけを再構築したい場合に便利です。
    • ボリュームも削除したい場合は、-v オプションを付けます。
      bash
      docker compose down -v

      このコマンドは、コンテナ、ネットワークに加えて、定義されたボリュームも削除します。永続化されたデータも失われるため、注意して使用してください。

4.5 アプリケーションとRedisの連携 (Docker Compose)

Docker Composeの最大の利点は、複数のサービスを連携させて単一のアプリケーションとして動作させられる点です。ここでは、ダミーのWebアプリケーションとRedisを連携させる例を考えます。

基本的な考え方:
Docker Composeは、デフォルトで定義されたすべてのサービスを共有のDockerネットワークに配置します。このネットワーク内で、各サービスは互いにそのサービス名(例: redis)をホスト名として名前解決できます。

例: Webアプリケーション + Redis

my-web-app というWebアプリケーションが redis サービスに接続するシナリオを想定します。

  1. docker-compose.yml の更新:
    my-redis-compose ディレクトリ内に、以下の docker-compose.yml を作成または更新します。

    “`yaml

    docker-compose.yml

    version: ‘3.8’

    services:
    web:
    build:
    context: ./web_app # web_app ディレクトリ内の Dockerfile を参照
    ports:
    – “8000:80” # ホストの8000ポートをwebコンテナの80ポートにマッピング
    environment:
    # Redis接続情報を環境変数としてwebコンテナに渡す
    REDIS_HOST: redis # サービス名 ‘redis’ をホスト名として指定
    REDIS_PORT: 6379
    depends_on:
    – redis # webサービスはredisサービスに依存することを宣言 (起動順序を制御)
    restart: on-failure

    redis:
    image: redis:6.2.7
    container_name: my-redis-server
    ports:
    – “6379:6379” # ホストからのアクセスも許可するためマッピング
    volumes:
    – redis-data:/data
    restart: always

    volumes:
    redis-data:
    “`

  2. Webアプリケーションの準備:
    my-redis-compose ディレクトリ内に web_app という新しいディレクトリを作成し、その中にWebアプリケーションのコードと Dockerfile を配置します。

    • web_app/Dockerfile:
      dockerfile
      # web_app/Dockerfile
      FROM alpine/git:latest # 適当な軽量イメージ、実際はPython, Node.jsなどのベースイメージ
      # 実際にはここにアプリケーションのビルド・コピーコマンドが続く
      # 例: COPY . /app
      # WORKDIR /app
      # CMD ["python", "app.py"] など
      # 今回はデモのため、単純に起動するだけ
      CMD ["sh", "-c", "echo 'Web App started, connecting to Redis at $REDIS_HOST:$REDIS_PORT' && sleep infinity"]

      (注: これはダミーのDockerfileです。実際のWebアプリケーションのDockerfileは、使用する言語やフレームワークによって異なります。)

    • web_app/app.pyweb_app/index.js など、実際のアプリケーションファイルもここに配置されますが、ここでは動作確認が目的のため省略します。

  3. 実行:
    my-redis-compose ディレクトリで docker compose up -d を実行します。
    bash
    docker compose up -d --build

    • --build: web サービスで build を指定しているので、イメージが存在しない場合はビルドします。

これで、web サービスは redis というホスト名でRedisコンテナに接続できるようになります。アプリケーションコード内で REDIS_HOST 環境変数から redis を取得し、接続を試みることになります。

Docker Composeは、複数のコンテナからなる複雑なアプリケーションのローカル開発環境やステージング環境を構築する際に非常に強力なツールです。


第5章: Redisコンテナの高度な設定と運用

Redisコンテナを本番環境やより複雑なシナリオで利用する場合、セキュリティ、パフォーマンス、可用性に関する高度な設定と考慮事項が必要になります。

5.1 Redisの設定ファイル (redis.conf) の適用

第3章で触れましたが、redis.conf をバインドマウントしてRedisコンテナに適用することは、様々な設定をカスタマイズするための最も一般的な方法です。

カスタム設定ファイルをバインドマウントする方法

基本的なコマンドは以下の通りです。

bash
docker run -d --name my-redis-configured -p 6379:6379 \
-v /path/to/your/redis_data:/data \
-v /path/to/your/redis.conf:/usr/local/etc/redis/redis.conf \
redis redis-server /usr/local/etc/redis/redis.conf

Docker Composeを使用する場合は、volumes セクションに設定ファイルを指定します。

“`yaml

docker-compose.yml

version: ‘3.8’

services:
redis:
image: redis:6.2.7
container_name: my-redis-server
ports:
– “6379:6379”
volumes:
– ./redis_data:/data # ホストの./redis_dataをコンテナの/dataにマッピング
– ./redis.conf:/usr/local/etc/redis/redis.conf # ホストの./redis.confをコンテナにマッピング
command: redis-server /usr/local/etc/redis/redis.conf # マウントした設定ファイルを指定して起動
restart: always

volumes:
# 名前付きボリュームは利用しないが、ここでは参考までにコメントアウト
# redis-data:
``
この例では、プロジェクトディレクトリの直下に
redis_dataディレクトリとredis.conf` ファイルがあることを想定しています。

主要なRedis設定オプション

redis.conf で設定できる重要なオプションの一部を再確認し、さらに追加の説明を加えます。

  1. 認証 (requirepass):
    Redisはデフォルトで認証なしで動作します。本番環境では絶対にパスワードを設定すべきです。
    conf
    requirepass your_strong_password_here

    パスワードを設定すると、redis-cli で接続する際に AUTH your_strong_password_here または redis-cli -a your_strong_password_here で認証が必要です。
    アプリケーションから接続する場合も、Redisクライアントライブラリでパスワードを指定する必要があります。

  2. メモリ制限 (maxmemory, maxmemory-policy):
    Redisはインメモリデータベースであるため、使用可能なメモリ量を制限することが重要です。
    conf
    maxmemory 256mb # Redisが使用できるメモリの最大値を256MBに制限
    maxmemory-policy allkeys-lru # メモリが上限に達した際の削除ポリシー

    maxmemory-policy は、メモリが上限に達したときに、どのキーを削除するかを決定します。

    • noeviction: デフォルト。キーの削除を行わず、書き込みコマンドに対してエラーを返す。データ損失を避けたい場合に有効。
    • allkeys-lru: 全てのキーの中から、最も最近使われていない(Least Recently Used)キーを削除。
    • volatile-lru: EXPIRE コマンドで有効期限が設定されたキーの中から、最も最近使われていないキーを削除。
    • その他、lfu, random, ttl など。
  3. 永続化オプション (save, appendonly, appendfsync):
    第3章で説明したRDBとAOFの設定です。
    これらをredis.confで明示的に制御することで、データの安全性とパフォーマンスを調整できます。

  4. ネットワーク設定 (bind, protected-mode):

    • bind 127.0.0.1: RedisがリッスンするIPアドレスを指定します。デフォルトではすべてのインターフェースでリッスンします。Dockerコンテナでは、コンテナ内部のネットワークインターフェースにバインドされます。外部からのアクセスを制限する場合は、ファイアウォールやDockerのネットワーク設定と組み合わせて行います。
    • protected-mode yes: デフォルトで有効。外部からのアクセスを制限し、不正アクセスを防ぎます。リモートからパスワードなしで接続できないようにします。bind を設定したり、パスワードを設定したりしない限り、リモートからの接続は拒否されます。

5.2 Redisセキュリティの考慮事項

DockerコンテナでRedisを運用する際のセキュリティは非常に重要です。

  • パスワード認証 (requirepass) の設定:
    これは最も基本的なセキュリティ対策です。推測されにくい強力なパスワードを設定し、定期的に変更することを検討してください。環境変数などでアプリケーションに渡す際は、secrets管理ツールを利用するのがベストプラクティスです。
  • ネットワークアクセス制限 (Firewall, Dockerネットワーク):
    • ホストOSのファイアウォール: ホストOSのファイアウォール(例: ufw on Linux, Windows Firewall)で、Redisがリッスンしているポート (6379) へのアクセスを、信頼できるIPアドレスのみに制限します。
    • Dockerネットワーク: Docker Composeでサービス間連携をする場合、Redisポートをホストに公開 (ports マッピング) せずに、アプリケーションコンテナから内部ネットワーク経由でのみアクセスさせることを検討します。
      yaml
      # docker-compose.yml (WebアプリからのみRedisにアクセス)
      version: '3.8'
      services:
      web:
      # ...
      environment:
      REDIS_HOST: redis
      REDIS_PORT: 6379
      depends_on:
      - redis
      redis:
      image: redis:6.2.7
      # ports:
      # - "6379:6379" # ホストへのポート公開をコメントアウト/削除
      volumes:
      - redis-data:/data
      # ...
      volumes:
      redis-data:

      この設定では、web サービスは redis というサービス名でRedisにアクセスできますが、ホストOSからは直接6379ポートでRedisに接続できなくなります(Docker Composeの内部ネットワーク経由のみ)。これがより安全な構成です。
  • TLS/SSL暗号化:
    RedisはネイティブでTLS/SSLをサポートしていません(Redis 6以降で試験的にサポートされ始めましたが、まだ広く使われていません)。安全な通信が必要な場合は、StunnelのようなTLSプロキシをRedisの前に配置することを検討します。これにより、クライアントとStunnel間、StunnelとRedis間で通信を暗号化できます。これは複雑な設定になるため、必要に応じて専門的な知識が必要です。
  • 最小権限の原則:
    Redisコンテナをrootユーザーで実行しないようにします。Dockerイメージによってはデフォルトでredisユーザーで実行されるようになっていますが、カスタムイメージを作成する際は注意が必要です。

5.3 RedisクラスタとSentinel (概念のみ、具体的なデプロイは別章)

単一のRedisインスタンスは、高可用性やスケーラビリティの点で限界があります。本番環境では、以下のいずれかの方法で冗長化・分散化を検討します。

  • Redis Sentinel: Redisの監視、高可用性、自動フェイルオーバーを提供するシステムです。複数のRedisインスタンス(マスターとレプリカ)を監視し、マスターに障害が発生した場合に自動的にレプリカを新しいマスターに昇格させます。主に高可用性を実現します。
  • Redis Cluster: データを複数のRedisノードにシャーディング(分散)し、書き込み・読み込みのスケーラビリティと高可用性を同時に実現します。クラスタ内の各ノードは、どのデータがどのノードにあるかを知っています。

Dockerコンテナ上でRedis SentinelやRedis Clusterをデプロイすることは可能ですが、単一コンテナのデプロイよりもはるかに複雑になります。これは、複数のコンテナを協調動作させ、ネットワーク、データ共有、設定同期などを慎重に管理する必要があるためです。本記事の範囲を超えますが、大規模な本番環境を構築する際にはこれらの選択肢を検討する必要があります。

5.4 監視とロギング

Redisコンテナが健全に動作しているか、パフォーマンスは問題ないかを継続的に監視することは非常に重要です。

  • Docker logs:
    docker logs [container_name] または docker compose logs [service_name] で、Redisコンテナの標準出力/標準エラー出力に記録されたログを確認できます。Redisは、起動情報、永続化に関するイベント、エラーなどをログに出力します。
  • Prometheus/Grafanaなど外部ツールとの連携:
    より高度な監視のためには、Prometheus (メトリクス収集) やGrafana (ダッシュボード表示) といったツールと連携することが一般的です。Redisは INFO コマンドで様々なメトリクスを提供しており、これらをPrometheusが収集し、Grafanaでグラフ化することができます。これには、Redis Exporterのような追加のコンテナが必要になる場合があります。
  • Redisコマンド:
    INFO コマンドは、Redisの現在の状態、メモリ使用量、接続数、永続化情報など、詳細なメトリクスを提供します。
    MONITOR コマンドは、Redisサーバーで実行されているすべてのコマンドをリアルタイムで表示します(デバッグ目的で非常に役立ちますが、パフォーマンスに影響を与える可能性があります)。

適切な監視とロギングは、問題の早期発見と解決、そしてパフォーマンスの最適化に不可欠です。


第6章: Dockerfileを使ったカスタムRedisイメージの作成

Docker Hubから提供される公式のRedisイメージは多くのユースケースに対応できますが、特定のニーズに合わせてカスタマイズしたい場合があります。例えば、特定のRedisモジュールを組み込みたい、独自の設定ファイルをイメージに含めたい、あるいは特定のOS環境でビルドしたいといったケースです。

このような場合、Dockerfile を使って独自のRedisイメージをビルドします。

6.1 なぜカスタムイメージが必要なのか?

  • Redisモジュールの組み込み: RedisJSON, RediSearch, RedisGraph など、Redisの機能を拡張するモジュールをあらかじめイメージに含めておきたい場合。
  • 特定の設定の組み込み: redis.conf ファイルをイメージ内に含めておき、コンテナ起動時にその設定が自動的に適用されるようにしたい場合。これにより、コンテナ起動時のコマンドがシンプルになります。
  • 依存関係の解決: Redisが特定の外部ライブラリやツールに依存する場合、それらをイメージビルド時にインストールしておくことができます。
  • 環境の標準化: 組織内の特定のセキュリティポリシーや構成要件を満たすようにイメージを標準化したい場合。
  • イメージサイズの最適化: 不要なパッケージを削除したり、軽量なベースイメージ(例: alpine)を使用したりして、イメージサイズをさらに最適化したい場合。

6.2 Dockerfileの基本

Dockerfile は、Dockerイメージを自動的にビルドするための一連の命令を記述したテキストファイルです。各命令は新しいレイヤーを作成し、最終的なイメージを構成します。

主要な命令:

  • FROM: ベースとなるイメージを指定します。すべてのDockerfileはこの命令から始まります。
    • 例: FROM redis:6.2.7-alpine
  • LABEL: イメージのメタデータ(作者、バージョンなど)を定義します。
  • RUN: イメージビルド時に実行するコマンドを指定します。通常、パッケージのインストールやファイルの準備などに使われます。
    • 例: RUN apt-get update && apt-get install -y build-essential
  • COPY: ホストOSのファイルやディレクトリをイメージ内にコピーします。
    • 例: COPY ./my-redis.conf /usr/local/etc/redis/redis.conf
  • ADD: COPY と似ていますが、URLからのダウンロードや圧縮ファイルの自動展開もサポートします。
  • EXPOSE: コンテナがリッスンするポートを宣言します。これはドキュメント的な意味合いが強く、ポートマッピングは docker run -p または Docker Composeで行います。
    • 例: EXPOSE 6379
  • ENV: 環境変数を設定します。
  • WORKDIR: 以降の RUN, CMD, ENTRYPOINT コマンドが実行される作業ディレクトリを設定します。
  • USER: 以降のコマンドを実行するユーザーを設定します。セキュリティのためにルート以外のユーザーを指定することが推奨されます。
  • VOLUME: 永続化が必要なデータを保存するボリュームとしてマークするディレクトリを宣言します。
  • CMD: コンテナ起動時に実行されるデフォルトのコマンドを指定します。Dockerfileごとに1つだけ設定でき、docker run のコマンドライン引数で上書き可能です。
  • ENTRYPOINT: コンテナ起動時に常に実行されるコマンドを指定します。CMD と組み合わせて、実行可能ファイルと引数を分離するイディオムがよく使われます。

6.3 カスタムRedisイメージの例

ここでは、独自の redis.conf を組み込み、RedisJSONモジュールを追加するカスタムイメージの例を示します。

  1. ディレクトリ構造:
    my-custom-redis/
    ├── Dockerfile
    ├── redis.conf # カスタム設定ファイル
    └── redisjson.so # RedisJSONモジュールファイル (事前にダウンロードまたはビルドしておく)

  2. redis.conf の内容 (例):
    “`conf
    # my-custom-redis/redis.conf
    requirepass my_custom_password
    appendonly yes
    save 900 1
    save 300 10
    save 60 10000
    maxmemory 256mb
    maxmemory-policy allkeys-lru

    Redisモジュールをロード

    loadmodule /usr/local/lib/redisjson.so
    “`

  3. Dockerfile の内容:
    “`dockerfile
    # my-custom-redis/Dockerfile

    Redisの公式イメージをベースにする

    FROM redis:6.2.7-alpine

    イメージのメンテナ情報 (任意)

    LABEL maintainer=”Your Name your.email@example.com

    必要なディレクトリを作成

    RUN mkdir -p /usr/local/etc/redis/ \
    /usr/local/lib/

    カスタム設定ファイルをコンテナ内にコピー

    ホストの ./redis.conf をコンテナの /usr/local/etc/redis/redis.conf へ

    COPY redis.conf /usr/local/etc/redis/redis.conf

    RedisJSONモジュールをコンテナ内にコピー

    ホストの ./redisjson.so をコンテナの /usr/local/lib/redisjson.so へ

    COPY redisjson.so /usr/local/lib/redisjson.so

    データ永続化ディレクトリ

    VOLUME /data

    Redisのデフォルトポート

    EXPOSE 6379

    コンテナ起動時にマウントした設定ファイルでRedisサーバーを起動

    CMD は docker run のコマンドライン引数で上書きできる

    CMD [“redis-server”, “/usr/local/etc/redis/redis.conf”]
    ``
    *注:
    redisjson.so` ファイルは、RedisJSONのGitHubリポジトリからダウンロードするか、自分でビルドする必要があります。ここではファイルが事前に用意されていることを前提としています。*

6.4 イメージのビルドと実行

  1. イメージのビルド:
    my-custom-redis ディレクトリに移動し、以下のコマンドを実行します。
    bash
    cd my-custom-redis
    docker build -t my-custom-redis:1.0.0 .

    • docker build: Dockerイメージをビルドするコマンド。
    • -t my-custom-redis:1.0.0: ビルドするイメージに my-custom-redis という名前と 1.0.0 というタグを付ける。
    • .: Dockerfileが存在するカレントディレクトリをビルドコンテキストとして指定。

    ビルドが成功すると、docker imagesmy-custom-redis イメージがリストされていることを確認できます。

  2. カスタムイメージの実行:
    ビルドしたカスタムイメージを使ってコンテナを起動します。
    bash
    docker run -d --name my-custom-redis-instance -p 6379:6379 -v redis_data_volume:/data my-custom-redis:1.0.0

    このコンテナは、Dockerfile内で組み込まれた redis.conf の設定(パスワードやメモリ制限、RedisJSONモジュールロードなど)を適用して起動します。

  3. 動作確認:
    redis-cli で接続し、パスワード認証を試したり、RedisJSONのコマンドを試したりして、カスタム設定が適用されているか確認できます。
    bash
    docker exec -it my-custom-redis-instance redis-cli -a my_custom_password
    # パスワード認証後
    PING
    JSON.SET mydoc $ '{"name":"Alice", "age":30}'
    JSON.GET mydoc

Dockerfileを使ったカスタムイメージの作成は、Redisの機能をより深くカスタマイズし、特定の要件を満たす環境を構築するために不可欠なスキルです。


第7章: 実践的なアプリケーション連携例

これまでの知識を活かし、実際のWebアプリケーションからDockerized Redisに接続する具体的な例を見ていきましょう。ここではPython FlaskとNode.js Expressの2つの例を扱います。どちらの例もDocker Composeを使用し、複数のサービスが連携する環境を構築します。

7.1 Python Flask + Redis (キャッシュ)

Python FlaskアプリケーションでRedisをシンプルにキャッシュとして利用する例です。

ディレクトリ構造:
flask-redis-example/
├── docker-compose.yml
└── app/
├── Dockerfile
├── requirements.txt
└── app.py

  1. app/requirements.txt:
    アプリケーションに必要なPythonライブラリを定義します。
    Flask
    redis

  2. app/app.py:
    Flaskアプリケーションのコードです。Redisに接続し、簡単なキャッシュ操作を行います。
    “`python
    # app/app.py
    import os
    import time
    from flask import Flask, jsonify
    import redis

    app = Flask(name)

    環境変数からRedisの接続情報を取得

    REDIS_HOST = os.getenv(‘REDIS_HOST’, ‘localhost’)
    REDIS_PORT = int(os.getenv(‘REDIS_PORT’, 6379))
    REDIS_PASSWORD = os.getenv(‘REDIS_PASSWORD’, None) # パスワードがない場合はNone

    Redisクライアントの初期化

    try:
    if REDIS_PASSWORD:
    redis_client = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, decode_responses=True)
    else:
    redis_client = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, decode_responses=True)
    redis_client.ping() # Redisへの接続をテスト
    print(f”Connected to Redis at {REDIS_HOST}:{REDIS_PORT}”)
    except redis.exceptions.ConnectionError as e:
    print(f”Could not connect to Redis: {e}”)
    redis_client = None # 接続失敗時はクライアントをNoneに設定

    @app.route(‘/’)
    def index():
    return jsonify(message=”Welcome to Flask Redis Example!”)

    @app.route(‘/cache/‘)
    def get_cached_data(key):
    if not redis_client:
    return jsonify(error=”Redis not connected.”), 500

    cached_value = redis_client.get(key)
    if cached_value:
        print(f"Cache hit for key: {key}")
        return jsonify(key=key, value=cached_value, source="cache")
    else:
        print(f"Cache miss for key: {key}, fetching from 'database'...")
        # ダミーのデータ取得(データベースからの取得をシミュレート)
        time.sleep(1) # ネットワーク遅延をシミュレート
        data_from_db = f"data_from_db_for_{key}_{time.time()}"
        redis_client.setex(key, 60, data_from_db) # 60秒間キャッシュに保存
        return jsonify(key=key, value=data_from_db, source="database")
    

    @app.route(‘/clear_cache/‘)
    def clear_cache(key):
    if not redis_client:
    return jsonify(error=”Redis not connected.”), 500

    deleted_count = redis_client.delete(key)
    return jsonify(message=f"Cache for key '{key}' cleared.", deleted_count=deleted_count)
    

    if name == ‘main‘:
    app.run(host=’0.0.0.0’, port=5000)
    “`

  3. app/Dockerfile:
    FlaskアプリケーションのDockerイメージをビルドするためのDockerfileです。
    “`dockerfile
    # app/Dockerfile
    FROM python:3.9-slim-buster

    WORKDIR /app

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

    COPY . .

    EXPOSE 5000

    CMD [“python”, “app.py”]
    “`

  4. docker-compose.yml:
    FlaskアプリとRedisサービスを定義するDocker Composeファイルです。
    “`yaml
    # docker-compose.yml
    version: ‘3.8’

    services:
    web:
    build:
    context: ./app # appディレクトリにあるDockerfileを使用
    ports:
    – “5000:5000” # ホストの5000ポートをwebコンテナの5000ポートにマッピング
    environment:
    REDIS_HOST: redis # Redisサービスのホスト名
    REDIS_PORT: 6379
    # REDIS_PASSWORD: your_redis_password # Redisにパスワードを設定した場合に有効化
    depends_on:
    – redis # webサービスはredisサービスに依存
    restart: on-failure

    redis:
    image: redis:6.2.7-alpine # 軽量版Redisイメージ
    container_name: flask_redis_server
    # ports:
    # – “6379:6379” # ホストからのRedis直接アクセスを不要とするためコメントアウト
    volumes:
    – redis-data:/data # Redisデータの永続化
    # – ./redis.conf:/usr/local/etc/redis/redis.conf # カスタムRedis設定を使用する場合
    # command: redis-server /usr/local/etc/redis/redis.conf # カスタム設定を使用する場合
    # environment:
    # REDIS_PASSWORD: your_redis_password # Redisパスワードを環境変数で設定する場合 (非推奨, secrets管理を推奨)
    restart: always

    volumes:
    redis-data: # 名前付きボリュームの定義
    ``
    *
    redisサービスからportsマッピングを削除しました。これにより、ホストOSからはRedisに直接アクセスできなくなり、webサービスからのみ内部ネットワーク経由でアクセスする、よりセキュアな構成になります。
    *
    REDIS_PASSWORD` はコメントアウトしています。本番環境ではDocker SecretsやKubernetes Secretsなどの安全な方法で管理すべきです。

  5. 実行:
    flask-redis-example ディレクトリに移動し、Docker Composeを起動します。
    bash
    cd flask-redis-example
    docker compose up -d --build

  6. 動作確認:
    ブラウザまたは curl でアクセスします。

    • http://localhost:5000/cache/mydata: 初回アクセス時は「database」からデータ取得し、Redisにキャッシュされます。
    • http://localhost:5000/cache/mydata: 2回目以降のアクセスは「cache」からデータ取得され、高速に応答します。
    • http://localhost:5000/clear_cache/mydata: キャッシュをクリアします。

    Redisコンテナのログも確認できます。
    bash
    docker compose logs -f redis
    docker compose logs -f web

7.2 Node.js Express + Redis (セッションストア)

Node.js ExpressアプリケーションでRedisをセッションストアとして利用する例です。

ディレクトリ構造:
express-redis-example/
├── docker-compose.yml
└── app/
├── Dockerfile
├── package.json
└── server.js

  1. app/package.json:
    アプリケーションに必要なNode.jsパッケージを定義します。
    json
    {
    "name": "express-redis-app",
    "version": "1.0.0",
    "description": "Express app with Redis session store",
    "main": "server.js",
    "scripts": {
    "start": "node server.js"
    },
    "dependencies": {
    "express": "^4.18.2",
    "express-session": "^1.17.3",
    "connect-redis": "^7.1.0",
    "redis": "^4.6.8"
    }
    }

  2. app/server.js:
    Expressアプリケーションのコードです。express-sessionconnect-redis を使ってセッションをRedisに保存します。
    “`javascript
    // app/server.js
    const express = require(‘express’);
    const session = require(‘express-session’);
    const redis = require(‘redis’);
    const RedisStore = require(‘connect-redis’).default;

    const app = express();
    const PORT = process.env.PORT || 3000;
    const REDIS_HOST = process.env.REDIS_HOST || ‘localhost’;
    const REDIS_PORT = parseInt(process.env.REDIS_PORT || ‘6379’);
    const REDIS_PASSWORD = process.env.REDIS_PASSWORD || undefined; // undefinedだとパスワードなし

    // Redisクライアントの初期化
    const redisClient = redis.createClient({
    socket: {
    host: REDIS_HOST,
    port: REDIS_PORT
    },
    password: REDIS_PASSWORD
    });

    redisClient.on(‘connect’, () => console.log(‘Connected to Redis!’));
    redisClient.on(‘error’, (err) => console.log(‘Redis Client Error’, err));

    // Redisクライアントを接続
    (async () => {
    await redisClient.connect();
    })();

    // RedisStoreの設定
    const redisStore = new RedisStore({
    client: redisClient,
    prefix: “myapp:”, // Redisキーのプレフィックス
    ttl: 3600 // セッションの有効期限 (秒)
    });

    // セッションミドルウェアの設定
    app.use(session({
    store: redisStore,
    secret: ‘your_super_secret_key_here’, // セッションIDを暗号化するための秘密鍵
    resave: false, // セッションストアに未変更のセッションを再保存しない
    saveUninitialized: false, // 初期化されていない(変更されていない)セッションを保存しない
    cookie: {
    secure: process.env.NODE_ENV === ‘production’, // HTTPSの場合にのみクッキーを送信
    httpOnly: true, // JavaScriptからのアクセスを禁止
    maxAge: 1000 * 60 * 60 * 24 // クッキーの有効期限 (ミリ秒, 24時間)
    }
    }));

    // ルートハンドラ
    app.get(‘/’, (req, res) => {
    // セッションにアクセス数を保存
    if (req.session.views) {
    req.session.views++;
    } else {
    req.session.views = 1;
    }
    res.send(Hello World! You have visited this page ${req.session.views} time(s). Session ID: ${req.session.id});
    });

    app.get(‘/reset’, (req, res) => {
    req.session.destroy((err) => {
    if (err) {
    return res.status(500).send(‘Could not destroy session’);
    }
    res.send(‘Session reset!’);
    });
    });

    app.listen(PORT, () => {
    console.log(Server listening on port ${PORT});
    });
    ``
    * **重要**:
    secretキーは推測されにくい強力な文字列に置き換え、本番環境では環境変数やSecretsマネージャーで管理してください。
    *
    redisClient.connect()` は非同期なので、即時実行関数でラップしています。

  3. app/Dockerfile:
    ExpressアプリケーションのDockerイメージをビルドするためのDockerfileです。
    “`dockerfile
    # app/Dockerfile
    FROM node:18-alpine

    WORKDIR /app

    COPY package*.json ./
    RUN npm install –production

    COPY . .

    EXPOSE 3000

    CMD [“npm”, “start”]
    “`

  4. docker-compose.yml:
    ExpressアプリとRedisサービスを定義するDocker Composeファイルです。
    “`yaml
    # docker-compose.yml
    version: ‘3.8’

    services:
    web:
    build:
    context: ./app
    ports:
    – “3000:3000”
    environment:
    PORT: 3000
    REDIS_HOST: redis
    REDIS_PORT: 6379
    # REDIS_PASSWORD: your_redis_password # Redisにパスワードを設定した場合に有効化
    NODE_ENV: development # development or production (cookie secure設定に影響)
    depends_on:
    – redis
    restart: on-failure

    redis:
    image: redis:6.2.7-alpine
    container_name: express_redis_server
    # ports:
    # – “6379:6379” # ホストからのRedis直接アクセスを不要とするためコメントアウト
    volumes:
    – redis-data:/data
    # – ./redis.conf:/usr/local/etc/redis/redis.conf
    # command: redis-server /usr/local/etc/redis/redis.conf
    # environment:
    # REDIS_PASSWORD: your_redis_password
    restart: always

    volumes:
    redis-data:
    “`

  5. 実行:
    express-redis-example ディレクトリに移動し、Docker Composeを起動します。
    bash
    cd express-redis-example
    docker compose up -d --build

  6. 動作確認:
    ブラウザで http://localhost:3000/ にアクセスし、ページをリロードすると訪問回数が増加することを確認します。これはRedisに保存されたセッションデータが利用されているためです。
    http://localhost:3000/reset でセッションをリセットできます。

    Redisコンテナ内部から redis-cli でセッションキーを確認することもできます。
    “`bash
    docker compose exec redis redis-cli

    redis-cliプロンプトで

    KEYS myapp:*

    出力例: 1) “myapp:YOUR_SESSION_ID”

    HGETALL myapp:YOUR_SESSION_ID

    セッションデータがハッシュとして保存されていることが確認できます

    “`

これらの実践例を通して、Docker Composeがいかに複雑なマルチサービスアプリケーションのデプロイと管理を簡素化するか、そしてDockerized Redisがアプリケーションのバックエンドとしていかに強力であるかを理解できたはずです。


第8章: トラブルシューティングとよくある質問

DockerとRedisの連携は非常に強力ですが、時に問題に直面することもあります。ここでは、よくある問題とその解決策、および関連するヒントをまとめます。

8.1 ポート衝突

問題: docker rundocker compose up 時に port is already allocated あるいは bind: address already in use のようなエラーが表示される。
原因: ホストOS上で、Redisが使用しようとしているポート(デフォルト6379)が、すでに別のプロセス(別のRedisインスタンス、別のDockerコンテナ、または他のアプリケーション)によって使用されている。
解決策:
* netstat -tuln | grep 6379 (Linux/macOS) または netstat -ano | findstr :6379 (Windows) で、どのプロセスが6379ポートを使用しているかを確認する。
* 使用しているプロセスを停止するか、Dockerのポートマッピングを変更して別のホストポートを使用する。
例: docker run -d -p 6380:6379 redis (ホストの6380ポートを使用)
Docker Composeの場合:
yaml
ports:
- "6380:6379"

8.2 コンテナが起動しない (docker logs)

問題: docker ps でコンテナの STATUSExited になっている、または全く表示されない。
原因: コンテナ内のアプリケーション(この場合はRedis)が、起動直後にエラーで終了している。
解決策:
* ログの確認: まず docker logs [container_name] または docker compose logs [service_name] でログを確認する。エラーメッセージから原因を特定できることが多い。
例: docker logs my-redis または docker compose logs redis
* 設定ファイルの問題: redis.conf をマウントしている場合、設定ファイルの構文エラーや、Redisがアクセスできないパス(権限不足など)が原因で起動に失敗することがあります。
* メモリ不足: ホストOSのメモリが不足しているか、Redisの maxmemory 設定が低すぎる場合、Redisが起動できないことがあります。
* ボリュームの権限: バインドマウントを使用している場合、ホスト側のディレクトリの権限が適切でないと、Redisがデータファイルを作成・書き込みできずに起動に失敗することがあります。ホスト側のディレクトリの所有者と権限を確認し、Redisユーザー(通常は redis)が書き込めるように設定する。

8.3 データ永続化の問題

問題: コンテナを停止・削除してから再起動すると、以前保存したデータが消えている。
原因: データの永続化設定が正しく行われていない。
解決策:
* Docker Volumeの確認:
* 名前付きボリュームを使用しているか? (docker volume ls, docker volume inspect)
* ボリュームがコンテナのRedisデータディレクトリ (/data) に正しくマウントされているか? (-v my-redis-data:/data)
* docker compose down -v でボリュームごと削除してしまっていないか?
* Redis永続化設定の確認:
* redis.conf でRDB (save) またはAOF (appendonly yes) が正しく有効になっているか?
* redis-server 起動時に redis.conf が正しくロードされているか?
* Redisコンテナ内部の /data ディレクトリに dump.rdbappendonly.aof が存在するかを確認する (docker exec my-redis ls /data)。

8.4 ネットワーク接続の問題 (Dockerネットワーク, ping hostname)

問題: アプリケーションコンテナからRedisコンテナに接続できない。エラーメッセージに Connection refused, Host not found などが含まれる。
原因: ネットワーク設定の誤り、ポートの誤り、ファイアウォール、Redisの bind 設定など。
解決策:
* Docker Composeの場合:
* アプリケーションがRedisサービス名 (redis) をホストとして正しく参照しているか確認する。
* docker compose networks ls でComposeによって作成されたネットワークを確認し、両方のコンテナが同じネットワークに接続されているか確認する。
* アプリケーションコンテナからRedisコンテナへの疎通を確認する。
bash
docker compose exec web ping redis
docker compose exec web redis-cli -h redis -p 6379 PING # パスワードがあれば -a で指定

* ポート公開の有無:
* docker-compose.yml でRedisの ports マッピングを削除した場合、ホストOSからはRedisに直接アクセスできません。アプリケーションコンテナから内部ネットワーク経由で接続する必要があります。
* アプリケーションコンテナのDockerfileで、Redis接続に必要なポートが開かれていることを確認します(Redisへの接続自体にはアプリ側でEXPOSEは不要)。
* Redisの bind 設定:
redis.confbind 127.0.0.1 のように特定のIPアドレスにバインドしている場合、Dockerコンテナの内部ネットワークからのアクセスが拒否される可能性があります。コンテナ内ではデフォルトで 0.0.0.0 (すべてのインターフェース) でリッスンするようにするか、またはバインドIPをコンテナのプライベートネットワークIPに変更する必要がありますが、通常はデフォルトの redis-server コマンドで問題ありません。protected-mode no に変更する必要がある場合もありますが、これはセキュリティリスクを伴います。パスワード設定とファイアウォールが推奨されます。

8.5 Redisメモリ不足 (maxmemory 設定)

問題: Redisにデータを書き込めない、あるいはデータが予期せず削除される。ログに OOM command not allowed when used memory > maxmemory のようなエラーが表示される。
原因: Redisが設定された maxmemory 上限に達している。
解決策:
* redis.confmaxmemory 設定を増やす。
* maxmemory-policy を適切に設定し、メモリ上限に達した際の挙動(LRUなどで古いデータを削除する)を制御する。
* ホストOSに十分なメモリがあるか確認し、Dockerコンテナに割り当てられたメモリ上限も確認する(docker run --memory オプション)。
* Redisに保存されているデータを確認し、不要なデータを削除したり、データ構造を見直したりしてメモリ使用量を最適化する。

8.6 redis-cli で接続できない

問題: redis-cli で接続しようとすると Could not connect to Redis at 127.0.0.1:6379: Connection refused などと表示される。
原因:
* Redisコンテナが起動していないか、ポートマッピングが正しくない。
* Redisにパスワードが設定されているが、redis-cli で認証していない。
* Redisが特定のIPアドレスにバインドされている(bind 設定)。
* ファイアウォールが接続をブロックしている。
解決策:
* docker ps でRedisコンテナが Up 状態であることを確認する。
* docker inspect [container_name] でポートマッピングを確認する。
* パスワードが設定されている場合、redis-cli -a your_password で接続する。
* redis.confbind 設定を確認し、デフォルトに戻すか、protected-mode no を試す(ただしセキュリティリスクあり)。
* ホストOSのファイアウォール設定を確認する。

8.7 権限の問題 (bind mounts)

問題: バインドマウントしたホストのディレクトリに、Redisがファイルを書き込めない。ログに Permission denied が表示される。
原因: ホストのディレクトリのファイルシステム権限が、コンテナ内でRedisプロセスが実行されるユーザー(通常は redis ユーザー、UID/GIDが999など)に書き込みを許可していない。
解決策:
* ホスト側のディレクトリの権限を、Redisコンテナのユーザーが書き込めるように変更する。
例 (Linux): sudo chown -R 999:999 /path/to/your/redis_data (RedisのUID/GIDが999の場合)
または、より広範な権限を与える: sudo chmod -R 777 /path/to/your/redis_data (セキュリティリスクあり)
* Dockerコンテナを起動する際に、RedisユーザーのUID/GIDをホスト側のディレクトリの所有者と合わせるように指定する(複雑になる場合がある)。
* 可能であれば、バインドマウントの代わりにDocker Volumeを使用することを検討する。

これらのトラブルシューティングのヒントが、あなたが直面する可能性のある問題を解決する手助けとなることを願っています。重要なのは、常にまずログを確認し、エラーメッセージを注意深く読むことです。


まとめと次のステップ

本記事では、「DockerでRedisを使いこなす!」をテーマに、Redisコンテナのデプロイと管理に関する広範な知識を網羅的に解説しました。

学習したことの再確認:

  • DockerとRedisの基本: コンテナ技術とインメモリデータストアRedisのそれぞれの特性と、両者を組み合わせるメリットを理解しました。
  • 基本的なコンテナ操作: docker pull, docker run, docker stop, docker rm といった基本的なコマンドを使って、Redisコンテナを起動・管理する方法を学びました。
  • データの永続化: Docker Volume (名前付きボリューム、バインドマウント) を使ってRedisデータを永続化する方法、そしてRedis自身の永続化機能 (RDB, AOF) の重要性を理解しました。
  • Docker Composeの活用: docker-compose.yml ファイルを使って複数のサービス(アプリケーションとRedis)を定義し、一元的に管理する方法を習得しました。
  • 高度な設定と運用: redis.conf を使ったカスタム設定の適用(認証、メモリ制限など)や、セキュリティに関する考慮事項について理解を深めました。
  • カスタムイメージの作成: Dockerfile を使って、特定の要件(モジュール組み込み、カスタム設定)に応じたRedisイメージをビルドする方法を学びました。
  • 実践的なアプリケーション連携: Python FlaskとNode.js Expressの具体例を通して、実際のアプリケーションからRedisコンテナに接続し、キャッシュやセッションストアとして利用する実践的なスキルを習得しました。
  • トラブルシューティング: よくある問題(ポート衝突、起動失敗、永続化問題など)とその解決策を学び、問題解決のための実践的なアプローチを身につけました。

あなたは今、Docker環境でRedisを効率的かつ堅牢にデプロイし、アプリケーションと連携させるための強力な基盤を築きました。

次のステップ:

本記事はRedisとDockerの基本的なデプロイに焦点を当てましたが、さらに深く学ぶべき分野は多岐にわたります。

  • Redis Cluster / Sentinelの深掘り: 大規模な本番環境では、単一のRedisインスタンスでは不十分です。Redis Sentinelによる高可用性、またはRedis Clusterによるスケーラビリティと可用性を実現する方法について学習してください。これらはDocker SwarmやKubernetesといったコンテナオーケストレーションツールと組み合わせてデプロイされることが一般的です。
  • Docker Swarm / Kubernetes: 複数のホストにわたってコンテナをデプロイ・管理するためのオーケストレーションツールです。本番環境での自動スケーリング、自己修復、負荷分散などを実現するために必須の知識となります。
  • Redisモジュール: RedisJSON, RediSearch, RedisGraph, RedisTimeSeriesなど、Redisの機能をさらに拡張するモジュールを探索し、あなたのアプリケーションのニーズに合わせて活用することを検討してください。
  • 監視とアラート: Prometheus, Grafana, ELK Stack (Elasticsearch, Logstash, Kibana) などのツールを使って、Redisのパフォーマンスを継続的に監視し、問題が発生した際に自動的に通知するシステムを構築してください。
  • セキュリティの強化: Docker Secretsや環境変数管理ツール、VPNなどを用いて、よりセキュアなRedis接続と認証情報の管理を実践してください。
  • CI/CDパイプラインへの組み込み: Dockerイメージの自動ビルド、テスト、デプロイをCI/CD (継続的インテグレーション/継続的デリバリー) パイプラインに組み込み、開発プロセスを自動化・効率化してください。

DockerとRedisは、現代のクラウドネイティブアプリケーション開発において不可欠なツールです。本記事で得た知識を基に、さらなる学習と実践を重ね、あなたの開発スキルを次のレベルへと引き上げていきましょう。

Happy Hacking!

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール