supervisordでコンテナ内の設定ファイルの変更検知と自動リロードをする(自動同期を添えて)
この記事は SKIYAKI Tech Blog Advent Calendar 2025 の1日目の記事になります。
「Dockerで動かしているconf変更してわざわざ再起動させるの面倒だな…」
「設定変更したのに上手く動かない…と思ってたらDockerコンテナの再起動忘れてた…やったと思ってたんだけどな…」
そんな経験あると思います。私はあります。
本記事では、設定ファイルを書き換えたら変更を検知して自動でリロードしてくれるDockerイメージを作ります。
さらに、ローカルファイルとコンテナ上のファイルを同期させる Docker Compose 環境も作ってみます。
今回は nginx の設定を自動リロードしてくれるDockerイメージを作ってみましょう。
以下の環境で試してみます。
| 名前 | バージョン |
|---|---|
| Docker | 28.5.2 |
| Docker Desktop | 4.51.0 (210443) |
| Docker Compose | v2.40.3-desktop.1 |
| nginx(Docker image) | 1.29.3-alpine |
supervisord とは
supervisord (Supervisor) は、UNIX系OS上で複数のプロセスを管理・監視するためのクライアント/サーバーシステムです。
通常、Dockerコンテナは「1コンテナにつき1プロセス」という原則で設計されており、コンテナ起動時に指定したメインプロセスが終了するとコンテナ自体も停止してしまいます。
しかし、今回のように「Nginx(メインのWebサーバー)」と「設定ファイルの変更を監視するスクリプト」といった複数のプロセスを1つのコンテナ内で同時に稼働させたい場合には、それらを統括するプロセスマネージャーが必要になります。
そのために supervisord を稼働させ、 supervisord 越しに nginx プロセスの起動と、Nginxの設定リロードを実施する監視スクリプトの起動を実現してみます。
今回は supervisord を採用し、nginx と監視スクリプトの両方を稼働させるという役割を担わせます。
これにより、Dockerコンテナのメリットを活かしつつ、柔軟な開発環境を構築することができます。
Dockerイメージを作る
作業用のディレクトリを作って移動しておきます。
ここに一連のファイルを保存していきます。
$ mkdir -p nginx_autoreload && cd $_
Dockerfile
既存のDockerイメージを元にして、Dockerfileを書いていきます。
まず必要になるのは、メインで稼働させる nginx ですが、これは元にするnginxのDockerイメージに既に導入されているため別途導入しなくてもOKですね。
他に必要となるのは inotify-tools 、 supervisord となります。
今回元にするDockerイメージのディストリビューションはalpineのため、上記のツールは apk を使って導入します。
また、その他必要なファイルをローカルに作っておき、それぞれ COPY でDockerイメージのビルド時に組み込みます。
では早速Dockerfileを書いていきましょう。
以下のようなDockerfileを用意します。
COPY でDockerイメージに追加しているファイルはこの後用意していきます。
FROM nginx:1.29.3-alpine-slim
RUN apk update \
&& apk upgrade \
&& apk add inotify-tools supervisor \
&& apk cache clean
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./conf.d /etc/nginx/conf.d
COPY ./entrypoint.sh /opt/entrypoint.sh
COPY ./supervisord.conf /opt/supervisord.conf
EXPOSE 80
EXPOSE 443
ENTRYPOINT ["/opt/entrypoint.sh"]
CMD ["start"]
ENTRYPOINT には自前で作った entrypoint.sh を指定します。
CMD には、デフォルト引数として start を指定しておきます。
引数は複数使用できる予定で、詳細は次で解説しますが、 start の場合は単純にnginxを起動させるだけとなっています。
次に COPY で追加するファイルを作成していきます。
entrypoint.sh
entrypoint.sh も以下のように新たに作ります。
作っている関数や引数に指定できる文字列は以下の通りです。
| 関数名 | 引数名 | 説明 |
|---|---|---|
log_info() |
- | 標準出力に日付付きで指定した文字列を出力するための内部関数 |
nginx_autoreloader() |
nginx-autoreloader |
/etc/nginx 以下の変更を検知したらnginxのreloadを実行する |
nginx_start() |
start |
nginxを起動する |
nginx_reload() |
reload |
nginxのreloadを実行する |
nginx_check() |
check |
nginxのconfを確認する |
| - | supervisord |
supervisordを起動する |
| - | exec |
引数をコマンドとして実行する |
今回の自動リロードを実現するにあたって、 enrypoint.sh で肝になる関数は、 nginx_autoreloader() と、 supervisord になります。
まずは entrypoint.sh の全文を記載します。
#!/bin/sh
function usage() {
local _script_name="$0"
cat <<EOL >&2
${_script_name} is script for starting nginx
Usage:
${_script_name} [[command] [arguments]]
Command:
start start nginx
check check nginx config
reload reload nginx process
nginx-autoreloader start nginx-autoreloder
supervisord start supervisord
exec execute linux command on Docker container(default option)
required [arguments]
exec e.g)
$ ${_script_name} exec ls -la
or
$ ${_script_name} ls -la
EOL
}
function log_info() {
time=$(date "+%Y/%m/%d %H:%M:%S")
echo "${time} [info] $@" > /dev/stdout
}
function nginx_autoreloader() {
while inotifywait -e create -e modify -e delete -e move -r /etc/nginx > /dev/null 2>&1; do
# 15秒の待機時間を置く
sleep 15
# nginxのステータスチェックをして成功(0)であればnginxをreloadする
nginx_status
if [ $? -eq 0 ]; then
log_info "Detected Nginx Configuration Change"
log_info "Executing: nginx -s reload"
nginx_reload
fi
done
}
function nginx_start() {
exec nginx -g 'daemon off;'
}
function nginx_reload() {
nginx -s reload
}
function nginx_check() {
nginx -t
}
_ARG="$1"
if [ ! -z "${_ARG}" ]; then
case "${_ARG}" in
--help|-h|help|--usage|usage )
usage
;;
start )
nginx_start
;;
check )
nginx_check
;;
reload )
nginx_reload
;;
nginx-autoreloader )
nginx_autoreloader
;;
supervisord )
exec /usr/bin/supervisord -c /opt/supervisord.conf
;;
exec )
shift 1
exec "$@"
;;
* )
exec "$@"
;;
esac
else
usage
exit 1
fi
これで全文です。かなり短めのスクリプトになっています。
全体の解説はせず、肝である nginx_autoreloader() と、 supervisord を見ていきましょう。
最初に nginx_autoreloader() から見ていきます。
nginx_autoreloader()
nginx_autoreloader() は以下のような関数になっています。
function nginx_autoreloader() {
while inotifywait -e create -e modify -e delete -e move --exclude .swp -r /etc/nginx > /dev/null 2>&1; do
# 15秒の待機時間を置く
sleep 15
# nginxのステータスチェックをして成功(0)であればnginxをreloadする
nginx_status
if [ $? -eq 0 ]; then
log_info "Detected Nginx Configuration Change"
log_info "Executing: nginx -s reload"
nginx_reload
fi
done
}
どんな処理をしているのか
while を使ったループの流れとしては以下のような形です。
-
whileを使ってinotifywaitを繰り返し実行し、/etc/nginx以下のイベントを監視します。 - ファイルの作成/変更/削除がされると、
inotifywaitコマンドは成功(終了コード 0)して終了します。 -
whileはコマンドの成功を受けて、while内部の処理へ移行します。 - まず最初に
sleep 15としています。これはファイルの変更を短時間に何度も検知した場合、その回数だけnginxのreloadが走ってしまうのを防ぐための措置になります。 - 次に
nginx_statusを実行し、設定ファイルに不備がないかを確認します。もし不備があってチェックが失敗した場合はreloadされません。 - 不備がなければ標準出力にログを出力し、
nginx_reloadを実行して、設定のreloadを実施します。 - ループ内の処理が終わると、
whileは再びinotifywaitを実行し、次のイベントを待ち受けます。
inotifywait というコマンドを使って /etc/nginx 以下のファイルの変更をリアルタイムで監視します。
/etc/nginx 以下でファイルの作成/変更/削除がされたら、 inotifywait コマンドの実行が終了し、 while 内の処理に進むというものです。
これで /etc/nginx 以下のファイルの変更検知ができます。
supervisord
supervisord はシンプルで、単純に supervisord コマンドを実行させているだけのものとなります。
supervisord )
exec /usr/bin/supervisord -c /opt/supervisord.conf
;;
引数に COPY でDockerイメージに組み込んだ /opt/supervisord.conf を指定しているだけとなっています。
supervisord.conf
supervisord.conf の内容も大したことはしていません。
supervisord を nodaemon で稼働させ、
/opt/entrypoint.sh start で nginx を稼働させ、
/opt/entrypoint.sh nginx-autoreloader で nginx_autoreloader を稼働させているだけとなります。
[supervisord]
nodaemon = true
user = root
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0
[program:nginx]
command = /opt/entrypoint.sh start
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0
[program:nginx_autoreloader]
command = /opt/entrypoint.sh nginx-autoreloader
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0
プロセス一覧を確認してみると、PID1に supervisord が存在していて、他のプロセスとして nginx と /opt/entrypoint.sh nginx-autoreloader が稼働している形となっていることがわかります。
ps auxwwf
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.8 0.3 34624 27436 pts/0 Ss+ 12:32 0:00 /usr/bin/python3 /usr/bin/supervisord -c /opt/supervisord.conf
root 6 0.0 0.0 10052 5896 pts/0 S 12:32 0:00 nginx: master process nginx -g daemon off;
nginx 9 0.0 0.0 10508 2896 pts/0 S 12:32 0:00 \_ nginx: worker process
nginx 10 0.0 0.0 10508 2896 pts/0 S 12:32 0:00 \_ nginx: worker process
nginx 11 0.0 0.0 10508 2896 pts/0 S 12:32 0:00 \_ nginx: worker process
nginx 12 0.0 0.0 10508 2896 pts/0 S 12:32 0:00 \_ nginx: worker process
root 7 0.0 0.0 1708 1012 pts/0 S 12:32 0:00 /bin/sh /opt/entrypoint.sh nginx-autoreloader
root 8 0.0 0.0 1160 664 pts/0 S 12:32 0:00 \_ inotifywait -e create -e modify -e delete -e move --exclude .swp -r /etc/nginx
この nginx と nginx-autoreloader を同時に動かさないと、今回の自動リロードが実現できないのです。
そのため、わざわざ supervisord を用いて複数プロセスを稼働させています。
nginx.conf など
後はnginxの設定ファイルですね。
これらも以下のように一旦テキトーに作っておきましょう。
ちなみにこの設定ファイルはnginxのDockerイメージから引っ張ってきてコメントなどを消したものになるので、ほとんどデフォルトの状態となっています。
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
conf.d/default.conf も作っておきます。
これも同じくDockerイメージから引っ張ってきたファイルです。
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
ここまで作ったら、Dockerイメージに組み込むファイルは完成です。
ファイルの確認
カレントディレクトリに作ったファイルは以下のような形になると思います。
.
├── conf.d
│ └── default.conf
├── Dockerfile
├── entrypoint.sh
├── nginx.conf
└── supervisord.conf
Dockerコンテナの動作確認
ここまでできたら一旦ビルドして実行してみましょう。
docker image build && docker container run
nginx:1.29.3-autoreload という名前のDockerイメージにしてみます。
$ docker image build -t nginx:1.29.3-autoreload .
ビルドが完了したらDockerコンテナとして実行してみます。
引数には supervisord を指定します。
また、Dockerコンテナには名前も付けてあげましょう。ここでは nginx_autoreload としておきます。
$ docker container run --rm --name nginx_autoreload \
-itd nginx:1.29.3-autoreload supervisord
/usr/lib/python3.12/site-packages/supervisor/options.py:13: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
import pkg_resources
2025-11-19 14:34:47,870 INFO Set uid to user 0 succeeded
2025-11-19 14:34:47,871 INFO supervisord started with pid 1
2025-11-19 14:34:48,876 INFO spawned: 'nginx' with pid 6
2025-11-19 14:34:48,879 INFO spawned: 'nginx-autoreloader' with pid 7
2025/11/19 14:34:48 [notice] 6#6: using the "epoll" event method
2025/11/19 14:34:48 [notice] 6#6: nginx/1.29.3
2025/11/19 14:34:48 [notice] 6#6: built by gcc 14.2.0 (Alpine 14.2.0)
2025/11/19 14:34:48 [notice] 6#6: OS: Linux 6.12.54-linuxkit
2025/11/19 14:34:48 [notice] 6#6: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025/11/19 14:34:48 [notice] 6#6: start worker processes
2025/11/19 14:34:48 [notice] 6#6: start worker process 9
2025/11/19 14:34:48 [notice] 6#6: start worker process 10
2025/11/19 14:34:48 [notice] 6#6: start worker process 11
2025/11/19 14:34:48 [notice] 6#6: start worker process 12
2025-11-19 14:34:49,891 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2025-11-19 14:34:49,891 INFO success: nginx-autoreloader entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
Dockerコンテナを稼働させたら、別ターミナルで docker container exec で、実行させたコンテナの sh を起動させて、 /etc/nginx/nginx.conf に文字列を追記してみます。
ここではコメントとして現在日時を追記してみます。
date コマンドで YYYY/MM/DD hh:mm:ss を出し、 tee -a で /etc/nginx/nginx.conf に文字列を追記します。
$ docker container exec -it nginx_autoreload sh
/ #
/ # echo "# $(date +'%Y/%m/%d %H:%M:%S')" | tee -a /etc/nginx/nginx.conf
# 2025/11/19 14:34:57
docker container run で起動させた方の元のターミナルに戻ります。
標準出力に約15秒経過後に nginx -t の出力と、 nginx -s reload の出力がされるはずです。
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
2025/11/19 14:35:13 [info] Detected Nginx Configuration Change
2025/11/19 14:35:13 [info] Executing: nginx -s reload
2025/11/19 14:35:13 [notice] 26#26: signal process started
2025/11/19 14:35:13 [notice] 6#6: signal 1 (SIGHUP) received from 26, reconfiguring
2025/11/19 14:35:13 [notice] 6#6: reconfiguring
2025/11/19 14:35:13 [notice] 6#6: using the "epoll" event method
2025/11/19 14:35:13 [notice] 6#6: start worker processes
2025/11/19 14:35:13 [notice] 6#6: start worker process 28
2025/11/19 14:35:13 [notice] 6#6: start worker process 29
2025/11/19 14:35:13 [notice] 6#6: start worker process 30
2025/11/19 14:35:13 [notice] 6#6: start worker process 31
2025/11/19 14:35:13 [notice] 10#10: gracefully shutting down
2025/11/19 14:35:13 [notice] 9#9: gracefully shutting down
2025/11/19 14:35:13 [notice] 9#9: exiting
2025/11/19 14:35:13 [notice] 10#10: exiting
2025/11/19 14:35:13 [notice] 9#9: exit
2025/11/19 14:35:13 [notice] 10#10: exit
2025/11/19 14:35:13 [notice] 11#11: gracefully shutting down
2025/11/19 14:35:13 [notice] 11#11: exiting
2025/11/19 14:35:13 [notice] 12#12: gracefully shutting down
2025/11/19 14:35:13 [notice] 12#12: exiting
2025/11/19 14:35:13 [notice] 11#11: exit
2025/11/19 14:35:13 [notice] 12#12: exit
2025/11/19 14:35:13 [notice] 6#6: signal 17 (SIGCHLD) received from 12
2025/11/19 14:35:13 [notice] 6#6: worker process 12 exited with code 0
2025/11/19 14:35:13 [notice] 6#6: signal 29 (SIGIO) received
2025/11/19 14:35:13 [notice] 6#6: signal 17 (SIGCHLD) received from 9
2025/11/19 14:35:13 [notice] 6#6: worker process 9 exited with code 0
2025/11/19 14:35:13 [notice] 6#6: worker process 10 exited with code 0
2025/11/19 14:35:13 [notice] 6#6: signal 29 (SIGIO) received
2025/11/19 14:35:13 [notice] 6#6: signal 17 (SIGCHLD) received from 11
2025/11/19 14:35:13 [notice] 6#6: worker process 11 exited with code 0
2025/11/19 14:35:13 [notice] 6#6: signal 29 (SIGIO) received
ここまで確認できればDockerイメージの作成は完了となります。
Docker Compose Watch でローカルのファイルと同期させる
Dockerイメージの用意はできました。
でもわざわざコンテナのシェルを実行して変更するというのは利便性に欠けますね。
そこで、 Docker Compose Watch を使って、ローカルファイルとコンテナ上のファイルの同期をするようにします。
これをすることで、ローカルファイルに変更を加えればコンテナ上のファイルも同期され、更に同期されるということは「ファイルの内容に変更が加えられる」ということなので、コンテナ上の変更検知に引っ掛かり、自動リロードされる…という仕組みです。
compose.yml
docker compose 用の compose.yml を書いていきます。
watch でローカルファイルと同期をさせるために、通常の設定以外に develop を用いた同期設定用文言を書いていきます。
develop:
watch:
- action: [Watchのアクション指定/ sync|rebuild]
path: [同期元となるローカルファイルのファイルパス]
target: [同期先となるDockerコンテナ上のファイルパス]
これを踏まえて compose.yml を書いてみます。
name: autoreload
services:
nginx_autoreload:
image: nginx:1.29.3-autoreload
build:
context: ./
dockerfile: ./Dockerfile
container_name: nginx_autoreload
ports:
- 127.0.0.1:80:80/tcp
- 127.0.0.1:443:443/tcp
command:
- "supervisord"
# 以下がDocker Compose Watch用の設定
develop:
watch:
- action: sync
path: ./conf.d
target: /etc/nginx/conf.d
- action: sync
path: ./nginx.conf
target: /etc/nginx/nginx.conf
簡単ですね。
Docker Compose Watch で動作確認
compose.yml を作ったので docker compose up -w で立ち上げてみます。
Watch を有効化するために -w オプションを付与しています。
$ docker compose up -w
[+] Running 2/2
✔ Network autoreload_default Created 0.0s
✔ Container nginx_autoreload Created 0.0s
⦿ Watch enabled
Attaching to nginx_autoreload
nginx_autoreload | /usr/lib/python3.12/site-packages/supervisor/options.py:13: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
nginx_autoreload | import pkg_resources
nginx_autoreload | 2025-11-20 12:08:26,152 INFO Set uid to user 0 succeeded
nginx_autoreload | 2025-11-20 12:08:26,153 INFO supervisord started with pid 1
nginx_autoreload | 2025-11-20 12:08:27,156 INFO spawned: 'nginx' with pid 7
nginx_autoreload | 2025-11-20 12:08:27,158 INFO spawned: 'nginx-autoreloader' with pid 8
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: using the "epoll" event method
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: nginx/1.29.3
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: built by gcc 14.2.0 (Alpine 14.2.0)
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: OS: Linux 6.12.54-linuxkit
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: getrlimit(RLIMIT_NOFILE): 1048576:1048576
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: start worker processes
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: start worker process 10
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: start worker process 11
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: start worker process 12
nginx_autoreload | 2025/11/20 12:08:27 [notice] 7#7: start worker process 13
nginx_autoreload | 2025-11-20 12:08:28,176 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
nginx_autoreload | 2025-11-20 12:08:28,177 INFO success: nginx-autoreloader entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
別のターミナルを開きます。
Dockerコンテナの動作確認と同じような形で、今度はローカルファイルの nginx.conf に追記してみます。
$ echo "# $(date +'%Y/%m/%d %H:%M:%S')" | tee -a nginx.conf
# 2025/11/20 21:08:35
元のターミナルに戻って同期を示す Syncing service "nginx_autoreload" after 1 changes were detected と、その後に設定ファイルチェック、リロードのログが出力されればOKです。
⦿ Syncing service "nginx_autoreload" after 1 changes were detected
nginx_autoreload | nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx_autoreload | nginx: configuration file /etc/nginx/nginx.conf test is successful
nginx_autoreload | 2025/11/20 12:08:50 [info] Detected Nginx Configuration Change
nginx_autoreload | 2025/11/20 12:08:50 [info] Executing: nginx -s reload
nginx_autoreload | 2025/11/20 12:08:50 [notice] 18#18: signal process started
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: signal 1 (SIGHUP) received from 18, reconfiguring
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: reconfiguring
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: using the "epoll" event method
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: start worker processes
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: start worker process 20
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: start worker process 21
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: start worker process 22
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: start worker process 23
nginx_autoreload | 2025/11/20 12:08:50 [notice] 11#11: gracefully shutting down
nginx_autoreload | 2025/11/20 12:08:50 [notice] 13#13: gracefully shutting down
nginx_autoreload | 2025/11/20 12:08:50 [notice] 10#10: gracefully shutting down
nginx_autoreload | 2025/11/20 12:08:50 [notice] 12#12: gracefully shutting down
nginx_autoreload | 2025/11/20 12:08:50 [notice] 12#12: exiting
nginx_autoreload | 2025/11/20 12:08:50 [notice] 13#13: exiting
nginx_autoreload | 2025/11/20 12:08:50 [notice] 10#10: exiting
nginx_autoreload | 2025/11/20 12:08:50 [notice] 13#13: exit
nginx_autoreload | 2025/11/20 12:08:50 [notice] 12#12: exit
nginx_autoreload | 2025/11/20 12:08:50 [notice] 10#10: exit
nginx_autoreload | 2025/11/20 12:08:50 [notice] 11#11: exiting
nginx_autoreload | 2025/11/20 12:08:50 [notice] 11#11: exit
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: signal 17 (SIGCHLD) received from 10
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: worker process 10 exited with code 0
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: signal 29 (SIGIO) received
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: signal 17 (SIGCHLD) received from 12
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: worker process 11 exited with code 0
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: worker process 12 exited with code 0
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: signal 29 (SIGIO) received
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: signal 17 (SIGCHLD) received from 13
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: worker process 13 exited with code 0
nginx_autoreload | 2025/11/20 12:08:50 [notice] 7#7: signal 29 (SIGIO) received
もっと簡単にやりたいな…え!?できるんですか!?
compose.yml は良いけど、わざわざ Dockerfile を書いたりしたくないなあ…。
そうですよね。
はい。もっとシンプルにできます。
それが watchのactionに指定できる sync+restart です。
その名の通り、「同期してコンテナをリスタートする」というものです。
develop:
watch:
- action: sync+restart
path: ./conf.d
target: /etc/nginx/conf.d
- action: sync+restart
path: ./nginx.conf
target: /etc/nginx/nginx.conf
これをすれば独自で Dockerfile を書かなくても良いのです。
え…じゃあこれでイイじゃん…?ねぇ…?(ちゃぶ台返し)
…とはいえ「最初にローカルファイルを COPY しておきたい」といったことがあればDockerfileを書かないといけません。
また、設定ファイル等のチェックは一切しないため、変更した設定ファイルの文法がおかしかった場合、コンテナが立ち上がってこない…なんてことも考えられます。
そんなわけで、色々安全にしたいなら Dockerfile を自前で書いて、 ENTRYPOINT も自前で用意するのが…良いように思います…。
…が… docker compose って基本的にローカルでしか使わないですよね…。
watchなんか特にローカルでしか使わないし…基本的に sync+restart だけで事足りるんじゃないですかね…。
文法ミスってた時も「自動リロードされない」よりも「コンテナ立ち上がって来ない」の方がわかりやすいような…。
どちらを選ぶべきか
ここまで長々と Dockerfile を書く方法を説明してきましたが、実際にはどちらを選ぶべきでしょうか。
最後にそれぞれのメリット/デメリットを整理してみます。
Dockerfile + supervisord で自動リロード
メリット:
- 設定ファイルの検証が可能。文法エラーがあってもサービスは継続稼働
- コンテナの再起動不要。Nginxのリロードだけで済むため接続が切れない
- リロードのタイミングや動作を細かく制御できる
デメリット:
-
Dockerfile、entrypoint.sh、supervisord.confなど複数ファイルの作成・管理が必要 -
supervisordやinotify-toolsの知識が必要 -
Dockerfileやsupervisordのconfigや自前スクリプトのメンテナンスが発生
sync+restart での自動再起動
メリット:
-
compose.ymlに数行追加するだけで実現 - Docker Composeの標準機能のみで完結
- 自前のスクリプトやツールが不要
- 文法エラーがあればコンテナが起動しないため、問題にすぐ気づける
デメリット:
- 毎回コンテナがフルリスタートするため、ダウンタイムが発生
- 開発中のテスト接続などが切れる可能性がある
- あくまでローカル開発専用の仕組み
以上のことからローカル開発環境で使うだけなら、sync+restart で十分だと思います。
シンプルな方が後々のメンテナンスも楽ですしね。
私は思い付かないのですが、特殊な環境下であれば、自前で Dockerfile などを用意してダウンタイムを極力避ける今回の手法も、有効な場合があるかもしれません。
まぁこういうやり方も実はありますよ…という事でひとつ…。
株式会社SKIYAKIのテックブログです。ファンクラブプラットフォームBitfanの開発・運用にまつわる知見や調べたことなどを発信します。主な技術スタックは Ruby on Rails / React / AWS / Swift / Kotlin などです。 recruit.skiyaki.com/
Discussion