Menjalankan aplikasi Laravel secara langsung di komputer host membutuhkan beberapa dependency seperti PHP, Composer, extension PHP, web server, dan database.
Masalahnya, setiap komputer bisa memiliki versi dan konfigurasi yang berbeda. Akibatnya, aplikasi yang berjalan di satu komputer belum tentu langsung berjalan di komputer lain.
Docker Compose membantu membuat environment aplikasi secara lebih konsisten. Pada artikel ini, kita akan menjalankan Laravel 10 menggunakan:
Laravel 10 membutuhkan PHP minimal versi 8.1 serta beberapa extension seperti Ctype, cURL, DOM, Fileinfo, Mbstring, OpenSSL, PDO, Tokenizer, dan XML.[1]
Pada praktik ini kita akan membuat dua service:
Browser
|
| localhost:8000
v
Laravel App Container
|
| Docker Compose Network
v
MySQL Database Container
Struktur service-nya:
app
└── Laravel 10
├── PHP 8.2
└── Apache
db
└── MySQL 8.0
Service Laravel menggunakan Apache sebagai web server. Pendekatan ini lebih sederhana untuk pembelajaran dibandingkan memisahkan Nginx dan PHP-FPM ke dalam dua container berbeda.
Catatan: Konfigurasi pada artikel ini ditujukan untuk development dan lab. Deployment production membutuhkan konfigurasi tambahan seperti HTTPS, secret management, logging, backup, dan hardening.
Pastikan Ubuntu 24.04 sudah tersedia. Docker Engine secara resmi mendukung Ubuntu 24.04 LTS dengan codename Noble.[2]
Pastikan Docker Engine, Docker Compose, dan Git sudah terpasang:
docker --version
docker compose version
git --version
Docker Compose modern menggunakan command:
docker compose
Bukan:
docker-compose
Docker mendokumentasikan instalasi Compose Plugin pada Linux melalui package docker-compose-plugin dan verifikasinya menggunakan docker compose version.[3]
Jika Docker belum terpasang, ikuti dokumentasi resmi:
Install Docker Engine on Ubuntu
Artikel ini mengasumsikan Anda sudah memiliki project Laravel 10. Project tersebut dapat berasal dari repository Git.
Contoh:
git clone YOUR_REPOSITORY_URL laravel-docker
cd laravel-docker
Jika ingin membuat project Laravel 10 baru menggunakan Composer:
composer create-project "laravel/laravel:^10.0" laravel-docker
cd laravel-docker
Laravel mendokumentasikan penggunaan Composer untuk membuat project Laravel dengan batasan versi ^10.0.[4]
Pastikan isi project Laravel terlihat seperti berikut:
laravel-docker/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
├── resources/
├── routes/
├── storage/
├── .env.example
├── artisan
├── composer.json
└── composer.lock
Buat file bernama Dockerfile di root project:
FROM php:8.2-apache
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN apt-get update \
&& apt-get install -y \
git \
unzip \
libzip-dev \
libonig-dev \
&& docker-php-ext-install \
pdo_mysql \
mbstring \
bcmath \
exif \
pcntl \
zip \
&& a2enmod rewrite \
&& rm -rf /var/lib/apt/lists/*
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
RUN sed -ri \
-e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' \
/etc/apache2/sites-available/000-default.conf \
/etc/apache2/apache2.conf
WORKDIR /var/www/html
COPY . .
RUN composer install \
--no-interaction \
--prefer-dist \
--optimize-autoloader \
&& chown -R www-data:www-data \
storage \
bootstrap/cache
EXPOSE 80
FROM php:8.2-apache
Menggunakan image PHP 8.2 dengan Apache. PHP 8.2 dipilih karena masih memenuhi requirement minimal Laravel 10, yaitu PHP 8.1 atau lebih baru.[1]
RUN apt-get install
Memasang package Linux yang diperlukan saat proses build image.
docker-php-ext-install
Image PHP Official menyediakan helper script seperti docker-php-ext-configure, docker-php-ext-install, dan docker-php-ext-enable untuk memasang extension PHP.[5]
Extension yang dipasang pada contoh ini antara lain:
pdo_mysql untuk koneksi Laravel ke MySQLmbstring untuk pemrosesan string multibytebcmath untuk operasi matematikaexif untuk metadata gambarpcntl untuk kebutuhan proses tertentuzip untuk dependency ComposerENV APACHE_DOCUMENT_ROOT=/var/www/html/public
Laravel harus dilayani dari folder public, bukan dari root project. Hal ini mencegah file internal seperti .env ikut terekspos oleh web server.[1]
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
Menyalin executable Composer dari image Composer ke image aplikasi.
composer install
Memasang dependency Laravel berdasarkan composer.json dan composer.lock.
Untuk deployment production, Laravel merekomendasikan optimasi autoloader dan menghilangkan dependency development menggunakan:
composer install --optimize-autoloader --no-dev
[1]
Pada artikel ini kita menggunakan konfigurasi development/lab agar proses belajar tetap sederhana.
.dockerignoreAgar file yang tidak diperlukan tidak ikut masuk ke build context, buat file .dockerignore:
.git
.env
vendor
node_modules
storage/logs/*
File .env sengaja tidak dimasukkan ke image karena berisi konfigurasi environment dan dapat berisi credential. Laravel juga menyarankan agar .env tidak disimpan di source control.[4][6]
.envSalin file environment example:
cp .env.example .env
Kemudian edit file .env:
nano .env
Sesuaikan bagian database menjadi:
APP_NAME=Laravel
APP_ENV=local
APP_KEY=***
APP_URL=http://localhost:8000
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=***
Tambahkan variable password root MySQL untuk kebutuhan Docker Compose:
DB_ROOT_PASSWORD=YOUR_ROOT_PASSWORD
Gunakan password berbeda saat menjalankan aplikasi sebenarnya. Nilai pada contoh ini hanya placeholder.
DB_HOST menggunakan db?Pada file Compose nanti, nama service database adalah:
db:
Docker Compose menyediakan network internal dan resolusi nama berdasarkan nama service. Karena itu Laravel dapat mengakses database melalui hostname:
DB_HOST=db
Jangan menggunakan:
DB_HOST=localhost
Di dalam container Laravel, localhost menunjuk ke container Laravel itu sendiri, bukan ke container MySQL.
Buat file compose.yaml:
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: laravel_app
ports:
- "8000:80"
env_file:
- .env
volumes:
- ./.env:/var/www/html/.env
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.0
container_name: laravel_db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE:-laravel}
MYSQL_USER: ${DB_USERNAME:-laravel}
MYSQL_PASSWORD: ${DB_PASSWORD:-YOUR_DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-YOUR_ROOT_PASSWORD}
volumes:
- db_data:/var/lib/mysql
healthcheck:
test:
[
"CMD",
"mysqladmin",
"ping",
"-h",
"localhost",
"-u",
"root",
"-p${DB_ROOT_PASSWORD:-YOUR_ROOT_PASSWORD}"
]
interval: 10s
timeout: 5s
retries: 10
volumes:
db_data:
Compose Specification menyediakan format untuk mendefinisikan service, environment, volume, dependency, dan konfigurasi aplikasi multi-container.[7]
appapp:
build:
context: .
dockerfile: Dockerfile
Compose akan membuat image menggunakan Dockerfile pada directory project saat ini.
ports:
- "8000:80"
Mapping tersebut berarti:
Port host 8000 → Port container 80
Aplikasi dapat diakses melalui:
http://localhost:8000
Jika port 8000 sudah digunakan, Anda dapat menggantinya:
ports:
- "8080:80"
Aplikasi kemudian diakses melalui:
http://localhost:8080
.envvolumes:
- ./.env:/var/www/html/.env
Mount ini membuat file .env pada host digunakan oleh Laravel di dalam container. Dengan begitu, ketika php artisan key:generate dijalankan, perubahan APP_KEY tersimpan pada file .env di project host.
dbimage: mysql:8.0
Menggunakan MySQL 8.0 dari Docker Official Image. Image MySQL mendukung konfigurasi database dan credential melalui environment variable.[8]
volumes:
- db_data:/var/lib/mysql
Named volume digunakan agar data database tetap tersimpan ketika container dihentikan atau dibuat ulang.
Database tidak selalu langsung siap menerima koneksi ketika container baru saja dijalankan. Karena itu service db diberi healthcheck.
Service app menunggu database berada pada status healthy:
depends_on:
db:
condition: service_healthy
depends_on membantu mengatur dependency service, tetapi aplikasi tetap perlu menangani kemungkinan database belum siap pada kondisi tertentu.
Sebelum build, validasi konfigurasi Compose:
docker compose config
Jika tidak ada error, periksa kembali service yang terbaca:
docker compose config --services
Output yang diharapkan:
app
db
Build image aplikasi:
docker compose build
Kemudian jalankan service di background:
docker compose up -d
Option -d menjalankan container secara detached atau background.[9]
Periksa status container:
docker compose ps
Contoh status yang diharapkan:
NAME SERVICE STATUS
laravel_app app running
laravel_db db healthy
Nama dan format output dapat berbeda tergantung versi Docker Compose.
APP_KEYSetelah container aplikasi aktif, jalankan:
docker compose exec app php artisan key:generate
Command tersebut menjalankan Artisan di dalam service app.
Periksa file .env:
grep APP_KEY .env
Seharusnya sekarang APP_KEY sudah memiliki nilai.
Jangan membagikan isi APP_KEY atau melakukan commit file .env ke repository publik.
Jalankan migration Laravel:
docker compose exec app php artisan migrate
Jika database belum siap, tunggu beberapa saat lalu ulangi command tersebut:
docker compose exec app php artisan migrate
Periksa konfigurasi database Laravel:
docker compose exec app php artisan about
Laravel menyediakan command Artisan untuk membantu melihat informasi aplikasi dan environment.
Buka browser dan akses:
http://localhost:8000
Jika berhasil, halaman default Laravel akan tampil.
Anda juga dapat memeriksa response HTTP menggunakan curl:
curl -I http://localhost:8000
Contoh response yang diharapkan:
HTTP/1.1 200 OK
Untuk melihat log aplikasi:
docker compose logs -f app
Untuk melihat log database:
docker compose logs -f db
Option -f membuat log terus mengikuti output terbaru.
Tekan Ctrl+C untuk berhenti melihat log. Container tetap berjalan karena yang dihentikan hanya proses monitoring log pada terminal.
Untuk membuka shell pada container aplikasi:
docker compose exec app bash
Setelah masuk, Anda dapat memeriksa versi PHP:
php -v
Memeriksa extension:
php -m
Memeriksa versi Laravel:
php artisan --version
Keluar dari container:
exit
docker compose exec memang digunakan untuk menjalankan command pada service Compose yang sedang aktif.[5]
docker compose stop
Perintah ini menghentikan container tanpa menghapusnya.
docker compose start
docker compose restart
docker compose down
Perintah ini menghapus container dan network yang dibuat Compose.[10]
Named volume database biasanya tetap ada jika tidak menggunakan option -v.
docker compose down -v
Warning: Jangan menggunakan
docker compose down -vjika masih membutuhkan data MySQL. Named volume database akan ikut dihapus.
Periksa proses yang menggunakan port:
sudo ss -tulpn | grep :8000
Atau ubah mapping pada compose.yaml:
ports:
- "8080:80"
Kemudian jalankan ulang:
docker compose up -d
Pastikan konfigurasi .env seperti berikut:
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=***
Jangan gunakan localhost sebagai DB_HOST.
Periksa status database:
docker compose ps
Lihat log database:
docker compose logs db
APP_KEY belum tersediaJalankan:
docker compose exec app php artisan key:generate
Jika Laravel masih membaca konfigurasi lama:
docker compose exec app php artisan config:clear
Laravel menjelaskan bahwa configuration cache dapat menyebabkan perubahan .env tidak langsung terbaca. config:cache sebaiknya digunakan sebagai bagian dari deployment production, bukan saat konfigurasi development sering berubah.[6]
Periksa log:
docker compose logs app
Periksa status semua service:
docker compose ps -a
Jika terdapat perubahan pada Dockerfile, rebuild image:
docker compose build --no-cache
docker compose up -d
Pastikan folder berikut dapat ditulis oleh web server:
storage/
bootstrap/cache/
Pada Dockerfile, permission awal sudah disiapkan menggunakan:
RUN chown -R www-data:www-data storage bootstrap/cache
Jika permission berubah setelah proses development, periksa owner folder dari dalam container:
docker compose exec app ls -ld storage bootstrap/cache
Periksa status health database:
docker compose ps
Jika status database belum healthy, lihat log:
docker compose logs -f db
Tunggu sampai MySQL selesai melakukan initialization, lalu jalankan ulang:
docker compose exec app php artisan migrate
Konfigurasi pada artikel ini digunakan untuk lab. Untuk production, perhatikan hal-hal berikut:
.env.APP_DEBUG=true di production.APP_KEY.Laravel menggunakan .env untuk konfigurasi yang dapat berbeda antar-environment. File tersebut sebaiknya tidak dimasukkan ke source control.[6]
Pada artikel ini kita sudah menjalankan Laravel 10 menggunakan Docker Compose dengan dua service:
app → Laravel 10 + PHP 8.2 + Apache
db → MySQL 8.0
Alur utamanya adalah:
cp .env.example .env
docker compose config
docker compose build
docker compose up -d
docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate
Aplikasi kemudian dapat diakses melalui:
http://localhost:8000
Dengan Docker Compose, dependency Laravel dan database dijalankan dalam container yang terpisah tetapi tetap dapat berkomunikasi melalui network internal Compose.
Langkah lanjutan yang dapat dipelajari:
[1] Laravel 10 Deployment Documentation
[2] Docker Engine — Install on Ubuntu
[3] Install the Docker Compose Plugin on Linux
[4] Laravel 10 Installation Documentation
[6] Laravel 10 Configuration Documentation
[7] Docker Compose File Reference
[8] Official MySQL Docker Image