目次

DockerでRedisを実行する方法:パスワード設定、データの保存、接続

Redisはメモリ上に存在するキーバリューデータベースで、キャッシュ、セッションの保存、カウンター、キューによく使われます。Dockerなら数秒で実行できます。

基本的な実行

$ docker run -d --name redis -p 127.0.0.1:6379:6379 redis:8-alpine
Unable to find image 'redis:8-alpine' locally
8-alpine: Pulling from library/redis
Digest: sha256:3811787313eba226a2ef38658c6ccb91cd5e110edc89c37767de373120a0e5a0
Status: Downloaded newer image for redis:8-alpine
6fbb2effcf1bc874eda1064575153984b6223fd6de15ac2452eae0bbf71a74f1

$ docker exec redis redis-cli PING
PONG

$ docker exec redis redis-cli SET greeting hello
OK

$ docker exec redis redis-cli GET greeting
hello

$ docker exec redis redis-cli SET session:abc "user42" EX 60
OK

$ docker exec redis redis-cli TTL session:abc
60

$ docker exec redis redis-server --version
Redis server v=8.10.2 sha=00000000:1 malloc=jemalloc-5.3.0 bits=64 build=6583f6419e33bdeb

$ docker rm -f redis
redis
  • -p 127.0.0.1:6379:6379:ローカルホストからのみアクセスできます。
  • コンテナ内には redis-cli があるため、そのままコマンドを実行できます。
  • SET ... EX 60 は60秒後に自動で期限切れにします。TTL で残り秒数を確認できます。セッションやキャッシュによく使われます。

対話形式で使うには docker exec -it redis redis-cli を実行します。127.0.0.1:6379> のプロンプトが表示されたら、コマンドを入力してEnterを押します。exit と入力すると終了します。

パスワードの設定

Redisにはデフォルトでパスワードがありません。ポートを外部に公開すると、誰でも読み書きでき、ホストへの侵入に利用されるおそれもあります。そのため、次のようにします。

  1. 外部から接続する必要がない場合は、-p を使わないでください。必要な場合は 127.0.0.1 にのみバインドします。
  2. パスワードを設定します。
$ docker run -d --name redis redis:8-alpine redis-server --requirepass "change-me"
8dbd1f84d2541f264d93555142cb65f6497e9635111ff4f9544258516e06a0e2

$ docker exec redis redis-cli GET greeting
NOAUTH Authentication required.


$ docker exec redis redis-cli -a "change-me" PING
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
PONG

$ docker exec redis redis-cli -a "change-me" --no-auth-warning PING
PONG

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli PING
PONG

$ docker rm -f redis
redis
  • パスワードがない場合は NOAUTH Authentication required. が表示されます。
  • -a でパスワードを渡すと実行できますが、パスワードがプロセス一覧に表示されるため警告が出ます。--no-auth-warning は警告を隠すだけです。
  • 環境変数 REDISCLI_AUTH でパスワードを渡す方法がおすすめです。redis-cli が自動的に使用するため、警告も出ません。

アプリケーションの接続文字列(ユーザー名は空欄):

redis://:change-me@redis:6379/0

末尾の /0 はデータベース番号(0~15)です。

データの永続化

Redisのデータはメモリ上にあります。ディスクに保存する方法は、RDBスナップショットとAOFログの2つです。公式イメージではデフォルトでRDBのみが有効で、ファイルはコンテナの /data に保存されるため、Volumeをマウントする必要があります。

検証:RDBはリアルタイムで保存されない

$ docker run -d --name redis -v redis_data:/data redis:8-alpine
882983e53f8e000fa65faaf8d71bbcbeb57192401b1854621172ce2df95c29a6

$ docker exec redis redis-cli SET visits 100
OK

$ docker rm -f redis
redis

$ docker run -d --name redis -v redis_data:/data redis:8-alpine
5ad1473152a6eafdfdb33df64f68355c73e454f10e6bc135688f7c51686bb059

$ docker exec redis redis-cli GET visits


$ docker exec redis redis-cli CONFIG GET save
save
3600 1 300 100 60 10000

Volumeをマウントしたのに、docker rm -f で削除して再作成すると visits が空になっています。CONFIG GET save に表示されるデフォルトの保存条件 3600 1 300 100 60 10000 の意味は次のとおりです。

条件意味
3600 11時間以内に少なくとも1つのkeyが変更されたら保存
300 1005分以内に少なくとも100個のkeyが変更されたら保存
60 100001分以内に少なくとも10000個のkeyが変更されたら保存

