DocsInfrastruktur
Docker Swarm
Menjalankan aplikasi sebagai service dengan replika di beberapa mesin, memakai orkestrator yang sudah ada di Docker — tanpa Kubernetes.
- Untuk apa
- Beberapa mesin di bawah satu panel
- Bentuk
- Aplikasi sebagai service + replika
- Siapa
- Owner (init/leave/node), admin melihat status
Swarm atau server remote?
| Server remote (SSH) | Swarm | |
|---|---|---|
| Bentuk | Panel mengendalikan daemon lain lewat SSH | Satu cluster; scheduler Docker yang menempatkan task |
| Aplikasi | Satu container di server yang dipilih | N replika yang bisa tersebar di beberapa node |
| Domain | Proxy per server (atau port host) | Traefik di manager dengan swarm provider |
| Cocok untuk | Lingkungan terpisah, region berbeda | Menambah kapasitas untuk aplikasi yang sama |
Keduanya bisa dipakai bersamaan: host aoox menjadi manager swarm, sementara server remote tetap melayani aplikasi lain secara terpisah.
Alur
- 01inithost jadi manager, overlay aoox-swarm dibuat
- 02joinnode lain bergabung dengan token dari panel
- 03serviceaplikasi diubah ke Mode deploy service + replika
- 04rollingdaemon mengganti task bertahap, rollback bila gagal
Mengaktifkan swarm
Settings → Docker Swarm → Init swarm (owner)
Isi Advertise address bila host punya lebih dari satu IP — alamat inilah yang dipakai node lain untuk menghubungi manager. Kosongkan untuk deteksi otomatis.
aoox menjadikan daemon host sebagai manager, membuat overlay network
aoox-swarmyang bisa di-attach, memasukkan proxy dan managed database ke sana, lalu mengaktifkan swarm provider Traefik.Gabungkan node lain
Kartu Swarm menampilkan perintah join lengkap dengan token — jalankan di mesin yang akan bergabung (Docker sudah terpasang, port
2377,7946, dan4789/udpterbuka antar node):docker swarm join --token SWMTKN-1-… <ip-manager>:2377Token worker dan manager berbeda; token hanya ditampilkan kepada owner. Node yang bergabung muncul di daftar node beberapa detik kemudian.
Pastikan registry terjangkau dari node lain
Node menarik image sendiri dari registry lokal. Status swarm memperingatkan bila
REGISTRY_PUBLIC_HOSTmasihlocalhost— node lain tidak bisa menariknya. Set ke hostname/IP yang terjangkau (dengan TLS atauinsecure-registries) — lihat Registry.
Node lewat VPN (WireGuard)
Node di jaringan berbeda bisa digabung lewat terowongan VPN sehingga port swarm tidak terbuka ke internet. Atur ini saat init swarm:
- Advertise address = IP tunnel manager (mis.
10.99.0.1). Port kontrol2377lalu hanya mendengarkan di alamat itu; Listen address menimpanya. Tanpa alamat apa pun, port tetap terbuka di semua interface. - MTU overlay = MTU tunnel,
1420untuk WireGuard default. Docker mengurangi 50 untuk header VXLAN, jadi container mendapat1370. Tanpa ini overlay mengira jaringannya 1500 (container 1450), dan paket yang lebih besar terbuang di dalam tunnel. - Port
2377/tcp,7946, dan4789/udpcukup terjangkau lewat tunnel. Di worker, join dengan--advertise-addr <ip-tunnel> --listen-addr <ip-tunnel>:2377.
MTU ditetapkan saat jaringan overlay dibuat: untuk mengubahnya di swarm yang sudah ada, kembalikan aplikasi ke mode container, keluar dari swarm, lalu inisialisasi ulang.
Mengelola node
| Aksi | Efek |
|---|---|
| Availability: active | Node menerima task baru. |
| Availability: pause | Task yang ada tetap jalan; tidak menerima task baru. |
| Availability: drain | Task dipindahkan ke node lain — dipakai sebelum maintenance. |
| Role: manager / worker | Promosikan atau turunkan node. Jumlah manager ganjil (1, 3, 5) agar kuorum aman. |
| Label | Pasangan key=value, mis. zone=eu — dipakai sebagai constraint penempatan. |
| Hapus node | Ditolak (409) bila node masih aktif; drain dulu, lalu hapus. Di node itu jalankan docker swarm leave. |
Aplikasi sebagai service
Di Pengaturan aplikasi, ubah Mode deploy dari container ke service:
| Field | Keterangan |
|---|---|
| Replika | Jumlah task yang dijalankan. Stop = skala ke 0; Start mengembalikannya. |
| Penempatan | Node tertentu, atau constraint bebas (node.labels.zone==eu, node.role==worker, node.hostname, node.platform.os). |
| Rolling update | Paralelisme (berapa task diganti sekaligus), jeda antar batch, dan urutan (start-first / stop-first). |
- Pergantian mode, replika, penempatan, atau limit dijalankan sebagai deployment
config— tanpa build, dan tidak memblokir request. - Daemon melakukan rolling update sendiri; bila task baru tidak pernah jalan sampai batas waktu, spec lama dikembalikan dan aplikasi tetap melayani.
- Aplikasi yang punya mount selalu ditempatkan di host tempat volumenya berada — volume Docker tidak ikut berpindah node.
- Deploy ulang yang identik tetap memicu rolling update (
ForceUpdate), jadi tombol Deploy selalu berefek.
Yang perlu diketahui tentang task
| Aspek | Di mode service |
|---|---|
| Log | Semua task, dari node mana pun. |
| Metrik | Dijumlahkan dari task yang berjalan di host — Engine API tidak bisa membaca task di node lain. |
| Job & terminal exec | Hanya task lokal. |
| Notifikasi | Watcher memberi tahu bila service bertahan di bawah jumlah replika (task yang tidak pernah start), dan watcher lain melaporkan task yang crash di node lain dalam sekitar 30 detik. |
| Domain | Traefik swarm provider merutekan ke service, bukan ke container. |
Keluar dari swarm
docker swarm leave sendiri.postgres dan mati. Begitu keluar, jalankan ini di server; semua container aoox menyala lagi sendiri:sudo systemctl restart dockerJebakan umum
| Gejala | Penyebab & solusi |
|---|---|
| Task pending: no suitable node | Constraint tidak cocok dengan label node mana pun, atau aplikasi punya mount sehingga terkunci di host. Longgarkan penempatan. |
| Node lain: image pull failed / x509 | REGISTRY_PUBLIC_HOST masih localhost, registry tanpa TLS, atau node belum punya entri insecure-registries. |
| Service tidak pernah mencapai jumlah replika | Health check gagal atau resource kurang; rolling update di-rollback otomatis setelah timeout. Cek log task. |
| Metrik kosong untuk aplikasi di node lain | Sesuai batasan: metrik hanya dari task lokal. |
| Node hilang setelah reboot | Daemon node belum start, atau firewall menutup port swarm (2377/7946/4789). |
Langkah berikutnya
Ada yang keliru? Edit halaman ini di GitHub ↗