Saya mencoba untuk menjalankan cronjob di dalam kontainer docker yang memanggil shell script.
Kemarin saya telah mencari seluruh web dan stack overflow, tapi aku tidak bisa benar-benar menemukan solusi yang bekerja. Bagaimana saya bisa melakukan ini?
EDIT:
I've menciptakan (berkomentar) repositori github dengan bekerja docker cron wadah yang memanggil shell script pada interval tertentu.
Anda dapat menyalin crontab ke dalam gambar, dalam rangka untuk wadah diluncurkan dari kata gambar untuk menjalankan pekerjaan.
Lihat "Jalankan cron job dengan Docker" dari Julien Boulay di Ekito/docker-cron
:
Mari kita buat file baru yang disebut "
halo-cron
" untuk menggambarkan pekerjaan kita.
* * * * * 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.
berikut Dockerfile menjelaskan semua langkah-langkah untuk membangun gambar anda
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
(lihat Gaafar's komentar dan Bagaimana cara membuat apt-get
install kurang bising?:
apt-get -y install-qq --force-ya cron
dapat pekerjaan juga)
ATAU, pastikan pekerjaan anda sendiri redirect langsung ke stdout/stderr bukan dari file log, seperti yang dijelaskan dalam hugoShaka's jawaban:
* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2
Mengganti terakhir Dockerfile line dengan
CMD ["cron", "-f"]
Lihat juga (tentang cron -f
, yang adalah untuk mengatakan cron "foreground") "docker ubuntu cron -f
tidak bekerja"
Membangun dan menjalankan ini:
sudo docker build --rm -t ekito/cron-example .
sudo docker run -t -i ekito/cron-example
bersabar, tunggu selama 2 menit dan anda commandline harus menampilkan:
Hello world
Hello world
perhatikan bahwa
ekor
tidak dapat menampilkan file yang benar jika itu dibuat selama membangun gambar. Jika itu terjadi, anda perlu membuat atau menyentuh file pada wadah runtime dalam rangka untuk ekor untuk mengambil file yang benar.
Lihat "Output tail -f
pada akhir docker CMD
tidak menunjukkan".
Mengadopsi solusi mungkin berbahaya dalam lingkungan produksi.
Di docker anda hanya harus menjalankan satu proses per kontainer karena jika anda don't, proses yang bercabang dan pergi latar belakang ini tidak dipantau dan mungkin berhenti tanpa anda menyadarinya.
Ketika anda menggunakan CMD cron && tail -f /var/log/cron.log
cron proses pada dasarnya garpu dalam rangka melaksanakan cron
di latar belakang, proses utama keluar dan membiarkan anda menjalankan tailf
di latar depan. Latar belakang proses cron bisa berhenti atau gagal anda tidak't pemberitahuan, wadah anda masih akan berjalan diam-diam dan orkestrasi alat tidak akan restart.
Anda dapat menghindari hal seperti itu dengan mengarahkan langsung cron's perintah output ke docker
stdout
danstderr
yang terletak masing-masing di/proc/1/fd/1
dan/proc/1/fd/2
.
Menggunakan dasar shell mengarahkan anda mungkin ingin melakukan sesuatu seperti ini :
``
Dan anda CMD akan sama : CMD ["cron", " f"]
Bagi mereka yang ingin menggunakan sederhana dan ringan gambar:
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"]
Mana cronjobs adalah file yang berisi cronjobs, dalam bentuk ini:
* * * * * echo "hello stackoverflow" >> /test_file 2>&1
# remember to end this file with an empty new line
Apa yang @VonC telah menyarankan bagus tapi saya lebih suka melakukan semua pekerjaan cron konfigurasi dalam satu baris. Ini akan menghindari lintas platform isu-isu seperti cronjob lokasi dan anda don't perlu memisahkan file cron.
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
Setelah menjalankan anda docker container, anda dapat pastikan jika layanan cron bekerja dengan:
# 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"
Jika anda lebih memilih untuk memiliki ENTRYPOINT bukan CMD, kemudian anda dapat mengganti CMD di atas dengan
ENTRYPOINT cron start && tail -f /var/log/cron.log
Ada cara lain untuk melakukannya, adalah dengan menggunakan Tas, tugas pelari yang memiliki cron (scheduler) dukungan.
Mengapa ? Kadang-kadang untuk menjalankan cron job, anda harus mencampur, anda dan pilihan gambar (python, java, nodejs, ruby) dengan crond. Itu berarti gambar lain untuk mempertahankan. Tasker menghindari bahwa dengan menggabungkan crond dan wadah. Anda hanya bisa fokus pada gambar yang ingin anda mengeksekusi perintah-perintah-mu, dan mengkonfigurasi Tasker untuk menggunakannya.
Di sini sebuah docker-menulis.yml
file, yang akan menjalankan beberapa tugas untuk anda
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")'
Ada 3 tugas di sana, mereka semua akan berjalan setiap menit (setiap: menit
), dan masing-masing dari mereka akan mengeksekusi script
code, dalam gambar yang ditetapkan dalam image
bagian.
Hanya menjalankan docker-menulis-up
, dan melihatnya bekerja. Berikut ini adalah Tasker repo dengan dokumentasi lengkap:
VonC's jawabannya adalah cukup menyeluruh. Selain I'd ingin menambahkan satu hal yang membantu saya. Jika anda hanya ingin menjalankan cron job tanpa tailing file, anda'd tergoda untuk hanya menghapus && tail -f /var/log/cron.log
dari perintah cron.
Namun hal ini akan menyebabkan kontainer Docker untuk keluar tak lama setelah berjalan karena ketika perintah cron selesai, Docker berpikir perintah terakhir yang telah keluar dan karenanya membunuh wadah. Hal ini dapat dihindari dengan menjalankan cron di latar depan melalui cron -f
.
Saya membuat sebuah gambar Docker berdasarkan jawaban yang lain, yang dapat digunakan seperti
docker run-v "/path/ke/cron:/etc/cron.d/crontab" gaafar/cron
di mana /path/ke/cron
: absolute path ke file crontab, atau anda dapat menggunakannya sebagai dasar dalam Dockerfile:
FROM gaafar/cron
# COPY crontab file in the cron directory
COPY crontab /etc/cron.d/crontab
# Add your commands here
Untuk referensi, gambar di sini.
Meskipun ini bertujuan untuk menjalankan pekerjaan di samping proses yang berjalan dalam sebuah wadah melalui Docker's exec
antarmuka, ini mungkin menarik untuk anda.
I've menulis sebuah daemon yang mengamati wadah dan jadwal pekerjaan, yang didefinisikan dalam metadata mereka, pada mereka. Contoh:
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
'Klasik', cron konfigurasi seperti ini juga mungkin.
Berikut ini adalah docs, di sini's image repository.
Ketika anda menggunakan kontainer anda di host lain, hanya diketahui bahwa itu tidak't memulai setiap proses secara otomatis. Anda perlu memastikan bahwa 'cron' layanan berjalan di dalam wadah. Dalam kasus kami, saya menggunakan Supervisord dengan layanan lain untuk memulai layanan 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
Menentukan cronjob di kontainer khusus yang menjalankan perintah melalui docker exec untuk layanan anda.
Ini lebih tinggi kohesi dan menjalankan script akan memiliki akses ke variabel lingkungan yang telah ditetapkan untuk layanan anda.
#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"
Jadi, masalah saya adalah sama. Perbaikan itu untuk mengubah perintah bagian dalam docker-menulis.yml
.
Dari
perintah: crontab /etc/crontab && tail -f /etc/crontab
Untuk
perintah: crontab /etc/crontab
perintah: tail -f /etc/crontab
The masalah adalah '&&' antara perintah. Setelah menghapus ini, itu semua baik-baik saja.
Ketika berjalan pada beberapa terpangkas gambar yang membatasi akses root, saya harus menambahkan pengguna ke sudoers dan dijalankan sebagai 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
Mungkin itu membantu seseorang
Cron jobs disimpan di /var/spool/cron/crontabs (tempat Umum di semua distro yang saya Tahu). BTW, Anda bisa membuat cron tab di bash menggunakan sesuatu seperti itu:
crontab -l > cronexample
echo "00 09 * * 1-5 echo hello" >> cronexample
crontab cronexample
rm cronexample
Hal ini akan menciptakan sebuah file sementara dengan tugas cron, maka program ini menggunakan crontab. Baris terakhir menghapus file sementara.
Cobalah menggunakan jarum jam permata untuk menjadwalkan tugas-tugas. Ikuti langkah-langkah yang disediakan di link ini.
Anda dapat menghubungi menyapu tugas dalam lib/jam.rb file seperti di bawah ini.
every(1.day, 'Import large data from csv files', :at => '5:00') do |job|
`rake 'portal:import_data_from_csv'`
end
Membuat wadah terpisah di docker-menulis file & menjalankan perintah di bawah ini di dalam wadah.
command: bundle exec clockwork lib/clock.rb
Yang paling kuat cara yang saya temukan sejauh ini berjalan independen cron wadah - install docker klien dan mengikat gunung docker kaus kaki sehingga anda dapat berbicara dengan docker server pada host.
Kemudian hanya menggunakan env var untuk setiap cron job dan entrypoint script untuk menghasilkan /etc/crontab
Berikut adalah gambar yang saya buat menggunakan prinsip ini dan menggunakannya dalam produksi selama 3-4 tahun terakhir.
https://www.vip-consult.solutions/post/better-docker-cron#content