Docker di Ubuntu VPS: Apa Itu Container dan Kenapa Berguna untuk Server?
Ketika aplikasi mulai berkembang, menjalankannya langsung di Ubuntu VPS sering membuat konfigurasi server menjadi semakin kompleks. Web server, PHP, database, Redis, queue worker, Node.js, dan berbagai dependency harus dipasang serta dikonfigurasi satu per satu.
Masalah lain muncul ketika aplikasi berjalan dengan baik di komputer developer tetapi mengalami error setelah dipindahkan ke server. Perbedaan versi PHP, library, konfigurasi sistem, extension, atau dependency dapat menyebabkan aplikasi tidak berjalan seperti yang diharapkan.
Docker hadir untuk membantu mengatasi masalah tersebut.
Dengan Docker, aplikasi dan dependency-nya dapat dikemas ke dalam sebuah container. Container kemudian dapat dijalankan di Ubuntu VPS dengan environment yang lebih konsisten.
Artikel ini membahas konsep dasar Docker di Ubuntu VPS, mulai dari container, image, volume, network, hingga alasan Docker sangat berguna untuk deployment aplikasi di server.
Apa Itu Docker?
Docker adalah platform untuk membuat, menjalankan, dan mengelola aplikasi dalam container.
Secara sederhana, Docker memungkinkan kita mengatakan:
Aplikasi
+ Dependency
+ Runtime
+ Configuration
↓
Docker Image
↓
Container
↓
Ubuntu VPS
Daripada menginstal semua dependency aplikasi langsung ke operating system, sebagian besar kebutuhan aplikasi dapat dikemas ke dalam image Docker.
Container kemudian dibuat dari image tersebut.
Apa Itu Container?
Container adalah lingkungan terisolasi yang digunakan untuk menjalankan aplikasi beserta dependency yang dibutuhkan.
Misalnya sebuah aplikasi Laravel membutuhkan:
- PHP
- PHP extensions
- Composer
- Nginx
- Redis
- database
Tanpa Docker, semua komponen tersebut dapat dipasang langsung di VPS.
Dengan Docker, komponen dapat dipisahkan menjadi beberapa container.
Ubuntu VPS
│
├── Nginx Container
│
├── Laravel/PHP Container
│
├── Redis Container
│
└── Database Container
Setiap container memiliki tanggung jawab yang berbeda.
Container Bukan Virtual Machine
Container sering dibandingkan dengan virtual machine, tetapi keduanya tidak sama.
| Container | Virtual Machine |
|---|---|
| Berbagi kernel host | Memiliki kernel guest sendiri |
| Lebih ringan | Lebih berat |
| Startup cepat | Startup relatif lebih lambat |
| Cocok untuk packaging aplikasi | Cocok untuk virtualisasi OS |
| Resource overhead relatif kecil | Resource overhead lebih besar |
Gambaran sederhananya:
Virtual Machine:
VPS/Physical Server
│
├── Hypervisor
│ ├── VM 1 → Guest OS
│ ├── VM 2 → Guest OS
│ └── VM 3 → Guest OS
Container:
VPS/Physical Server
│
├── Docker Engine
│ ├── Container A
│ ├── Container B
│ └── Container C
Container biasanya jauh lebih ringan karena tidak menjalankan operating system lengkap untuk setiap aplikasi.
Kenapa Docker Berguna di Ubuntu VPS?
Ada beberapa alasan Docker sangat berguna untuk server.
1. Environment Lebih Konsisten
Salah satu masalah deployment klasik adalah perbedaan environment.
Misalnya aplikasi dikembangkan menggunakan PHP versi tertentu, tetapi VPS menggunakan versi PHP berbeda.
Development
PHP 8.x
MySQL versi tertentu
Redis
Extension tertentu
↓ deploy
Production
PHP versi berbeda
MySQL berbeda
Extension belum tersedia
↓
Aplikasi bermasalah
Dengan Docker, environment aplikasi dapat didefinisikan secara lebih eksplisit melalui Dockerfile dan konfigurasi container.
2. Dependency Lebih Terisolasi
Tanpa container, dua aplikasi dalam satu VPS dapat saling membutuhkan versi dependency yang berbeda.
VPS
│
├── App A
│ └── PHP version A
│
└── App B
└── PHP version B
Situasi seperti ini dapat menjadi rumit jika kedua aplikasi bergantung pada versi runtime yang berbeda.
Dengan container:
VPS
│
├── Container App A
│ └── Runtime A
│
└── Container App B
└── Runtime B
Masing-masing aplikasi dapat memiliki environment yang lebih terisolasi.
3. Deployment Lebih Terstruktur
Docker membuat deployment dapat dilakukan berdasarkan image yang sama.
Developer
│
├── Dockerfile
└── Source Code
│
↓
Docker Image
│
↓
Registry
│
↓
Ubuntu VPS
│
↓
Container
Dengan pendekatan tersebut, server tidak harus dikonfigurasi secara manual dari awal setiap kali aplikasi dideploy.
4. Mudah Menjalankan Banyak Service
Sebuah aplikasi modern sering tidak hanya terdiri dari satu proses.
Contohnya:
- Laravel
- Nginx
- MySQL
- Redis
- Queue worker
- Scheduler
Docker dapat digunakan untuk memisahkan service-service tersebut.
Application Stack
│
├── nginx
├── app
├── queue
├── scheduler
├── mysql
└── redis
Pengelolaan beberapa container biasanya menjadi lebih mudah menggunakan Docker Compose.
Docker Image vs Container
Dua istilah yang sangat penting dalam Docker adalah image dan container.
Docker Image
Image adalah template yang digunakan untuk membuat container.
Contohnya:
Docker Image
│
├── Base OS / filesystem
├── Runtime
├── Libraries
├── Application dependency
└── Application files
Image bersifat immutable sebagai konsep dasar. Ketika image digunakan untuk membuat container, container tersebut menjadi instance yang berjalan dari image.
Docker Container
Container adalah instance yang sedang berjalan dari sebuah image.
Image
│
├── Container A
├── Container B
└── Container C
Satu image dapat digunakan untuk membuat beberapa container.
Mengenal Dockerfile
Dockerfile adalah file yang berisi instruksi untuk membangun Docker image.
Contoh sederhana:
FROM php:8.3-cli
WORKDIR /app
COPY . .
CMD ["php", "-S", "0.0.0.0:8000", "-t", "public"]
Dockerfile tersebut menggunakan image PHP sebagai base, menentukan working directory, menyalin source code, lalu menjalankan PHP built-in server.
FROM, WORKDIR, COPY, dan CMD
FROM
Menentukan base image.
FROM php:8.3-cli
WORKDIR
Menentukan direktori kerja di dalam container.
WORKDIR /app
COPY
Menyalin file dari build context ke image.
COPY . .
CMD
Menentukan command default ketika container dijalankan.
CMD ["php", "-S", "0.0.0.0:8000", "-t", "public"]
Instalasi Docker di Ubuntu VPS
Untuk server production, sebaiknya gunakan dokumentasi resmi Docker dan repository resmi yang sesuai dengan versi Ubuntu yang digunakan.
Setelah Docker terinstal, periksa versinya:
docker --version
Kemudian periksa apakah Docker dapat digunakan:
docker run hello-world
Jika berhasil, Docker akan menjalankan container sederhana yang menampilkan pesan konfirmasi.
Memahami Docker Daemon dan Docker CLI
Ketika menjalankan command seperti:
docker ps
kita sebenarnya berinteraksi dengan Docker melalui command-line interface.
Secara sederhana:
Docker CLI
│
↓
Docker Engine
│
↓
Containers / Images / Networks / Volumes
Docker Engine bertanggung jawab terhadap proses container di server.
Melihat Container
Untuk melihat container yang sedang berjalan:
docker ps
Untuk melihat semua container termasuk yang sudah berhenti:
docker ps -a
Contoh hasil secara konsep:
CONTAINER ID IMAGE STATUS
a12b34c56d78 nginx Up
b23c45d67e89 redis Up
c34d56e78f90 mysql Up
Menjalankan Container
Contoh menjalankan Nginx:
docker run -d --name web nginx
Parameter -d berarti container berjalan di background.
Parameter --name memberikan nama container.
Container dapat dihentikan dengan:
docker stop web
Dan dijalankan kembali:
docker start web
Port Mapping
Container memiliki network namespace sendiri. Agar service di dalam container dapat diakses melalui port VPS, kita dapat melakukan port mapping.
docker run -d \
--name web \
-p 8080:80 \
nginx
Format:
HOST_PORT:CONTAINER_PORT
Dalam contoh tersebut:
- Port
8080berada di VPS. - Port
80berada di container.
Sehingga request ke port 8080 VPS dapat diteruskan ke Nginx pada port 80 di container.
Docker Volume
Container pada dasarnya bersifat ephemeral. Data yang hanya disimpan di writable layer container tidak sebaiknya dianggap sebagai penyimpanan permanen.
Untuk data yang harus bertahan ketika container dibuat ulang, gunakan volume atau mekanisme persistent storage lainnya.
Contoh membuat volume:
docker volume create app_data
Melihat volume:
docker volume ls
Volume sangat penting untuk service seperti database.
Container MySQL
│
↓
Docker Volume
│
↓
Persistent Data
Dengan volume, lifecycle container dapat dipisahkan dari lifecycle data.
Kenapa Database Tidak Boleh Bergantung pada Container?
Container dapat dihentikan, dihapus, dan dibuat kembali.
Data database harus memiliki lifecycle yang berbeda.
Contohnya:
Container
│
├── MySQL process
│
└── /var/lib/mysql
│
↓
Docker Volume
Jika container MySQL dihapus tetapi volume tetap ada, data masih dapat digunakan oleh container baru yang menggunakan volume tersebut.
Namun volume bukan pengganti backup. Database production tetap membutuhkan backup yang benar dan teruji.
Docker Network
Docker menyediakan network agar container dapat berkomunikasi satu sama lain.
Misalnya aplikasi Laravel membutuhkan Redis.
Laravel Container
│
│ redis:6379
↓
Redis Container
Dalam network Docker, aplikasi biasanya tidak perlu mengetahui IP container secara manual. Service name dapat digunakan sebagai hostname jika menggunakan network dan konfigurasi yang sesuai.
Mengapa Docker Compose Berguna?
Jika aplikasi hanya memiliki satu container, command docker run mungkin sudah cukup.
Namun aplikasi production biasanya memiliki beberapa service.
Misalnya:
Laravel
├── app
├── nginx
├── mysql
└── redis
Menjalankan semua container secara manual dapat menjadi merepotkan.
Docker Compose memungkinkan konfigurasi beberapa service ditulis dalam satu file.
Contoh docker-compose.yml
services:
app:
build:
context: .
container_name: laravel_app
nginx:
image: nginx:alpine
container_name: laravel_nginx
ports:
- "8080:80"
depends_on:
- app
redis:
image: redis:alpine
container_name: laravel_redis
Dengan konfigurasi tersebut, kita dapat mendefinisikan beberapa service dalam satu stack.
Perintah untuk menjalankan stack dapat menggunakan:
docker compose up -d
Untuk melihat service:
docker compose ps
Untuk menghentikan stack:
docker compose down
Docker Compose vs Docker Run
| Docker Run | Docker Compose |
|---|---|
| Cocok untuk container sederhana | Cocok untuk multi-container application |
| Command lebih panjang | Konfigurasi tersimpan di file |
| Sulit dikelola jika service banyak | Lebih mudah dikelola |
| Bagus untuk testing sederhana | Cocok untuk application stack |
Arsitektur Docker di Ubuntu VPS
Contoh arsitektur sederhana untuk aplikasi Laravel:
Internet
│
↓
Ubuntu VPS
│
┌──────┴──────┐
│ Docker │
│ Engine │
└──────┬──────┘
│
Docker Network
│
┌───────────────┼───────────────┐
↓ ↓ ↓
Nginx Laravel Redis
Container Container Container
│
↓
Database
Container
│
↓
Volume
Dalam deployment production, arsitektur dapat dibuat lebih kompleks dengan reverse proxy, HTTPS, external database, monitoring, backup, registry, dan service lainnya.
Docker untuk Aplikasi Laravel
Docker sangat cocok digunakan untuk Laravel karena aplikasi Laravel biasanya membutuhkan beberapa komponen berbeda.
Contohnya:
- PHP-FPM untuk menjalankan aplikasi.
- Nginx sebagai web server.
- MySQL atau PostgreSQL sebagai database.
- Redis untuk cache dan queue.
- Queue worker untuk pekerjaan asynchronous.
- Scheduler untuk task terjadwal.
Arsitekturnya dapat terlihat seperti berikut:
Internet
│
↓
Nginx
│
↓
PHP-FPM
│
┌──────────┴──────────┐
↓ ↓
MySQL Redis
│
↓
Queue Worker
Pendekatan tersebut membuat setiap komponen memiliki tanggung jawab yang jelas.
Container untuk Queue Worker
Laravel queue worker adalah salah satu contoh service yang cocok dijalankan sebagai container terpisah.
php artisan queue:work
Daripada menjalankan worker langsung di host, worker dapat ditempatkan dalam container aplikasi.
Jika membutuhkan beberapa worker, jumlah container worker dapat ditingkatkan sesuai kebutuhan dan resource server.
Container untuk Laravel Scheduler
Laravel juga dapat memiliki task terjadwal.
Pendekatan deployment dapat memisahkan scheduler dari web application.
Laravel App
│
├── Web Request
│
├── Queue Worker
│
└── Scheduler
Pemisahan ini membantu pengelolaan resource dan lifecycle masing-masing proses.
Docker Image dari Docker Registry
Image tidak harus selalu dibangun langsung di VPS.
Dalam workflow CI/CD, image dapat dibangun terlebih dahulu kemudian disimpan pada container registry.
Git Repository
│
↓
CI/CD
│
↓
Build Docker Image
│
↓
Container Registry
│
↓
Ubuntu VPS
│
↓
docker pull
│
↓
Container
Pendekatan ini dapat membuat proses deployment lebih konsisten.
Docker Pull
Jika image tersedia di registry, server dapat mengambil image menggunakan:
docker pull nginx:alpine
Kemudian image tersebut dapat digunakan untuk membuat container.
Tag Image
Image biasanya memiliki tag.
docker pull nginx:alpine
Tag membantu menentukan varian image yang ingin digunakan.
Untuk deployment production, sebaiknya jangan sembarangan menggunakan tag yang selalu berubah tanpa memahami bagaimana image tersebut dikelola.
Lebih baik versioning image dibuat secara jelas sehingga deployment dapat direproduksi dan rollback lebih mudah.
Docker Logs
Salah satu keuntungan Docker adalah log container dapat diperiksa menggunakan Docker CLI.
docker logs nama-container
Untuk mengikuti log secara real-time:
docker logs -f nama-container
Ini sangat berguna ketika melakukan troubleshooting aplikasi di VPS.
Masuk ke Dalam Container
Untuk melakukan pemeriksaan manual, kita dapat menjalankan shell di dalam container.
docker exec -it nama-container sh
Jika image menyediakan Bash:
docker exec -it nama-container bash
Setelah masuk, kita dapat memeriksa file, environment, proses, atau konfigurasi di dalam container.
Environment Variable
Configuration aplikasi sebaiknya tidak ditulis secara hard-coded di image.
Docker mendukung environment variable.
docker run -d \
--name app \
-e APP_ENV=production \
-e APP_DEBUG=false \
my-app:latest
Untuk aplikasi Laravel, environment seperti database host, username, password, dan application key perlu dikelola dengan aman.
Jangan memasukkan secret production ke repository Git secara sembarangan.
Docker dan Keamanan Server
Docker bukan berarti server otomatis aman.
Beberapa aspek tetap perlu diperhatikan:
- Gunakan image yang terpercaya dan terawat.
- Update image secara berkala.
- Jangan menjalankan container dengan privilege yang tidak diperlukan.
- Batasi port yang dibuka ke internet.
- Gunakan firewall.
- Jangan mengekspos database ke internet tanpa alasan.
- Kelola secret dengan baik.
- Perhatikan permission volume.
- Monitor resource container.
Jangan Membuka Semua Port Container
Misalnya MySQL hanya diperlukan oleh aplikasi internal.
Tidak selalu diperlukan konfigurasi seperti:
ports:
- "3306:3306"
Jika database hanya perlu diakses oleh container lain dalam network Docker, database dapat tetap berada di internal network tanpa dipublish ke interface publik VPS.
Internet
│
↓
Nginx :443
│
↓
Application
│
├── MySQL internal
└── Redis internal
Ini merupakan prinsip penting: publish hanya service yang memang perlu diakses dari luar.
Docker Resource Limit
Container tetap menggunakan resource VPS.
Jika VPS hanya memiliki RAM kecil tetapi menjalankan terlalu banyak container, server tetap dapat mengalami kehabisan memory.
Karena itu, penggunaan Docker tidak menghilangkan kebutuhan untuk memahami:
- CPU
- RAM
- Disk
- Network
- Load average
Docker hanya membantu mengemas dan mengelola workload dengan lebih terstruktur.
Docker Tidak Menghilangkan Kebutuhan Monitoring
Server production tetap perlu dimonitor.
Contoh pemeriksaan dasar:
docker ps
docker stats
docker system df
docker stats dapat membantu melihat penggunaan resource container secara real-time.
Docker System Cleanup
Image lama, stopped container, dan resource Docker yang tidak lagi digunakan dapat memakan disk.
Pemeriksaan penggunaan storage dapat dilakukan dengan:
docker system df
Cleanup harus dilakukan dengan hati-hati, terutama pada server production. Jangan menghapus volume yang masih berisi data penting.
Docker Container Bersifat Disposable
Salah satu konsep penting dalam Docker adalah container sebaiknya diperlakukan sebagai sesuatu yang dapat dibuat dan dihancurkan kembali.
Contohnya:
Image
│
↓
Container
│
├── Running
│
└── Removed
│
↓
Create again
│
↓
New Container
Karena itu, data penting sebaiknya tidak hanya disimpan di filesystem internal container.
Container vs Data
Pemisahan lifecycle dapat digambarkan seperti ini:
Application Container
│
│ disposable
↓
Container lifecycle
Database Volume
│
│ persistent
↓
Data lifecycle
Ini adalah salah satu konsep terpenting ketika mulai menggunakan Docker untuk production.
Docker dan Reverse Proxy
Untuk aplikasi web production, sering kali Docker ditempatkan di belakang reverse proxy atau load balancer.
Contoh sederhana:
Internet
│
↓
Reverse Proxy / Nginx
│
↓
Docker Network
│
↓
Application Container
Reverse proxy dapat menangani HTTPS, routing domain, dan meneruskan request ke service internal.
Apakah Semua Aplikasi Harus Menggunakan Docker?
Tidak.
Docker adalah tool, bukan kewajiban.
Aplikasi sederhana yang hanya membutuhkan Nginx dan PHP mungkin dapat berjalan dengan baik tanpa Docker.
Docker menjadi semakin menarik ketika:
- aplikasi memiliki banyak dependency;
- terdapat beberapa service;
- development dan production perlu environment konsisten;
- deployment dilakukan berkali-kali;
- membutuhkan CI/CD;
- ingin memisahkan service;
- ingin mempermudah provisioning server.
Kapan Sebaiknya Tidak Menggunakan Docker?
Docker dapat menambah lapisan kompleksitas.
Untuk VPS yang sangat sederhana, menambahkan Docker, Compose, banyak container, dan konfigurasi network mungkin justru membuat sistem lebih sulit dipahami.
Jika sebuah aplikasi hanya membutuhkan satu service sederhana, deployment tradisional bisa menjadi pilihan yang masuk akal.
Yang penting adalah memilih arsitektur berdasarkan kebutuhan, bukan sekadar mengikuti tren.
Docker vs Instalasi Langsung di Ubuntu
| Aspek | Instalasi Langsung | Docker |
|---|---|---|
| Setup awal | Sederhana untuk aplikasi kecil | Membutuhkan pemahaman Docker |
| Isolation | Lebih rendah | Lebih baik |
| Reproducibility | Lebih sulit | Lebih mudah |
| Multi-service | Dapat menjadi rumit | Lebih terstruktur |
| Portability | Tergantung konfigurasi host | Lebih mudah dipindahkan |
| Maintenance | Berbasis host | Berbasis image/container |
Contoh Workflow Deployment Docker di VPS
Workflow sederhana dapat dibuat seperti berikut:
Developer
│
↓
Git Push
│
↓
Build Image
│
↓
Registry
│
↓
Ubuntu VPS
│
├── Pull Image
│
├── Stop/Replace Container
│
└── Start Container
│
↓
Production
Dengan CI/CD, proses tersebut dapat diotomatisasi lebih lanjut.
Contoh Struktur Project Docker
Project aplikasi dapat memiliki struktur seperti:
my-app/
├── app/
├── public/
├── Dockerfile
├── compose.yaml
├── .dockerignore
├── composer.json
└── .env.example
File .dockerignore dapat digunakan agar file yang tidak diperlukan tidak ikut dikirim ke build context.
Contoh .dockerignore
.git
.env
node_modules
vendor
storage/logs/*
Isi sebenarnya perlu disesuaikan dengan workflow build aplikasi.
Kesalahan Umum Saat Belajar Docker
1. Menganggap Container Sama dengan VPS
Container bukan pengganti VPS. Container berjalan di atas host atau environment container runtime.
2. Menyimpan Data Penting di Container
Data database sebaiknya menggunakan persistent storage dan backup.
3. Membuka Semua Port ke Internet
Publish port hanya jika memang diperlukan.
4. Menggunakan Image Tanpa Memahami Isinya
Image pihak ketiga perlu diperiksa sumber, maintenance, dan konfigurasi keamanannya.
5. Mengabaikan Resource VPS
Menjalankan banyak container tidak membuat resource VPS menjadi tidak terbatas.
6. Menggunakan Secret di Dockerfile
Credential dan secret production sebaiknya tidak ditulis langsung dalam Dockerfile atau source code.
Perintah Docker Dasar yang Perlu Diketahui
| Command | Fungsi |
|---|---|
docker ps | Melihat container yang berjalan |
docker ps -a | Melihat semua container |
docker images | Melihat image |
docker pull | Mengambil image |
docker run | Membuat dan menjalankan container |
docker stop | Menghentikan container |
docker start | Menjalankan container yang berhenti |
docker restart | Restart container |
docker rm | Menghapus container |
docker rmi | Menghapus image |
docker logs | Melihat log container |
docker exec | Menjalankan command dalam container |
docker stats | Melihat penggunaan resource |
docker compose up | Menjalankan application stack |
docker compose down | Menghentikan application stack |
Checklist Docker untuk Ubuntu VPS
- Docker Engine sudah terinstal.
- Docker Compose tersedia jika dibutuhkan.
- Image berasal dari sumber yang dapat dipercaya.
- Container memiliki konfigurasi yang jelas.
- Port publik dibatasi.
- Database menggunakan persistent storage.
- Backup database tersedia.
- Secret tidak disimpan sembarangan di repository.
- Log container dapat diperiksa.
- Resource VPS dimonitor.
- Image dan dependency diperbarui secara berkala.
- Deployment memiliki strategi rollback.
Kesimpulan
Docker memungkinkan aplikasi dijalankan dalam container yang terisolasi dan lebih mudah direproduksi. Untuk Ubuntu VPS, Docker sangat berguna ketika aplikasi mulai memiliki banyak dependency dan service seperti PHP, Nginx, Redis, database, queue worker, dan scheduler.
Konsep dasar yang perlu dipahami adalah hubungan antara image, container, volume, dan network.
Docker Image
│
↓
Container
│
├── Network
│
└── Volume
│
↓
Persistent Data
Image menjadi template aplikasi, container menjadi instance yang berjalan, network memungkinkan komunikasi antar-service, sedangkan volume digunakan untuk data yang perlu bertahan melewati lifecycle container.
Docker juga tidak otomatis membuat server menjadi aman atau scalable. Administrator tetap harus memahami firewall, HTTPS, authentication, backup, monitoring, resource management, dan keamanan image.
Untuk aplikasi sederhana, instalasi langsung di Ubuntu mungkin sudah cukup. Namun untuk application stack yang lebih kompleks, Docker dapat membuat deployment menjadi lebih konsisten, terisolasi, dan mudah dikelola.
