Docker の Redis イメージに初期データをロードするベストプラクティス
ローカル環境で動作を確認しながら開発していると、サクッとデータベースに接続したくなるタイミングが割とすぐに来ますよね。AWS などの PaaS で立ち上げても良いのですが、やはりローカル開発ならローカルで済むに越したことはありません。さらに、頻繁にデータを入れ替えたりする場合は AWS だと逆に手間やコストがかかる場合もあります。
私は使用したいデータベースの公式 Docker イメージが提供されている場合は、Docker で済ませてしまいます。今回は Docker コンテナで動作するデータベースに、初期データをロードする方法についてベストプラクティスを紹介します。
はじめに
公式 Docker イメージの多くは、コンテナを立ち上げた段階でデータベースに接続して利用できる状態になります。つまり、Docker コンテナを起動した後にデータロードの処理を実装する隙がないケースがほとんどです。これは Docker コンテナ起動後に、コンテナの外側からわざわざ接続して、データをロードする必要が有ることを意味しています。後述の説明では、Redis を例に Docker コンテナの内側から、コンテナの起動と同時にデータをロードする方法を紹介します。
ベストプラクティス
まずはディレクトリ構成です。 任意のディレクトリに後述の3つのファイルを作成します。
.
├ preload-data
│ └ example.txt
├ docker-compose.yml
└ startup.sh
起動処理をオーバーライドする
Redis の起動処理をオーバーライドする startup.sh
を作成します。
このシェルを Dockerfile
の CMD
に指定すればデータのプリロードを実現できますが、今回は Dockerfile
を作成せず、 docker-compose.yml
のみで構成します。
startup.sh
# ジョブコントロールを有効化 (最後の fg コマンドを利用するため)
set -m
# redis-server をバックグラウンドで起動して3秒待機 (秒数は適宜調整)
redis-server &
sleep 3
# データロード処理
# (1行目のように直接書いても良いが、2行目のファイルから読み込む方法がオススメ)
redis-cli set test-data test-value
redis-cli < ./preload-data/example.txt
# バックグラウンドの redis-server をフォアグランドに戻す
fg %1
プリロードデータを準備する
プリロードデータをシェルの外から読み込む場合に必要なファイルです。
example.txt
set batch-test-data1 batch-test-value1
hset batch-test-data2 key1 batch-test-value2-1
hset batch-test-data2 key2 batch-test-value2-2
Docker Compose で起動する
Dockerfile
を作成しても良いのですが、データディレクトリのマウントやデータの入れ替えを考えると、最初から docker-compose.yml
でデータディレクトリをマウントした状態で Docker コンテナを起動した方が捗るため、以下のファイルを作成します。
docker-compose.yml
version: "3.7"
services:
database:
image: redis:6.2.6
command: /bin/bash /data/startup.sh
ports:
- 6379:6379
volumes:
- ./startup.sh:/data/startup.sh
- ./preload-data:/data/preload-data
データがロードされたか確認する
Docker コンテナを起動して、データがロードされるか確認します。
redis-cli
の中で叩いた keys *
に、想定通りのキーが出力されれば OK です。
% cd (docker-compose.ymd を配置したフォルダ)
% docker-compose up -d
Creating network "example_default" with the default driver
Creating example_database_1 ... done
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
(CONTAINER-ID) redis:6.2.6 "docker-entrypoint.s…" 14 seconds ago Up 13 seconds 6379/tcp example_database_1
% docker exec -it (CONTAINER-ID) bash
xxxxx@(CONTAINER-ID):/data# redis-cli
127.0.0.1:6379>keys *
1) "batch-test-data2"
2) "test-data"
3) "batch-test-data1"