keyを1つ変更しただけなら、保存まで1時間待つ必要があります。docker rm -f は SIGKILL でRedisを強制終了するため、保存が間に合いません。

docker stop で正常に停止します。

$ docker exec redis redis-cli SET visits 100
OK

$ docker stop redis
redis

$ docker logs redis 2>&1 | tail -n 5
1:M 13 Oct 2026 00:57:09.620 * User requested shutdown...
1:M 13 Oct 2026 00:57:09.620 * Saving the final RDB snapshot before exiting.
1:M 13 Oct 2026 00:57:09.621 * BGSAVE done, 1 keys saved, 0 keys skipped, 104 bytes written.
1:M 13 Oct 2026 00:57:09.623 * DB saved on disk
1:M 13 Oct 2026 00:57:09.623 # Redis is now ready to exit, bye bye...

$ docker start redis
redis

$ docker exec redis redis-cli GET visits
100

$ docker exec redis ls -l /data
total 4
-rw-------    1 redis    redis          104 Oct 13 00:57 dump.rdb

$ docker rm -f redis
redis

$ docker volume rm redis_data
redis_data

docker stop は SIGTERM を送信します。Redisは終了前に Saving the final RDB snapshot before exiting を実行するため、データが保存されます。つまり、次のとおりです。

  • 正常な停止(docker stop、docker compose down、ホストの正常なシャットダウン)ではデータは失われません。
  • クラッシュ、停電、docker rm -f、メモリ不足によるシステムの強制終了では、最後のスナップショット以降のデータが失われます。

AOF:書き込みのたびに記録

より確実にデータを保存するには、AOF(Append Only File)を有効にします。書き込みコマンドがすべて記録されます。

$ docker run -d --name redis -v redis_data:/data redis:8-alpine redis-server --appendonly yes
aaac5c67a222018db886e0f3a3306841ec4bba7e8ae0b4b4eca71dc5cede91c9

$ docker exec redis redis-cli SET visits 41
OK

$ docker exec redis redis-cli INCR visits
42

$ docker rm -f redis
redis

$ docker run -d --name redis -v redis_data:/data redis:8-alpine redis-server --appendonly yes
1c880b5c2e8ef54b65baaa1fd99b1b9c976eb42f2d9c52f1eb9188eaeda955e4

$ docker exec redis redis-cli GET visits
42

$ docker exec redis ls /data/appendonlydir
appendonly.aof.1.base.rdb
appendonly.aof.1.incr.aof
appendonly.aof.manifest

$ docker rm -f redis
redis

$ docker volume rm redis_data
redis_data

docker rm -f で強制削除しても、再作成後の visits は 42 のままです。/data/appendonlydir には AOF ファイルがあります。base.rdb はベースとなるスナップショット、incr.aof はその後の各書き込み、manifest はファイル一覧を記録します。

方式メリットデメリット
RDB(デフォルト)ファイルが小さく、再起動時の読み込みが速い異常終了すると、直近のスナップショット以降のデータが失われる可能性がある
AOFデフォルトでは毎秒 1 回ディスクに書き込み、失われるデータは最大約 1 秒分ファイルが大きく、書き込み量が多いとディスクへの負荷が高い
保存しない最速再起動後にデータがすべて消えるため、純粋なキャッシュにのみ適している

純粋なキャッシュとして使う場合は、保存を完全に無効にできます:redis-server --save "" --appendonly no。

設定ファイルとメモリ上限を使う

パラメーターが多い場合は、設定ファイルを使います。redis-demo/redis.conf:

requirepass change-me
appendonly yes
maxmemory 64mb
maxmemory-policy allkeys-lru

キャッシュとして使う場合は、必ず maxmemory を設定してください。設定しないと、ホストのメモリが不足するまで Redis がメモリを使い続けます。上限に達すると、maxmemory-policy に従って処理されます。

ポリシー動作
noevictionデフォルト値です。新しい書き込みを拒否し、エラーを返します
allkeys-lruすべての key から最も長く使われていないものを削除します。キャッシュで最もよく使われます
volatile-lru有効期限が設定されている key のみ削除します
allkeys-lfu使用頻度が最も低いものを削除します

実測:上限を超えるデータを書き込む

Redis に組み込まれている redis-benchmark を使い、1 件 500 bytes のデータを 30 万件(約 150 MB)書き込みます。64 MB の上限を大幅に超える量です。

