---
title: "Cara Menjalankan Tugas Terjadwal di Dalam Container Docker"
description: "Pilihan menjalankan cron untuk aplikasi Docker, dari cron di host, supercronic di container, sampai Ofelia, plus jebakan zona waktu dan variabel env."
url: "https://nivelva.com/insight/cara-menjalankan-tugas-terjadwal-container-docker"
category: "Server \u0026 Infrastruktur"
tags: ["docker","cron","supercronic","ofelia","penjadwalan"]
author: "Lucas Tan"
published: "2026-11-11T13:27:00+07:00"
updated: "2026-11-11T13:27:00+07:00"
language: "id"
publisher: "Nivelva (https://nivelva.com)"
---

# Cara Menjalankan Tugas Terjadwal di Dalam Container Docker

> **Jawaban singkat:** Ada tiga cara umum menjadwalkan tugas untuk aplikasi Docker, yaitu cron atau systemd timer di host yang memanggil docker exec, supercronic di dalam container, atau container penjadwal seperti Ofelia. Hindari cron bawaan di dalam container karena variabel env dan log mudah hilang.

Tugas terjadwal di dunia container adalah pekerjaan yang berjalan pada waktu tertentu, misalnya membersihkan sesi tiap jam, mengirim laporan harian, atau menjalankan `php artisan schedule:run` setiap menit. Di server biasa cukup menambah satu baris crontab. Di Docker, pertanyaannya jadi lebih rumit: cron itu dijalankan di mana?

Salah pilih bisa membuat tugas diam-diam tidak berjalan selama berminggu-minggu. Penyebabnya klasik: variabel lingkungan tidak terbaca, log tidak terlihat di `docker logs`, atau jam di container berbeda dengan jam yang kamu kira.

## Kenapa cron biasa sering gagal di dalam container?

Memasang paket `cron` ke dalam image lalu menjalankannya terdengar sederhana. Masalahnya, cron dirancang untuk server penuh, bukan container:

- Cron membersihkan variabel lingkungan sebelum menjalankan tugas. Konfigurasi yang kamu kirim lewat `ENV` di Dockerfile atau `docker run -e`, seperti alamat database, tidak sampai ke tugas.
- Keluaran tugas biasanya dikirim lewat email lokal atau dibuang, bukan ke stdout. Akibatnya `docker logs` sepi walau tugasnya error.
- Container hanya punya satu proses utama. Kalau cron menjadi proses utama, aplikasinya butuh container lain. Kalau aplikasi yang menjadi proses utama, cron harus dijalankan dengan pengelola proses tambahan.
- Saat container dihentikan, cron bawaan bisa meninggalkan tugas yang sedang berjalan tanpa penutupan yang rapi.

Poin pertama, kedua, dan keempat inilah yang disebut di dokumentasi supercronic sebagai alasan proyek itu dibuat.

## Apa saja cara yang lebih rapi?

| Cara | Di mana jadwal ditulis | Kelebihan | Kekurangan |
|:--|:--|:--|:--|
| Cron atau systemd timer di host | Crontab host atau unit timer | Sederhana, tanpa image tambahan | Jadwal terpisah dari kode aplikasi |
| Supercronic di container | File crontab di dalam image | Env terbaca, log ke stdout, ikut versi image | Perlu container atau proses khusus |
| Container penjadwal (Ofelia) | Label di docker-compose | Jadwal menempel di definisi layanan | Butuh akses ke Docker socket |

### Cron atau systemd timer di host

Cara paling lugas: biarkan host yang mengatur jadwal, lalu jalankan perintah di container yang sudah hidup.

```cron
*/5 * * * * docker exec app-web-1 php artisan schedule:run >> /var/log/app-cron.log 2>&1
0 2 * * * cd /opt/app && docker compose run --rm worker python laporan_harian.py
```

`docker exec` menjalankan perintah di container yang sedang berjalan, sehingga variabel lingkungannya ikut terpakai. `docker compose run --rm` membuat container sekali pakai yang otomatis dihapus setelah selesai, cocok untuk tugas berat yang tidak boleh mengganggu container web.

