Eu sunt încercarea de a rula un cronjob în interiorul unui container docker care invocă un script de shell.
Ieri am cautat peste tot pe web și stack overflow, dar nu am putut găsi într-adevăr o soluție care funcționează. Cum pot face asta?
EDIT:
Am'am creat o (comentat) depozit github cu un lucru docker cron container care invocă un script de shell la interval dat.
Puteți copia crontab într-o imagine, în scopul de pentru container lansat de spus imagine pentru a rula de locuri de muncă.
A se vedea "Rula un cron job cu Docker" din Julien Boulay în Ekito/docker-cron
:
Să creeze un nou fișier numit " alo-cron`" pentru a descrie slujba noastră.
* * * * * 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.
următoarele Dockerfile descrie toti pasii pentru a construi imaginea dvs.
FROM ubuntu:latest
MAINTAINER [email protected]
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
(a se vedea Gaafar's comentariu și Cum fac apt-get
instala mai puțin zgomotos?:
de apt-get -y install -qq --force-da cron
poate lucra, de asemenea)
SAU, asigurați-vă că locul de muncă în sine redirecționa în mod direct la stdout/stderr în loc de un fișier jurnal, așa cum este descris în hugoShaka's răspunde:
* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2
Înlocuiți ultimul Dockerfile conformitate cu
CMD ["cron", "-f"]
A se vedea, de asemenea, (despre cron -f, care este de a spune cron "prim-plan") "[docker ubuntu
cron -f` nu este de lucru]9"
Construi și rula:
sudo docker build --rm -t ekito/cron-example .
sudo docker run -t -i ekito/cron-example
aveți răbdare, așteptați timp de 2 minute și commandline ar trebui să afișeze:
Hello world
Hello world
Eric adauga în comentarii:
Nu act de faptul că "coada" nu poate afișa corect fișier dacă acesta este creat în timpul construi imaginea. Dacă acesta este cazul, aveți nevoie pentru a crea sau atingeți fișierul în recipient de execuție, în scopul de coada pentru a ridica fișierului corectă.
A se vedea "Ieșire de `tail-f la sfârșitul unui docher "CMD", nu dă".
Solutia adoptata poate fi periculos într-un mediu de producție.
În docker ar trebui doar să execute o procesul per recipient pentru că dacă tu nu't, proces care bifurcată și s-a dus de fundal nu este monitorizată și se poate opri fără să știe el.
Când utilizați CMD cron && tail-f /var/log/cron.log
cron proces practic furculiță în scopul de a executa cron
în fond, procesul principal ieșirile și să te execute tailf
în prim-plan. Fundal cron proces ar putea opri sau nu ai câștigat't observa, containerul va rula în continuare în tăcere și orchestrație instrument nu va reporni.
puteți evita un astfel de lucru prin redirecționarea direct cron's comenzi de ieșire în docker
stdout " și "stderr
care sunt situate, respectiv, în/proc/1/fd/1" și " /proc/1/fd/2
.
Folosind coajă de bază redirecționări poate vrei sa faci ceva de genul asta :
``
Și CMD va fi : CMD ["cron", " f"]
Pentru cei care vrea să se folosească de un simplu și ușor de imagine:
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"]
Unde cronjobs este fișierul care conține cronjobs, în această formă:
* * * * * echo "hello stackoverflow" >> /test_file 2>&1
# remember to end this file with an empty new line
Ce @VonC a sugerat este frumos, dar eu prefer de a face toate de locuri de muncă cron configurare într-o singură linie. Acest lucru ar evita cross-platform probleme, cum ar fi cronjob locație și don't nevoie de o separat cron fișier.
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
După rularea docker container, puteți să vă asigurați dacă cron service este de lucru prin:
# 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"
Dacă preferați să aveți ENTRYPOINT în loc de CMD, apoi puteți înlocui CMD-ul de mai sus cu
ENTRYPOINT cron start && tail -f /var/log/cron.log
Nu există un alt mod de a o face, este de a folosi Tasker, o sarcină alergător care a cron (un scheduler) de sprijin.
De ce ? Uneori, pentru a rula un loc de muncă cron, trebuie să se amestecă, imaginea ta (python, java, nodejs, ruby), cu crond. Asta înseamnă că o altă imagine pentru a menține. Tasker evita ca prin decuplarea crond și recipient. Vă puteți concentra doar pe imaginea pe care doriți pentru a executa comenzi și să configurați Tasker să-l folosească.
Aici un docher-compune.yml` de fișier, care va rula unele sarcini pentru tine
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")'
Există 3 sarcini de acolo, toate acestea vor rula în fiecare minut (la fiecare: minute), și fiecare dintre ele va executa
script` cod, în interiorul imaginii definite în "imagine" secțiune.
Doar rula `docker-compune în sus, și vedea de lucru. Aici este Tasker repo cu documentația completă:
VonC's răspunsul este destul de temeinică. În plus, am'd dori să adaug un lucru care m-a ajutat. Dacă doriți doar pentru a rula un loc de muncă cron fără decantare un fișier,'d fi tentat să eliminați doar `&& tail-f /var/log/cron.jurnal de comanda cron.
Cu toate acestea, acest lucru va provoca Docker container pentru a ieși la scurt timp după rularea pentru că atunci când comanda cron completeaza, Docker crede că ultima comandă a ieșit și, prin urmare, îl ucide pe recipient. Acest lucru poate fi evitat prin rularea cron în prim-plan prin cron -f
.
Am creat un Docher de imagine bazat pe alte răspunsuri, care pot fi folosite ca
docker run-v "/path/to/cron:/etc/cron.d/crontab" gaafar/cron
unde /path/to/cron
: calea absolută la fișierul crontab, sau îl puteți folosi ca o bază într-o Dockerfile:
FROM gaafar/cron
# COPY crontab file in the cron directory
COPY crontab /etc/cron.d/crontab
# Add your commands here
Pentru referință, imaginea aici.
Deși acest lucru are scopul de a rula de locuri de muncă alături de un proces care rulează într-un recipient prin intermediul Docker's "exec" interfață, acest lucru poate fi de interes pentru tine.
Am'am scris un daemon care observă containere și programe de locuri de muncă, definite în metadatele lor, pe ele. Exemplu:
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
'Clasic', cron-cum ar fi de configurare este, de asemenea, posibil.
Aici sunt documente, aici's depozitul de imagine.
Când implementați container de pe un alt host, doar să rețineți că nu o't de a începe orice mod automat procesele de periculoase. Ai nevoie să vă asigurați că 'cron' serviciul se execută în interiorul containerului. În cazul nostru, eu sunt, folosind Supervisord cu alte servicii pentru a începe serviciul cron.
[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
Defini cronjob într-un container dedicat care ruleaza comanda prin docker exec la serviciu.
Acest lucru este mai mare de coeziune și rularea script-ul va avea acces la variabilele de mediu le-ați definit pentru dvs. de servicii.
#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"
Deci, problema mea a fost la fel. Fix a fost de a modifica secțiunea de comandă în docker-compune.yml`.
La
comanda: crontab /etc/crontab && tail-f /etc/crontab
Pentru
comanda: crontab /etc/crontab
comanda: tail-f /etc/crontab
La problema **** a fost '&&' între comenzi. După ștergerea asta, totul a fost bine.
Atunci când rulează pe unele împodobite jos imagini care restricționează accesul root, am avut de a adăuga meu de utilizator la sudoers și a alerga ca 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
Poate că ajută pe cineva
Cron de locuri de muncă sunt stocate în /var/spool/cron/crontabs (loc Comun în toate distributii Stiu). BTW, puteți crea un cron tab în bash, folosind ceva de genul asta:
crontab -l > cronexample
echo "00 09 * * 1-5 echo hello" >> cronexample
crontab cronexample
rm cronexample
Acest lucru va crea un fișier temporar cu sarcină cron, atunci programul folosind crontab. Ultima linie a elimina fișierul temporar.
Încercați să utilizați un ceas bijuterie pentru a programa sarcini. Urmați pașii din acest link.
Puteți apela rake sarcină în interiorul lib/ceas.rb fișierul de mai jos.
every(1.day, 'Import large data from csv files', :at => '5:00') do |job|
`rake 'portal:import_data_from_csv'`
end
A crea un recipient separat în docker-compune fișiere & executați comanda de mai jos în interiorul containerului.
command: bundle exec clockwork lib/clock.rb
Cel mai robust cum l-am găsit până în prezent este condus de un independent cron container - a instala docker client și se leagă muntele docher ciorap astfel încât să puteți vorbi cu docker server pe host.
Apoi, utilizați doar env var pentru fiecare loc de muncă cron și o entrypoint script pentru a genera fișierul /etc/crontab
Aici este o imagine pe care am creat-o folosind acest principiu și folosind-o în producție pentru ultimii 3-4 ani.
https://www.vip-consult.solutions/post/better-docker-cron#content