$ docker run -d --name redis -v "$(pwd)/redis.conf:/usr/local/etc/redis/redis.conf:ro" -v redis_data:/data redis:8-alpine redis-server /usr/local/etc/redis/redis.conf
af187c21e0d6ecb0e9a0299200a6d866dc605d92c715e49df8a7abd850107040

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli CONFIG GET maxmemory*
maxmemory
67108864
maxmemory-clients
0
maxmemory-eviction-tenacity
10
maxmemory-samples
5
maxmemory-policy
allkeys-lru

$ docker exec redis redis-benchmark -a change-me -t set -n 300000 -r 300000 -d 500 -q
SET: 31043.05 requests per second, p50=0.903 msec

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli INFO memory | grep -E "^(used_memory_human|maxmemory_human|maxmemory_policy)"
used_memory_human:63.89M
maxmemory_human:64.00M
maxmemory_policy:allkeys-lru

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli INFO stats | grep evicted_keys
evicted_keys:95511

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli DBSIZE
115038

Windows での書き方(タブをクリックして切り替えます):

docker run -d --name redis -v "$(pwd)/redis.conf:/usr/local/etc/redis/redis.conf:ro" -v redis_data:/data redis:8-alpine redis-server /usr/local/etc/redis/redis.conf
docker run -d --name redis -v "${PWD}/redis.conf:/usr/local/etc/redis/redis.conf:ro" -v redis_data:/data redis:8-alpine redis-server /usr/local/etc/redis/redis.conf
docker run -d --name redis -v "%cd%/redis.conf:/usr/local/etc/redis/redis.conf:ro" -v redis_data:/data redis:8-alpine redis-server /usr/local/etc/redis/redis.conf
  • CONFIG GET maxmemory* で設定ファイルが反映されたことを確認できます。67108864 bytes は 64 MB で、ポリシーは allkeys-lru です。
  • 書き込み後のメモリ使用量は 63.89M で、上限を超えていません。
  • evicted_keys:95511:9 万件を超える key が自動削除され、最終的に約 11.5 万件の key が残りました。

同じ状況で noeviction に変更してみます。

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli CONFIG SET maxmemory-policy noeviction
OK

$ docker exec -e REDISCLI_AUTH=change-me redis sh -c 'head -c 2000000 /dev/zero | tr "\\0" x | redis-cli -x SET big-value'
OOM command not allowed when used memory > 'maxmemory'.


$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli GET greeting

メモリがいっぱいの状態で 2 MB の値を書き込むと、OOM command not allowed when used memory > 'maxmemory' が返され、アプリケーションでエラーが発生します。そのため、純粋なキャッシュには allkeys-lru を使います。Redis にキューなど失ってはいけないデータを保存する場合は、noeviction を使い、メモリ使用量を監視してください。

Compose でアプリケーションと組み合わせる

リクエストごとに Redis の visits を 1 増やす Flask カウンターを作成します。

redis-demo/
├── compose.yaml
├── .env
└── app/
    ├── app.py
    ├── requirements.txt
    └── Dockerfile

app/app.py:

import os

import redis
from flask import Flask

app = Flask(__name__)
r = redis.Redis.from_url(os.environ["REDIS_URL"], decode_responses=True)


@app.get("/")
def index():
    visits = r.incr("visits")
    return {"message": "Hello from Flask + Redis", "visits": visits}

app/requirements.txt:

flask==3.1.*
gunicorn==23.*
redis==6.*

app/Dockerfile(書き方の説明はPython アプリケーションを参照してください):

FROM python:3.14-slim
ENV PYTHONUNBUFFERED=1 PIP_NO_CACHE_DIR=1
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
USER nobody
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

.env:

REDIS_PASSWORD=change-this-password

compose.yaml:

services:
  app:
    build: ./app
    ports:
      - "8000:8000"
    environment:
      REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
    depends_on:
      redis:
        condition: service_healthy

  redis:
    image: redis:8-alpine
    command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}", "--appendonly", "yes"]
    environment:
      REDISCLI_AUTH: ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"]
      interval: 5s
      retries: 10
    restart: unless-stopped

volumes:
  redis_data:
設定説明
REDIS_URL 内の @redis:6379サービス名を使って接続します
command 内の ${REDIS_PASSWORD}Compose が .env の値を実際のパスワードに置き換えます
REDISCLI_AUTHコンテナ内の redis-cli(ヘルスチェックを含む)にパスワードを自動で渡します
redis に ports がない接続が必要なのは app だけなので、外部には公開しません
$ docker compose up -d --build