Cara menulis jadwalnya sama dengan crontab biasa, lihat [contoh cron job di Linux](https://nivelva.com/insight/cron-job-linux). Kalau ingin log yang lebih rapi dan bisa melihat kapan tugas terakhir berjalan, [systemd timer](https://nivelva.com/insight/cara-memakai-systemd-timer-sebagai-pengganti-cron) adalah alternatif yang baik.

Kekurangannya, jadwal hidup di server, bukan di repository. Saat pindah server, crontab mudah terlupa.

### Supercronic di dalam container

Supercronic adalah penjalan tugas yang kompatibel dengan format crontab dan dirancang khusus untuk container. Tugas mewarisi variabel lingkungan container, keluaran dan error dikirim ke stdout dan stderr, dan sinyal SIGTERM ditangani dengan penutupan yang rapi.

Pola yang umum adalah satu image untuk dua layanan: web dan penjadwal.

```yaml
services:
  web:
    image: registry.contoh.co.id/app:1.4.0
    env_file: .env
  jadwal:
    image: registry.contoh.co.id/app:1.4.0
    env_file: .env
    command: ["supercronic", "/app/crontab"]
    environment:
      TZ: Asia/Jakarta
```

Isi `/app/crontab` memakai format crontab biasa, misalnya `0 2 * * * python laporan_harian.py`. Binary supercronic diunduh dari halaman rilis resmi di GitHub saat build image. Verifikasi checksum-nya sesuai petunjuk di halaman rilis. Gunakan juga `supercronic -test /app/crontab` di tahap build untuk memastikan sintaks crontab benar tanpa menjalankan tugasnya.

### Ofelia sebagai container penjadwal

Ofelia berjalan sebagai container terpisah yang membaca label di container lain, lalu menjalankan perintah sesuai jadwal. Contoh dari dokumentasinya memakai label seperti ini:

```yaml
services:
  web:
    image: registry.contoh.co.id/app:1.4.0
    labels:
      ofelia.enabled: "true"
      ofelia.job-exec.bersih-sesi.schedule: "@every 1h"
      ofelia.job-exec.bersih-sesi.command: "php artisan session:clean"
  ofelia:
    image: mcuadros/ofelia:latest
    command: daemon --docker
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    depends_on:
      - web
```

Perintah `session:clean` di atas hanya contoh. Ganti dengan perintah aplikasimu.

Perhatikan format jadwalnya. Ofelia memakai format cron versi Go, dan menurut README-nya, versi 0.3.x mewajibkan kolom detik di depan, sedangkan versi 0.4.x menjadikannya opsional. Bentuk `@every 1h` aman di keduanya. Selalu cek versi image yang kamu pakai sebelum menulis jadwal lima atau enam kolom.

> **Docker socket setara akses root:**
>
> Container yang memegang /var/run/docker.sock bisa membuat container baru dengan hak penuh atas host, walaupun socket dipasang read-only. Pakai Ofelia hanya dari image yang kamu percaya, kunci versinya, dan jangan pernah membuka container ini ke jaringan publik.

## Kapan memilih yang mana?

Pilih cron atau systemd timer di host kalau server hanya menjalankan satu atau dua aplikasi, tim kecil, dan kamu ingin sesedikit mungkin komponen tambahan. Ini juga pilihan paling mudah di-debug.

Pilih supercronic kalau jadwal adalah bagian dari aplikasi dan harus ikut versi kode. Deploy di server mana pun langsung membawa jadwalnya, tanpa perlu mengedit crontab host.

Pilih Ofelia kalau banyak layanan di satu host dan kamu ingin jadwal terlihat di file compose, dekat dengan layanan yang dijadwalkan, dengan menerima risiko akses Docker socket.

## Bagaimana mencegah tugas berjalan dobel?

Apa pun pilihanmu, pastikan hanya ada satu penjadwal untuk satu tugas. Kalau aplikasi di-scale menjadi tiga container web dan masing-masing punya cron sendiri, tugas harian akan berjalan tiga kali. Itu sebabnya penjadwal sebaiknya berupa layanan terpisah dengan satu replika saja.

Masalah kedua adalah tugas yang belum selesai saat jadwal berikutnya tiba. Untuk cron di host, bungkus perintah dengan `flock`, misalnya `flock -n /tmp/laporan.lock docker compose run --rm worker python laporan_harian.py`, sehingga tugas kedua langsung batal bila yang pertama masih berjalan. Di dalam aplikasi, banyak framework juga menyediakan kunci serupa untuk tugas terjadwal.

## Bagaimana mengatasi jam yang meleset?

Image dasar umumnya memakai UTC. Tugas "jam 2 pagi" bisa berjalan pukul 09.00 WIB. Atur variabel `TZ=Asia/Jakarta` di container penjadwal (pastikan paket `tzdata` ada di image), atau tulis jadwal dalam UTC dengan sengaja dan beri komentar. Untuk cron di host, jadwal mengikuti zona waktu host, yang bisa dicek dengan `timedatectl`.

## Pertanyaan yang sering diajukan

### Bisakah cron dijalankan bersama aplikasi dalam satu container?

Bisa dengan pengelola proses seperti supervisord, tapi cara ini membuat container lebih sulit dipantau. Container terpisah untuk penjadwal biasanya lebih rapi.

### Bagaimana melihat apakah tugas sudah berjalan?

Dengan supercronic atau Ofelia, cek docker logs pada container penjadwal. Dengan cron host, arahkan keluaran ke file log atau pakai systemd timer lalu baca journalctl.

### Apakah tugas yang berjalan lama aman saat deploy?

Belum tentu. Saat container dihentikan, tugas yang sedang berjalan ikut menerima sinyal stop. Jadwalkan deploy di luar jam tugas berat atau buat tugas yang aman diulang.

### Mana yang paling hemat sumber daya?

Cron di host tidak menambah container apa pun. Supercronic dan Ofelia menambah satu proses kecil, umumnya tidak signifikan dibanding aplikasi itu sendiri.

## Sumber

- <https://github.com/aptible/supercronic>
- <https://github.com/mcuadros/ofelia>
- <https://docs.docker.com/reference/cli/docker/container/exec/>

---

Diterbitkan oleh Nivelva Insight (https://nivelva.com/insight/). Artikel ini: https://nivelva.com/insight/cara-menjalankan-tugas-terjadwal-container-docker
Kontak Nivelva: WhatsApp https://wa.me/6285111245007, email hello@nivelva.com
