feat: Docker Compose setup untuk development & production
- docker/php/Dockerfile: PHP 8.4-FPM + GD + imagick (PECL) + semua extension Laravel - docker/php/php.ini: upload 20MB, memory 512MB, opcache, Asia/Kuala_Lumpur - docker/php/php-dev.ini: validate_timestamps=1, display_errors=On (dev) - docker/nginx/default.conf: gzip, security headers, static asset caching - docker/entrypoint.sh: tunggu MySQL → migrate → seed AdminSeeder → cache (prod) - docker-compose.yml: dev stack — port 8003, DB host 33060, queue worker - docker-compose.prod.yml: production overrides — storage volume, no DB port exposed - .env.docker: template env untuk Docker (DB_HOST=db) - .dockerignore: exclude node_modules, vendor, .env, logs fix: testGenerate try/catch kembalikan JSON error (bukan HTML 500) fix: loadPreview() semak r.ok, tunjuk error alert, loading spinner Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
78
docker/nginx/default.conf
Normal file
78
docker/nginx/default.conf
Normal file
@@ -0,0 +1,78 @@
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# eCert MBIP — Nginx Server Block
|
||||
# Document root: /var/www/public | PHP-FPM upstream: app:9000
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
# Gzip compression
|
||||
gzip on;
|
||||
gzip_comp_level 5;
|
||||
gzip_min_length 256;
|
||||
gzip_proxied any;
|
||||
gzip_vary on;
|
||||
gzip_types
|
||||
text/plain text/css text/javascript application/javascript
|
||||
application/json application/xml image/svg+xml font/woff2;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
root /var/www/public;
|
||||
index index.php;
|
||||
|
||||
# Max upload (kena sama dengan php.ini: post_max_size)
|
||||
client_max_body_size 25M;
|
||||
|
||||
charset utf-8;
|
||||
|
||||
# ── Security headers ──────────────────────────────────────────────────────
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
|
||||
# ── Laravel routes ────────────────────────────────────────────────────────
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
# ── PHP-FPM ───────────────────────────────────────────────────────────────
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
|
||||
fastcgi_pass app:9000;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
|
||||
fastcgi_read_timeout 120s;
|
||||
fastcgi_connect_timeout 10s;
|
||||
fastcgi_buffer_size 16k;
|
||||
fastcgi_buffers 8 16k;
|
||||
}
|
||||
|
||||
# ── Static assets — cache 1 tahun ─────────────────────────────────────────
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|svg|css|js|woff2?|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# ── Halang akses fail tersembunyi ─────────────────────────────────────────
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# ── Halang akses terus ke fail sensitif ───────────────────────────────────
|
||||
location ~* \.(env|log|htaccess|htpasswd|ini|sh|sql|bak)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# ── Logging ───────────────────────────────────────────────────────────────
|
||||
access_log /var/log/nginx/ecert-access.log;
|
||||
error_log /var/log/nginx/ecert-error.log warn;
|
||||
}
|
||||
Reference in New Issue
Block a user