dockerでcrondをフォアグラウンド起動しておくメモ。
crontabのことは以前に書いたけれども、dockerでcrondを使用することについては、あまり細かいことを書いていなかったので、別で書いておきたい。
更新履歴
- 2022/12: 見出しの整理。githubのサンプルレポジトリを追加。
やりたいこと
docker上でcrondを動作させたい。できればrootでないユーザ上で起動させたい。正直rootでも問題はなさそうだけどユーザについてのメモも残したいので記録しておく。
外部からの入力・リクエストを受け付けるならrootでないほうがいい。
crontabファイルについては省略。テスト用では* * * * * echo -n hello crontab && date
だけ書いている。
実際使うならverboseになる-l
やcrondのログの出力先を決める-L
オプションは変更する。
docker compose
で使っており、docker-compose.yml
は次のようなごく単純なもの:
services:
cron:
build: .
この前提でdockerでcrondを使用したい。
USER設定するとそのままでは動かない
crondはrootでの動作が前提になっているようで、次のように:
# ./BadDockerfile
## うまくいかない例
FROM python:alpine
ARG ANUSER=myuser
COPY crontabfile /tmp/crontabfile
RUN adduser -D ${ANUSER} && \
crontab -u ${ANUSER} /tmp/crontabfile && \
rm /tmp/crontabfile
USER ${ANUSER}
CMD [ "crond", "-f", "-l", "0", "-L", "/dev/stdout" ]
ただUSER
を設定しただけでは、起動はするものの、permission denied
になっていて定期実行されない。
rootで動かす
なお、rootのままでいいならば、USER
設定を省いた以下で十分動く:
# ./Dockerfile1
## このようにrootで動かせば普通に動く。
FROM python:alpine
COPY crontabfile /tmp/crontabfile
RUN crontab /tmp/crontabfile && \
rm /tmp/crontabfile
CMD [ "crond", "-f", "-l", "0", "-L", "/dev/stdout" ]
ユーザを変更して動かすならsudoersを編集する
ちょうどsudoers
についていじっていたので、これに追加すればいいとすぐに思いついた。ただ、Alpine
にはsudoコマンドがないので、apk
での導入が必要になる。
そして、特定ユーザの特定コマンドの実行でパスワードの要求を不要にすればいいので、次のようになる:
# ./Dockerfile2
FROM python:alpine
ARG ANUSER=myuser
COPY crontabfile /tmp/crontabfile
RUN apk update --no-cache && \
apk add --no-cache sudo && \
adduser -D ${ANUSER} && \
echo "Cmnd_Alias USERCOMMANDS = /usr/sbin/crond" >> /etc/sudoers && \
echo "${ANUSER} ALL=PASSWD: ALL, NOPASSWD: USERCOMMANDS" >> /etc/sudoers && \
crontab -u ${ANUSER} /tmp/crontabfile && \
rm /tmp/crontabfile
USER ${ANUSER}
CMD [ "sudo", "crond", "-f", "-L", "/dev/stdout" ]
これで目的は達成できた。
githubにサンプルを用意した(2022/12追記)
crond
でwhoami
するだけのサンプルレポジトリを用意した。docker-compose.yml
を書き換えてビルド時に使用するDockerfile
を切り替えてユーザの変化を確認できる:
おわり
ほかにも、supervisordを使う方法もある。以前に書いた。
よく考えて使い分けたい。ほかの方法もあるだろう。
ひとまず、docker+crondについては以上です。