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.

ContainerVirtual Machine
Berbagi kernel hostMemiliki kernel guest sendiri
Lebih ringanLebih berat
Startup cepatStartup relatif lebih lambat
Cocok untuk packaging aplikasiCocok untuk virtualisasi OS
Resource overhead relatif kecilResource 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 8080 berada di VPS.
  • Port 80 berada 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 RunDocker Compose
Cocok untuk container sederhanaCocok untuk multi-container application
Command lebih panjangKonfigurasi tersimpan di file
Sulit dikelola jika service banyakLebih mudah dikelola
Bagus untuk testing sederhanaCocok 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

AspekInstalasi LangsungDocker
Setup awalSederhana untuk aplikasi kecilMembutuhkan pemahaman Docker
IsolationLebih rendahLebih baik
ReproducibilityLebih sulitLebih mudah
Multi-serviceDapat menjadi rumitLebih terstruktur
PortabilityTergantung konfigurasi hostLebih mudah dipindahkan
MaintenanceBerbasis hostBerbasis 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

CommandFungsi
docker psMelihat container yang berjalan
docker ps -aMelihat semua container
docker imagesMelihat image
docker pullMengambil image
docker runMembuat dan menjalankan container
docker stopMenghentikan container
docker startMenjalankan container yang berhenti
docker restartRestart container
docker rmMenghapus container
docker rmiMenghapus image
docker logsMelihat log container
docker execMenjalankan command dalam container
docker statsMelihat penggunaan resource
docker compose upMenjalankan application stack
docker compose downMenghentikan 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.