Saat menjalankan project menggunakan Docker, aplikasi tidak langsung berjalan dari folder lokal seperti pada setup biasa.

Docker membaca konfigurasi project, menyiapkan image yang dibutuhkan, lalu menjalankan setiap service sebagai container yang saling terhubung.

docker-lokal-flow.png

Memahami Alur pada Gambar

Pada gambar tersebut, proses dimulai dari project lokal yang berisi source code, Dockerfile, dan compose.yaml.

Docker kemudian membangun atau mengambil image yang dibutuhkan. Setiap image dijalankan menjadi container, lalu container aplikasi berkomunikasi dengan PostgreSQL dan Redis melalui network Docker.

Data PostgreSQL disimpan di volume agar tetap tersedia ketika container dibuat ulang.

Pada gambar tersebut, project memiliki tiga service utama:

  • Aplikasi
  • PostgreSQL sebagai database
  • Redis sebagai cache atau penyimpanan session

Setiap service berjalan dalam container yang berbeda, tetapi tetap dapat berkomunikasi melalui network Docker.

1. Project Lokal

Proses dimulai dari project yang berada di komputer developer.

Beberapa file yang biasanya digunakan:

project/
├── source-code/
├── Dockerfile
├── compose.yaml
├── .dockerignore
└── .env
File Fungsi
Dockerfile Instruksi untuk membangun image aplikasi
compose.yaml Mendefinisikan service, port, network, dan volume
.dockerignore Mengecualikan file tertentu dari proses build
.env Menyimpan konfigurasi lokal

Tidak semua service membutuhkan Dockerfile. PostgreSQL dan Redis biasanya menggunakan image yang sudah tersedia.

2. Docker Membaca Compose

Saat command berikut dijalankan:

docker compose up -d --build

Docker Compose membaca service yang didefinisikan dalam compose.yaml.

Contoh sederhananya:

services:
  app:
    build: .
    ports:
      - "8080:80"

  database:
    image: postgres:16

  redis:
    image: redis:7-alpine

Dari konfigurasi tersebut, Docker mengetahui bahwa project membutuhkan tiga service:

  • app
  • database
  • redis

Compose kemudian meminta Docker Engine menyiapkan image, network, volume, dan container yang dibutuhkan.

3. Docker Menyiapkan Image

Image adalah paket atau template yang digunakan untuk membuat container.

Image dapat disiapkan melalui dua cara.

Build dari Dockerfile

Image aplikasi biasanya dibangun menggunakan Dockerfile:

FROM php:8.3-fpm

WORKDIR /var/www/html

COPY . .

Dockerfile dapat berisi:

  • Base image
  • Runtime aplikasi
  • Dependency
  • Source code
  • Konfigurasi sistem
  • Command awal aplikasi

Mengambil Image yang Sudah Tersedia

Service seperti PostgreSQL dan Redis biasanya menggunakan image yang sudah tersedia:

database:
  image: postgres:16

redis:
  image: redis:7-alpine

Jika image belum tersedia di komputer, Docker akan mengambilnya dari registry.

4. Image Dijalankan Menjadi Container

Image dan container merupakan dua hal yang berbeda.

Dockerfile → build → image → run → container

Image adalah template yang bersifat tetap, sedangkan container adalah instance dari image yang sedang atau pernah dijalankan.

Satu image juga dapat digunakan untuk membuat beberapa container:

App Image
├── App Container 1
├── App Container 2
└── App Container 3

Perubahan di dalam container tidak otomatis memperbarui image. Jika isi image perlu diubah, image harus dibangun ulang.

5. Source Code Dihubungkan dengan Bind Mount

Saat development, source code biasanya tetap diedit dari komputer menggunakan editor seperti Visual Studio Code.

Folder project kemudian dihubungkan ke container melalui bind mount:

services:
  app:
    volumes:
      - ./:/var/www/html

Alurnya:

Edit source code di komputer
    ↓
Bind mount meneruskan perubahan
    ↓
Source code di container ikut berubah
    ↓
Perubahan dapat diuji di browser

Dengan bind mount, image tidak perlu dibangun ulang setiap kali source code berubah.

Build ulang biasanya diperlukan jika terjadi perubahan pada:

  • Dockerfile
  • Runtime aplikasi
  • Dependency sistem
  • Ekstensi PHP
  • Konfigurasi build image

6. Container Terhubung Melalui Network

Docker Compose biasanya membuat network khusus untuk project secara otomatis.

Container dapat saling terhubung menggunakan nama service, bukan localhost.

Contoh konfigurasi aplikasi:

DB_HOST=database
DB_PORT=5432
REDIS_HOST=redis
REDIS_PORT=6379

Nama database dan redis berasal dari nama service dalam compose.yaml.

Dari dalam container aplikasi, localhost menunjuk ke container aplikasi itu sendiri. Karena itu, koneksi menuju database harus menggunakan nama service database.

App Container
├── database:5432 → PostgreSQL Container
└── redis:6379    → Redis Container

7. Port Membuka Akses dari Komputer

Agar aplikasi dapat dibuka dari browser, port container perlu dipublikasikan.

services:
  app:
    ports:
      - "8080:80"

Konfigurasi tersebut berarti:

localhost:8080 → port 80 di dalam container

Aplikasi kemudian dapat dibuka melalui:

http://localhost:8080

Port sebelah kiri adalah port komputer, sedangkan port sebelah kanan adalah port di dalam container.

8. Volume Menyimpan Data

Container dapat dihentikan, dihapus, dan dibuat ulang. Karena itu, data penting tidak sebaiknya hanya disimpan di filesystem container.

Database biasanya menggunakan named volume:

services:
  database:
    image: postgres:16
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Alurnya:

PostgreSQL Container
    ↓
Docker Volume
    ↓
Data tetap tersedia saat container dibuat ulang

Container database dapat dibuat ulang, tetapi datanya tetap berada di volume.

Perlu diperhatikan bahwa command berikut dapat menghapus volume Compose:

docker compose down -v

Jika database menggunakan volume tersebut, data lokal dapat ikut terhapus.

Alur Lengkapnya

Saat docker compose up -d --build dijalankan, proses sederhananya adalah:

  1. Docker Compose membaca compose.yaml.
  2. Image aplikasi dibangun dari Dockerfile.
  3. Image PostgreSQL dan Redis diambil jika belum tersedia.
  4. Docker menyiapkan network dan volume.
  5. Setiap image dijalankan menjadi container.
  6. Container aplikasi terhubung dengan PostgreSQL dan Redis.
  7. Port aplikasi dibuka agar dapat diakses melalui localhost.
  8. Data database disimpan di volume.

Kesimpulan

Docker memisahkan kebutuhan project menjadi beberapa service yang berjalan dalam container masing-masing.

Image digunakan sebagai template, container menjalankan service, network menghubungkan antar-container, port membuka akses dari komputer, dan volume menjaga data agar tetap tersimpan.

Dengan struktur tersebut, environment development lebih mudah dibuat ulang dan tidak terlalu bergantung pada konfigurasi manual di setiap komputer.