VPS • DOCKER • NGINX PROXY MANAGER • PHP

Pedoman Deploy Aplikasi PHP di VPS

Panduan praktis untuk deployment aplikasi PHP versi 7.4 maupun PHP 8+ menggunakan Docker dan Nginx Proxy Manager. Cocok untuk aplikasi native PHP, CodeIgniter, Laravel, API, dan aplikasi PHP lainnya.

1. Arsitektur yang Direkomendasikan

Pisahkan DNS, reverse proxy, container aplikasi, dan database agar mudah dikelola.

DNSSubdomain → Public IP VPS
Nginx Proxy ManagerPort 80/443 → container aplikasi
PHP ContainerApache/Nginx + PHP sesuai versi aplikasi
Internet
   │
   ├── DNS: app.domain.tld → PUBLIC_IP_VPS
   │
   ▼
Nginx Proxy Manager
   │ :80 / :443
   │
   ├── app-php74:80
   ├── app-php82:80
   └── app-php84:80
Prinsip penting DNS hanya mengarahkan domain ke IP VPS. Nginx Proxy Manager menentukan container mana yang menerima trafik berdasarkan domain/subdomain.

2. Persiapan VPS

1
Update OS
apt update && apt upgrade -y
2
Install utilitas dasar
apt install -y curl git nano unzip ca-certificates
3
Pastikan Docker tersedia
docker --version
docker compose version
4
Buat struktur aplikasi
mkdir -p /opt/apps
mkdir -p /opt/apps/proxy/nginx
mkdir -p /opt/apps/web
Firewall Buka minimal TCP 80 dan 443. Port aplikasi internal seperti 8080, 8081, atau port container tidak perlu dibuka ke Internet jika trafik masuk melalui Nginx Proxy Manager.

3. Membuat Container PHP

PHP 7.4 — contoh untuk aplikasi legacy

Dockerfile
FROM php:7.4-apache

RUN docker-php-ext-install mysqli pdo pdo_mysql

COPY ./src/ /var/www/html/

RUN chown -R www-data:www-data /var/www/html

EXPOSE 80

PHP 8.x — contoh aplikasi modern

Dockerfile
FROM php:8.3-apache

RUN docker-php-ext-install mysqli pdo pdo_mysql

COPY ./src/ /var/www/html/

RUN chown -R www-data:www-data /var/www/html

EXPOSE 80

Ganti 8.3 sesuai kebutuhan aplikasi. Jangan menaikkan versi PHP secara langsung pada aplikasi legacy tanpa menguji kompatibilitas dependency dan kode.

Build dan jalankan container

cd /opt/apps/web/nama-app

docker build -t nama-app-php74 .

docker run -d \
  --name nama-app-php74 \
  --restart unless-stopped \
  --network web \
  nama-app-php74
Catatan jaringan Jika Nginx Proxy Manager juga berada pada Docker network bernama web, container aplikasi harus terhubung ke network yang sama.

Verifikasi container

docker ps
docker inspect nama-app-php74
docker network inspect web

Pastikan container aplikasi terlihat pada bagian Containers di network web.

4. Konfigurasi Nginx Proxy Manager

Di Nginx Proxy Manager buat Proxy Host baru.

FieldIsi
Domain NamesContoh: tests.telpro5.org
Schemehttp
Forward Hostname / IPNama container, contoh test-php74
Forward Port80
Block Common ExploitsAktifkan
Websockets SupportAktifkan jika aplikasi membutuhkannya
docker network inspect web

Jika container bernama test-php74 berada pada network yang sama, Nginx Proxy Manager dapat meneruskan trafik ke test-php74:80. Tidak perlu mengekspos port container ke Internet.

Jangan lakukan ini kecuali memang diperlukan:
docker run -p 80:80 ...
Jika Nginx Proxy Manager sudah memakai port 80/443 pada VPS, mem-publish port yang sama dari container lain akan menimbulkan konflik.

5. DNS dan SSL

A. DNS

Buat record A pada DNS provider yang benar:

Type : A
Name : tests
Value: PUBLIC_IP_VPS
TTL  : 300 / 3600

Verifikasi:

dig +short tests.telpro5.org
dig @ns1.niagahoster.com tests.telpro5.org A
Perhatikan authoritative DNS Jika domain menggunakan nameserver ns1.niagahoster.com dan ns2.niagahoster.com, record harus dibuat pada DNS zone yang benar. Membuat record di panel DNS yang bukan authoritative tidak akan mengubah DNS publik.