[+] Building 0.3s (12/12) FINISHED
 => [internal] load local bake definitions                                                                                                       0.0s
 => => reading from stdin 486B                                                                                                                   0.0s
 => [internal] load build definition from Dockerfile                                                                                             0.0s
 => => transferring dockerfile: 263B                                                                                                             0.0s
 => [internal] load metadata for docker.io/library/python:3.14-slim                                                                              0.0s
 => [internal] load .dockerignore                                                                                                                0.0s
 => => transferring context: 2B                                                                                                                  0.0s
 => [1/5] FROM docker.io/library/python:3.14-slim@sha256:a2b82f3c48559aa0a8446d9af49826b6e2b2016f4cd2afabfe6013ec53729170                        0.0s
 => => resolve docker.io/library/python:3.14-slim@sha256:a2b82f3c48559aa0a8446d9af49826b6e2b2016f4cd2afabfe6013ec53729170                        0.0s
 => [internal] load build context                                                                                                                0.0s
 => => transferring context: 93B                                                                                                                 0.0s
 => CACHED [2/5] WORKDIR /app                                                                                                                    0.0s
 => CACHED [3/5] COPY requirements.txt .                                                                                                         0.0s
 => CACHED [4/5] RUN pip install -r requirements.txt                                                                                             0.0s
 => CACHED [5/5] COPY . .                                                                                                                        0.0s
 => exporting to image                                                                                                                           0.0s
 => => exporting layers                                                                                                                          0.0s
 => => exporting manifest sha256:2cb1f769137117a44dde49bfb2f8551a8ce989fe8bd0a72696ba37987c29fd13                                                0.0s
 => => exporting config sha256:88373d2af6030b965f8b4e878d871e906738cd9194ec77bd007c6bbbace7c1b9                                                  0.0s
 => => exporting attestation manifest sha256:c8f570c26323c3e08476544296d44ed0e159d27d9f25b86bf879cd08c6b6e186                                    0.0s
 => => exporting manifest list sha256:46bd2450b425a935481fb6ef8567c915f5543996f4e35018bdb955ecf858b361                                           0.0s
 => => naming to docker.io/library/redis-demo-app:latest                                                                                         0.0s
 => => unpacking to docker.io/library/redis-demo-app:latest                                                                                      0.0s
 => resolving provenance for metadata file                                                                                                       0.0s
[+] up 5/5
 ✔ Image redis-demo-app         Built                                                                                                             0.4s
 ✔ Network redis-demo_default   Created                                                                                                           0.0s
 ✔ Volume redis-demo_redis_data Created                                                                                                           0.0s
 ✔ Container redis-demo-redis-1 Healthy                                                                                                           5.8s
 ✔ Container redis-demo-app-1   Started                                                                                                           5.9s

$ curl -s http://localhost:8000/
{"message":"Hello from Flask + Redis","visits":1}

$ curl -s http://localhost:8000/
{"message":"Hello from Flask + Redis","visits":2}

$ curl -s http://localhost:8000/
{"message":"Hello from Flask + Redis","visits":3}

Redis が Healthy になってから app が起動し、リクエストごとに visits が 1 増えます。AOF を有効にして Volume をマウントしているため、すべてのコンテナを再作成してもカウントは引き継がれます。

$ docker compose up -d --force-recreate
[+] up 2/2
 ✔ Container redis-demo-redis-1 Healthy                                                                                                           6.1s
 ✔ Container redis-demo-app-1   Started                                                                                                           6.2s

$ curl -s http://localhost:8000/
{"message":"Hello from Flask + Redis","visits":4}

ヘルスチェックで grep PONG を使う理由

よく見かける書き方は test: ["CMD", "redis-cli", "ping"] です。実際に終了コードを確認してみましょう。

$ docker compose exec redis redis-cli ping; echo "exit code: $?"
PONG
exit code: 0

$ docker compose exec -e REDISCLI_AUTH=wrong redis redis-cli ping; echo "exit code: $?"
AUTH failed: WRONGPASS invalid username-password pair or user is disabled.
NOAUTH Authentication required.

exit code: 0

$ docker compose exec -e REDISCLI_AUTH=wrong redis sh -c "redis-cli ping | grep -q PONG"; echo "exit code: $?"
AUTH failed: WRONGPASS invalid username-password pair or user is disabled.
exit code: 1

