如何让 django-crontab 在 Docker 容器中执行命令?
How to make django-crontab execute commands in Docker container?
为了在我的 Django 应用程序中定期执行任务,我安装了 django_crontab
扩展。我的应用程序由 dockerized 数据库和 Django 应用程序组成。
https://pypi.org/project/django-crontab/
我已经按照设置段落中的描述完成了每一步。
settings.py
INSTALLED_APPS = [
...
'django_crontab',
]
...
CRONJOBS = [
('*/1 * * * *', 'config.cron.fun')
]
cron.py
def fun():
print("hello cron")
with open("./test.txt", "a") as f:
f.write("Hello")
我还在 docker-entrypoint.yml
中添加了 cron 作业:
python manage.py crontab add
python manage.py crontab show
输出:
webapp | no crontab for root
webapp | adding cronjob: (ebcca28ea3199afe6d09a445db5d5fd8) -> ('*/1 * * * *', 'config.cron.fun')
webapp | Currently active jobs in crontab:
webapp | ebcca28ea3199afe6d09a445db5d5fd8 -> ('*/1 * * * *', 'config.cron.fun')
在 Dockerfile
我使用 python:3.8
图像并安装 cron
:
RUN apt-get install -y cron && touch /var/log/cron.log
运行容器后无响应。
进入容器后,可以看到cron看到了job,但是还是没有执行
root@bar:/back# crontab -l
*/1 * * * * /usr/local/bin/python /back/manage.py crontab run ebcca28ea3199afe6d09a445db5d5fd8 # django-cronjobs for config
我该如何解决?
编辑:
整个 Dockerfile:
FROM python:3.8
ENV PYTHONUNBUFFERED 1
RUN mkdir /back
WORKDIR /back
COPY . /back/
RUN apt-get update
RUN apt-get install -y cron && touch /var/log/cron.log
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
ENTRYPOINT ["python3", "manage.py"]
CMD ["runserver", "0.0.0.0:8080"]
docker-compose.yml
:
version: "3"
services:
db:
image: postgres:latest
restart: unless-stopped
container_name: database
env_file:
- .env
webapp:
build: ./back
container_name: webapp
restart: unless-stopped
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
links:
- db:db
volumes:
- ./back:/back
entrypoint: "bash /back/docker-entrypoint.sh"
command: "runserver 0.0.0.0:8000"
docker-entrypoint.yml
- 这里进行了迁移,等待 db
并提到 crontab
命令
一个Docker容器只有运行一个进程。您需要 运行 两个独立的东西:主应用程序服务器和(经过一些初始设置后)cron 守护程序。您可以直接 运行 两个单独的容器 运行 使用正确的设置从同一图像中设置两个单独的命令。
我要在这里做的第一个改变是将你目前的拆分 ENTRYPOINT
和 CMD
组合成一个 CMD
:
# no ENTRYPOINT, but
CMD ["python3", "manage.py", "runserver", "0.0.0.0:8080"]
通过此设置,您可以使用此默认命令启动一个容器,并从同一图像启动第二个命令,但覆盖 Compose 设置中的 command:
。
version: '3.8'
services:
db: { ... }
webapp:
build: ./back
restart: unless-stopped
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
# run the default command: from the image; no override
# skip unnecessary links:, container_name:, volumes: options
cron:
build: ./back # same as main application
restart: unless-stopped
env_file:
- .env
depends_on:
- db
command: cron -f # as a long-running foreground process
我们在这里没有做的事情是在容器启动时填充 crontab。这就是 ENTRYPOINT
可以发挥作用的地方:如果你有一个 ENTRYPOINT
,它会得到 运行 而不是 CMD
,但它会得到 passed the CMD
as arguments。这里一个非常典型的模式是将 ENTRYPOINT
用于 shell 脚本,该脚本执行一些首次设置,然后以 exec "$@"
到 运行 结束,无论提供什么 CMD
/command:
是。
#!/bin/sh
# docker-entrypoint.sh
# If this is going to be a cron container, set up the crontab.
if [ "" = cron ]; then
./manage.py crontab add
fi
# Launch the main container command passed as arguments.
exec "$@"
然后在 Docker 文件中,将此脚本指定为 ENTRYPOINT
.
...
WORKDIR /back
COPY . ./ # including docker-entrypoint.sh
...
ENTRYPOINT ["./docker-entrypoint.sh"] # must be JSON-array syntax
CMD ["./manage.py", "runserver", "0.0.0.0:8080"] # as before
您无需在此处覆盖 entrypoint:
。像 docker-compose run web app bash
这样的命令来获得交互式调试 shell 可以正常工作;他们将通过该入口点脚本,运行 shell 作为最后的 exec "$@"
行。
为了在我的 Django 应用程序中定期执行任务,我安装了 django_crontab
扩展。我的应用程序由 dockerized 数据库和 Django 应用程序组成。
https://pypi.org/project/django-crontab/
我已经按照设置段落中的描述完成了每一步。
settings.py
INSTALLED_APPS = [
...
'django_crontab',
]
...
CRONJOBS = [
('*/1 * * * *', 'config.cron.fun')
]
cron.py
def fun():
print("hello cron")
with open("./test.txt", "a") as f:
f.write("Hello")
我还在 docker-entrypoint.yml
中添加了 cron 作业:
python manage.py crontab add
python manage.py crontab show
输出:
webapp | no crontab for root
webapp | adding cronjob: (ebcca28ea3199afe6d09a445db5d5fd8) -> ('*/1 * * * *', 'config.cron.fun')
webapp | Currently active jobs in crontab:
webapp | ebcca28ea3199afe6d09a445db5d5fd8 -> ('*/1 * * * *', 'config.cron.fun')
在 Dockerfile
我使用 python:3.8
图像并安装 cron
:
RUN apt-get install -y cron && touch /var/log/cron.log
运行容器后无响应。
进入容器后,可以看到cron看到了job,但是还是没有执行
root@bar:/back# crontab -l
*/1 * * * * /usr/local/bin/python /back/manage.py crontab run ebcca28ea3199afe6d09a445db5d5fd8 # django-cronjobs for config
我该如何解决?
编辑: 整个 Dockerfile:
FROM python:3.8
ENV PYTHONUNBUFFERED 1
RUN mkdir /back
WORKDIR /back
COPY . /back/
RUN apt-get update
RUN apt-get install -y cron && touch /var/log/cron.log
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
ENTRYPOINT ["python3", "manage.py"]
CMD ["runserver", "0.0.0.0:8080"]
docker-compose.yml
:
version: "3"
services:
db:
image: postgres:latest
restart: unless-stopped
container_name: database
env_file:
- .env
webapp:
build: ./back
container_name: webapp
restart: unless-stopped
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
links:
- db:db
volumes:
- ./back:/back
entrypoint: "bash /back/docker-entrypoint.sh"
command: "runserver 0.0.0.0:8000"
docker-entrypoint.yml
- 这里进行了迁移,等待 db
并提到 crontab
命令
一个Docker容器只有运行一个进程。您需要 运行 两个独立的东西:主应用程序服务器和(经过一些初始设置后)cron 守护程序。您可以直接 运行 两个单独的容器 运行 使用正确的设置从同一图像中设置两个单独的命令。
我要在这里做的第一个改变是将你目前的拆分 ENTRYPOINT
和 CMD
组合成一个 CMD
:
# no ENTRYPOINT, but
CMD ["python3", "manage.py", "runserver", "0.0.0.0:8080"]
通过此设置,您可以使用此默认命令启动一个容器,并从同一图像启动第二个命令,但覆盖 Compose 设置中的 command:
。
version: '3.8'
services:
db: { ... }
webapp:
build: ./back
restart: unless-stopped
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
# run the default command: from the image; no override
# skip unnecessary links:, container_name:, volumes: options
cron:
build: ./back # same as main application
restart: unless-stopped
env_file:
- .env
depends_on:
- db
command: cron -f # as a long-running foreground process
我们在这里没有做的事情是在容器启动时填充 crontab。这就是 ENTRYPOINT
可以发挥作用的地方:如果你有一个 ENTRYPOINT
,它会得到 运行 而不是 CMD
,但它会得到 passed the CMD
as arguments。这里一个非常典型的模式是将 ENTRYPOINT
用于 shell 脚本,该脚本执行一些首次设置,然后以 exec "$@"
到 运行 结束,无论提供什么 CMD
/command:
是。
#!/bin/sh
# docker-entrypoint.sh
# If this is going to be a cron container, set up the crontab.
if [ "" = cron ]; then
./manage.py crontab add
fi
# Launch the main container command passed as arguments.
exec "$@"
然后在 Docker 文件中,将此脚本指定为 ENTRYPOINT
.
...
WORKDIR /back
COPY . ./ # including docker-entrypoint.sh
...
ENTRYPOINT ["./docker-entrypoint.sh"] # must be JSON-array syntax
CMD ["./manage.py", "runserver", "0.0.0.0:8080"] # as before
您无需在此处覆盖 entrypoint:
。像 docker-compose run web app bash
这样的命令来获得交互式调试 shell 可以正常工作;他们将通过该入口点脚本,运行 shell 作为最后的 exec "$@"
行。