도커 컨테이너 내에서 크론 작업을 실행하는 방법은 무엇입니까?
쉘 스크립트를 호출하는 도커 컨테이너 내에서 cronjob을 실행하려고합니다.
어제 웹과 스택 오버플로를 검색했지만 실제로 작동하는 솔루션을 찾을 수 없었습니다.
어떻게해야합니까?
편집하다:
주어진 간격마다 쉘 스크립트를 호출하는 작동하는 docker cron 컨테이너 로 (commented) github 저장소 를 만들었습니다 .
해당 이미지에서 시작된 컨테이너가 작업을 실행하기 위해 crontab을 이미지로 복사 할 수 있습니다.
자세한 내용은 " 부두 노동자와 cron 작업을 실행 에서" 줄리앙 Boulay 자신에 Ekito/docker-cron
:
hello-cron
작업을 설명하기 위해 " " 라는 새 파일을 만들어 봅시다 .
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.
다음 Dockerfile은 이미지를 빌드하는 모든 단계를 설명합니다.
FROM ubuntu:latest
MAINTAINER docker@ekito.fr
RUN apt-get update && apt-get -y install cron
# Copy hello-cron file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Apply cron job
RUN crontab /etc/cron.d/hello-cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log
( Gaafar 의 의견 과 설치를 덜 시끄럽게 만드는 방법을apt-get
참조하십시오 : :
apt-get -y install -qq --force-yes cron
작동 가능)
또는 hugoShaka 의 답변에 설명 된 것처럼 작업 자체가 로그 파일 대신 stdout / stderr로 직접 리디렉션되는지 확인하십시오 .
* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2
마지막 Dockerfile 줄을
CMD ["cron", "-f"]
(에 대한 참조 cron -f
크론 "전경"라고하는 것입니다있는) " 우분투는 고정 표시기 cron -f
작동하지 않습니다 "
빌드하고 실행하십시오.
sudo docker build --rm -t ekito/cron-example .
sudo docker run -t -i ekito/cron-example
인내심을 갖고 2 분 동안 기다리면 명령 행이 표시됩니다.
Hello world
Hello world
참고 수행
tail
이 이미지 빌드하는 동안 생성 된 경우 올바른 파일을 표시하지 않을 수 있습니다.
이 경우 테일이 올바른 파일을 선택하도록 컨테이너 런타임 동안 파일을 작성하거나 터치해야합니다.
" 도커 끝에 출력이 표시되지 않음tail -f
CMD
"을 참조하십시오.
채택 된 솔루션 은 프로덕션 환경에서 위험 할 수 있습니다 .
도커에서는 컨테이너 당 하나의 프로세스 만 실행해야합니다. 그렇지 않은 경우 분기 및 백그라운드로 진행된 프로세스는 모니터링되지 않으며이를 모르면 중지 될 수 있습니다.
당신이 사용하는 경우 CMD cron && tail -f /var/log/cron.log
실행하기 위해 기본적으로 포크 크론 프로세스를 cron
백그라운드에서 주요 프로세스 종료하고 실행하자 tailf
전경. 백그라운드 크론 프로세스가 중지되거나 실패 할 수 있습니다. 컨테이너는 여전히 자동으로 실행되며 오케스트레이션 도구는 다시 시작하지 않습니다.
당신은 당신의 고정 표시기에 직접 크론의 명령 출력을 리디렉션하여 이러한 일을 방지 할 수 있습니다
stdout
및stderr
각각 위치/proc/1/fd/1
및/proc/1/fd/2
.
기본 셸 리디렉션을 사용하면 다음과 같이 할 수 있습니다.
* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2
CMD는 다음과 같습니다. CMD ["cron", "-f"]
간단하고 가벼운 이미지를 사용하려는 사람들을 위해 :
FROM alpine:3.6
# copy crontabs for root user
COPY config/cronjobs /etc/crontabs/root
# start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]
여기서 cronjobs 는 다음 형식의 cronjob을 포함하는 파일입니다.
* * * * * echo "hello stackoverflow" >> /test_file 2>&1
# remember to end this file with an empty new line
What @VonC has suggested is nice but I prefer doing all cron job configuration in one line. This would avoid cross platform issues like cronjob location and you don't need a separate cron file.
FROM ubuntu:latest
# Install cron
RUN apt-get -y install cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Setup cron job
RUN (crontab -l ; echo "* * * * * echo "Hello world" >> /var/log/cron.log") | crontab
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log
After running your docker container, you can make sure if cron service is working by:
# To check if the job is scheduled
docker exec -ti <your-container-id> bash -c "crontab -l"
# To check if the cron service is running
docker exec -ti <your-container-id> bash -c "pgrep cron"
If you prefer to have ENTRYPOINT instead of CMD, then you can substitute the CMD above with
ENTRYPOINT cron start && tail -f /var/log/cron.log
There is another way to do it, is to use Tasker, a task runner that has cron (a scheduler) support.
Why ? Sometimes to run a cron job, you have to mix, your base image (python, java, nodejs, ruby) with the crond. That means another image to maintain. Tasker avoid that by decoupling the crond and you container. You can just focus on the image that you want to execute your commands, and configure Tasker to use it.
Here an docker-compose.yml
file, that will run some tasks for you
version: "2"
services:
tasker:
image: strm/tasker
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
environment:
configuration: |
logging:
level:
ROOT: WARN
org.springframework.web: WARN
sh.strm: DEBUG
schedule:
- every: minute
task: hello
- every: minute
task: helloFromPython
- every: minute
task: helloFromNode
tasks:
docker:
- name: hello
image: debian:jessie
script:
- echo Hello world from Tasker
- name: helloFromPython
image: python:3-slim
script:
- python -c 'print("Hello world from python")'
- name: helloFromNode
image: node:8
script:
- node -e 'console.log("Hello from node")'
There are 3 tasks there, all of them will run every minute (every: minute
), and each of them will execute the script
code, inside the image defined in image
section.
Just run docker-compose up
, and see it working. Here is the Tasker repo with the full documentation:
http://github.com/opsxcq/tasker
VonC's answer is pretty thorough. In addition I'd like to add one thing that helped me. If you just want to run a cron job without tailing a file, you'd be tempted to just remove the && tail -f /var/log/cron.log
from the cron command.
However this will cause the Docker container to exit shortly after running because when the cron command completes, Docker thinks the last command has exited and hence kills the container. This can be avoided by running cron in the foreground via cron -f
.
I created a Docker image based on the other answers, which can be used like
docker run -v "/path/to/cron:/etc/cron.d/crontab" gaafar/cron
where /path/to/cron
: absolute path to crontab file, or you can use it as a base in a Dockerfile:
FROM gaafar/cron
# COPY crontab file in the cron directory
COPY crontab /etc/cron.d/crontab
# Add your commands here
For reference, the image is here.
Though this aims to run jobs beside a running process in a container via Docker's exec
interface, this may be of interest for you.
I've written a daemon that observes containers and schedules jobs, defined in their metadata, on them. Example:
version: '2'
services:
wordpress:
image: wordpress
mysql:
image: mariadb
volumes:
- ./database_dumps:/dumps
labels:
deck-chores.dump.command: sh -c "mysqldump --all-databases > /dumps/dump-$$(date -Idate)"
deck-chores.dump.interval: daily
'Classic', cron-like configuration is also possible.
Here are the docs, here's the image repository.
When you deploy your container on another host, just note that it won't start any processes automatically. You need to make sure that 'cron' service is running inside your container. In our case, I am using Supervisord with other services to start cron service.
[program:misc]
command=/etc/init.d/cron restart
user=root
autostart=true
autorestart=true
stderr_logfile=/var/log/misc-cron.err.log
stdout_logfile=/var/log/misc-cron.out.log
priority=998
Define the cronjob in a dedicated container which runs the command via docker exec to your service.
This is higher cohesion and the running script will have access to the environment variables you have defined for your service.
#docker-compose.yml
version: "3.3"
services:
myservice:
environment:
MSG: i'm being cronjobbed, every minute!
image: alpine
container_name: myservice
command: tail -f /dev/null
cronjobber:
image: docker:edge
volumes:
- /var/run/docker.sock:/var/run/docker.sock
container_name: cronjobber
command: >
sh -c "
echo '* * * * * docker exec myservice printenv | grep MSG' > /etc/crontabs/root
&& crond -f"
Cron jobs are stored in /var/spool/cron/crontabs (Common place in all distros I Know). BTW, You can create a cron tab in bash using something like that:
crontab -l > cronexample
echo "00 09 * * 1-5 echo hello" >> cronexample
crontab cronexample
rm cronexample
This will create a temporary file with cron task, then program it using crontab. Last line remove temporary file.
When running on some trimmed down images that restrict root access, I had to add my user to the sudoers and run as sudo cron
FROM node:8.6.0
RUN apt-get update && apt-get install -y cron sudo
COPY crontab /etc/cron.d/my-cron
RUN chmod 0644 /etc/cron.d/my-cron
RUN touch /var/log/cron.log
# Allow node user to start cron daemon with sudo
RUN echo 'node ALL=NOPASSWD: /usr/sbin/cron' >>/etc/sudoers
ENTRYPOINT sudo cron && tail -f /var/log/cron.log
Maybe that helps someone
So, my problem was the same. The fix was to change the command section in the docker-compose.yml
.
From
command: crontab /etc/crontab && tail -f /etc/crontab
To
command: crontab /etc/crontab
command: tail -f /etc/crontab
The problem was the '&&' between the commands. After deleting this, it was all fine.
The most robust way I found so far is run an independent cron container - install the docker client and bind mount the docker sock so you can talk to the docker server on the host.
Then just use env vars for each cron job and an entrypoint script to generate the /etc/crontab
Here is an image that I created using this principle and using it in production for the last 3-4 years.
https://www.vip-consult.solutions/post/better-docker-cron#content
Try using clockwork gem to schedule tasks. Follow the steps provided in this link.
You can call the rake task inside lib/clock.rb file as below.
every(1.day, 'Import large data from csv files', :at => '5:00') do |job|
`rake 'portal:import_data_from_csv'`
end
Create a separate container in docker-compose file & run the below command inside the container.
command: bundle exec clockwork lib/clock.rb
참고URL : https://stackoverflow.com/questions/37458287/how-to-run-a-cron-job-inside-a-docker-container
'IT story' 카테고리의 다른 글
Vim 전문가가 왜 탭보다 버퍼를 선호합니까? (0) | 2020.05.07 |
---|---|
Font Awesome not working, 사각형으로 표시되는 아이콘 (0) | 2020.05.07 |
시간 지연으로 작업을 반복 하시겠습니까? (0) | 2020.05.07 |
현재 메뉴 항목을 강조 표시하는 방법 (0) | 2020.05.07 |
node.js 전역 변수? (0) | 2020.05.07 |