パスワードが間違っていると、redis-cli は NOAUTH Authentication required. と出力しますが、終了コードは 0 のままです。Docker は終了コードだけで正常かどうかを判断するため、パスワードが間違っていてもヘルスチェックは通り、app の起動後に接続が失敗します。| grep -q PONG を追加すると、実際に PONG を受信した場合にのみ終了コードが 0 になります。

よく使う redis-cli コマンド

docker exec redis redis-cli INFO memory      # メモリ使用量
docker exec redis redis-cli INFO stats       # 統計情報(evicted_keys を含む)
docker exec redis redis-cli DBSIZE           # key の数
docker exec redis redis-cli --scan --pattern 'session:*' | head
docker exec -it redis redis-cli MONITOR      # すべてのコマンドをリアルタイム表示(デバッグ用。性能に影響し、Ctrl+C で終了)

パスワードを設定している場合は、docker exec に -e REDISCLI_AUTH=パスワード を追加します。

本番環境では KEYS * を使わないでください。すべての key をスキャンして Redis をブロックするため、key が多いと数秒間停止することがあります。代わりに SCAN(redis-cli --scan)を使ってください。

GUI でデータを閲覧するには、公式の Redis Insight(イメージ redis/redisinsight、デフォルトポート 5540)を使えます。初回起動時にライセンス条項を読んで同意する必要があります。その後、接続を追加し、ホストに Compose のサービス名 redis、ポートに 6379、パスワードを入力すれば接続できます。

Redis のライセンスと Valkey

Redis は 2024 年にライセンスを RSALv2/SSPL などの非オープンソースライセンスに変更し、Redis 8 からは AGPLv3 も選択肢に加わりました。Linux Foundation は 2024 年に、互換性のあるオープンソースのフォーク Valkey(BSD ライセンス)を公開しました。コマンドと使い方はほぼ同じです。

$ docker run -d --name valkey valkey/valkey:8-alpine
Unable to find image 'valkey/valkey:8-alpine' locally
8-alpine: Pulling from valkey/valkey
Digest: sha256:081c2f5cb575efc901aa80ff9cdbd1ec6a301682fd35e1ebb4b0990a4a4a8507
Status: Downloaded newer image for valkey/valkey:8-alpine
3e7385b8f0d22a999ccf9306938e178c8f82bb4bc1ef9d304bd307917a890087

$ docker exec valkey valkey-cli PING
PONG

$ docker exec valkey redis-cli SET greeting hello
OK

$ docker exec valkey valkey-server --version
Valkey server v=8.1.10 sha=00000000:1 malloc=jemalloc-5.3.0 bits=64 build=fd3b186b1408478b

$ docker rm -f valkey
valkey

Valkey イメージには valkey-cli と互換性のある redis-cli の両方が含まれており、アプリケーションの Redis ライブラリからもそのまま接続できます。個人で Redis を使う場合、ライセンス変更の影響はありません。Redis をサービスとして他者に提供する場合は、ライセンス条項を確認してください。

まとめ

  • Redis にはデフォルトでパスワードがありません。--requirepass で設定し、REDISCLI_AUTH で渡します。
  • RDB はリアルタイムに保存されません。信頼性が必要な場合は --appendonly yes を有効にします。
  • キャッシュとして使う場合は maxmemory と allkeys-lru を設定します。
  • ヘルスチェックには redis-cli ping | grep -q PONG と書きます。

練習問題

練習 1:docker exec redis redis-cli を使い、30 秒後に期限切れになる key を設定して、残り時間を確認してください。

解答
docker exec redis redis-cli SET temp hello EX 30
docker exec redis redis-cli TTL temp

パスワードがある場合は -e REDISCLI_AUTH=パスワード を追加します。

よくある質問

Redisには必ずパスワードを設定する必要がありますか?

他の人が接続できる可能性があるなら、必ず設定してください。最善の方法はポートを外部に公開せず、パスワードを設定することです。

Redisを再起動したらデータが消えました。

デフォルトのRDBは、保存条件を満たしたとき、または正常に停止したときにのみディスクへ書き込みます。docker rm -fやクラッシュではデータが失われます。確実に保存するにはAOFを有効にしてください。

ValkeyとRedisは互換性がありますか?

ValkeyはRedisのオープンソースフォークで、コマンドとプロトコルに互換性があります。通常、アプリケーションの変更は不要です。

更新日 2026年10月14日