B. SSL Let's Encrypt

Setelah DNS sudah mengarah ke VPS dan HTTP berhasil:

  1. Nginx Proxy Manager → Proxy Hosts.
  2. Edit domain/subdomain.
  3. Tab SSL → Request a new SSL Certificate.
  4. Pilih Let's Encrypt.
  5. Aktifkan Force SSL jika HTTP sudah normal.

Uji:

curl -I http://tests.telpro5.org
curl -I https://tests.telpro5.org
Jika muncul ERR_SSL_UNRECOGNIZED_NAME_ALERT Periksa apakah SSL certificate untuk hostname tersebut sudah dibuat, Proxy Host HTTPS sudah aktif, dan port 443 benar-benar menuju Nginx Proxy Manager. Jangan menguji HTTPS sebelum konfigurasi SSL selesai.

6. Database

Untuk MySQL/MariaDB, aplikasi sebaiknya menggunakan hostname service/container, bukan localhost, jika database berada di container terpisah.

DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=nama_database
DB_USERNAME=nama_user
DB_PASSWORD=password-kuat
Jika database berada di VPS host Gunakan konfigurasi yang memang sesuai dengan topologi server. Jangan membuka port database ke Internet tanpa kebutuhan dan pengamanan yang memadai.

7. Prosedur Deploy Aplikasi

1
Upload / clone source code
cd /opt/apps/web
git clone URL_REPOSITORY nama-app
cd nama-app
2
Siapkan environment
cp .env.example .env
nano .env
3
Build image
docker build -t nama-app-php74 .
4
Hubungkan ke network proxy
docker network connect web nama-app-php74
Jika container dibuat langsung dengan --network web, langkah ini tidak diperlukan.
5
Periksa aplikasi dari dalam container
docker exec nama-app-php74 sh
php -v
curl -I http://127.0.0.1
6
Periksa dari VPS melalui nama container
docker exec nginx-proxy-manager \
  curl -I http://nama-app-php74:80
Jika curl tidak tersedia pada image Nginx Proxy Manager, lakukan pengujian dari container lain yang berada di network web.
7
Konfigurasi Proxy Host Gunakan hostname container dan port 80.
8
Aktifkan SSL setelah HTTP berhasil Request Let's Encrypt, lalu aktifkan Force SSL.

8. Troubleshooting Cepat

GejalaPemeriksaan
DNS kosong / NXDOMAIN dig +short subdomain.domain
dig @ns1.niagahoster.com subdomain.domain A
Pastikan record dibuat pada authoritative DNS.
DNS sudah benar tetapi website tidak tampil docker ps
docker network inspect web
Pastikan NPM dan container aplikasi berada pada network yang sama.
502 Bad Gateway Periksa nama container, port internal, network Docker, dan apakah Apache/Nginx di container hidup.
Connection refused docker exec nama-container curl -I http://127.0.0.1
Periksa service web di dalam container.
SSL error Pastikan DNS → VPS, port 80/443 terbuka, Proxy Host benar, dan certificate valid.
PHP error docker logs nama-container
Periksa versi PHP dan extension yang dibutuhkan aplikasi.

Perintah diagnosis utama

docker ps
docker logs --tail 100 nama-container
docker inspect nama-container
docker network inspect web
docker exec nama-container php -v
docker exec nama-container curl -I http://127.0.0.1

dig +short subdomain.domain.tld
curl -I http://subdomain.domain.tld
curl -I https://subdomain.domain.tld

9. Checklist Sebelum Go-Live

Contoh konfigurasi yang sudah terbukti berjalan
Domain: tests.telpro5.org
DNS: 202.10.37.186
Container: test-php74
Network: web
Container IP: 172.18.0.2
Web server: Apache
PHP: 7.4.33
Port internal: 80
Reverse proxy: Nginx Proxy Manager

10. Pola Standar untuk Banyak Aplikasi

Gunakan satu container per aplikasi/versi PHP bila kebutuhan versi berbeda.

DomainContainerPHPPort Internal
app1.domain.tldapp1-php747.480
app2.domain.tldapp2-php828.280
app3.domain.tldapp3-php838.380

Semua container dapat berada di network web. Nginx Proxy Manager menjadi pintu masuk HTTP/HTTPS dan meneruskan request berdasarkan hostname.