{"id":2189,"date":"2026-10-14T13:01:29","date_gmt":"2026-10-14T05:01:29","guid":{"rendered":"https:\/\/zaf.web.id\/blog\/?p=2189"},"modified":"2026-11-14T21:43:07","modified_gmt":"2026-11-14T13:43:07","slug":"migrasi-ke-docker","status":"publish","type":"post","link":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/","title":{"rendered":"Migrasi ke Docker"},"content":{"rendered":"<p>Hampir sepuluh tahun terakhir semua website yang saya kelola selalu berjalan di atas web panel. Dimulai dari Webuzo, lalu <a href=\"https:\/\/zaf.web.id\/blog\/mengganti-webuzo-dengan-centos-web-panel\/\">pindah ke CentOS Web Panel<\/a>, sempat singgah di aaPanel, dan akhirnya sekarang semuanya saya pindahkan ke Docker. Tulisan ini merangkum alasan dan cara migrasinya.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2238\" src=\"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?resize=1680%2C944&#038;ssl=1\" alt=\"Ilustrasi perjalanan dari web panel ke Docker container\" width=\"1680\" height=\"944\" srcset=\"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?w=1680&amp;ssl=1 1680w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?resize=1024%2C575&amp;ssl=1 1024w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?resize=1536%2C863&amp;ssl=1 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<h2>Manajemen pakai panel<\/h2>\n<p>Panel sangat membantu di awal. Membuat domain, database, email, dan sertifikat SSL cukup dengan beberapa klik. Untuk satu atau dua website, cara ini masih masuk akal.<\/p>\n<p>Masalah mulai terasa ketika jumlah website bertambah dan kebutuhannya berbeda-beda. Ada aplikasi lama yang hanya jalan di PHP 7.4, ada WordPress yang butuh PHP 8.3, ada OJS dengan kebutuhan ekstensi sendiri. Semuanya berbagi satu web server, satu MySQL, dan satu sistem operasi. Satu situs yang terinfeksi malware berpotensi menular ke situs lain di server yang sama, seperti yang pernah saya ceritakan di <a href=\"https:\/\/zaf.web.id\/blog\/mitigasi-malware-di-web-server-dan-cara-membersihkannya\/\">mitigasi malware di web server<\/a>.<\/p>\n<h2>Webuzo<\/h2>\n<p>Webuzo adalah panel pertama yang saya pakai serius. Ringan dan mudah, tetapi versi gratisnya hanya menyediakan satu user untuk mengelola semuanya. SSL juga masih harus dipasang manual setiap tiga bulan.<\/p>\n<h2>CentOS Web Panel<\/h2>\n<p>CWP menyelesaikan masalah di Webuzo: multiuser, ModSecurity, dan auto SSL dari Let&#8217;s Encrypt. Bertahun-tahun CWP menjadi andalan. Sayangnya CWP terikat dengan keluarga CentOS. Ketika CentOS 8 dihentikan lebih awal dan CentOS 7 berakhir masa dukungannya pada Juni 2024, saya harus mencari jalan keluar.<\/p>\n<h2>aaPanel<\/h2>\n<p>aaPanel sempat menjadi pengganti karena bisa berjalan di Ubuntu dan Debian. Tampilannya rapi dan instalasinya cepat. Tetapi pada dasarnya polanya sama: semua aplikasi tetap menumpuk di satu sistem. Setiap kali upgrade PHP atau MySQL, saya harus berdoa supaya tidak ada situs yang rusak.<\/p>\n<p>Di titik ini saya sadar yang saya butuhkan bukan panel yang lebih baik, melainkan cara kerja yang berbeda.<\/p>\n<h2>Docker<\/h2>\n<p>Dengan Docker, setiap aplikasi berjalan di container sendiri lengkap dengan versi PHP, web server, dan databasenya. Satu situs bermasalah tidak menyeret situs lain. Konfigurasi juga tersimpan sebagai file teks yang bisa disimpan di Git, jadi membangun ulang server tidak lagi bergantung pada ingatan.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2239\" src=\"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-arsitektur-reverse-proxy.jpg?resize=1680%2C944&#038;ssl=1\" alt=\"Diagram arsitektur reverse proxy dengan container per situs\" width=\"1680\" height=\"944\" srcset=\"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-arsitektur-reverse-proxy.jpg?w=1680&amp;ssl=1 1680w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-arsitektur-reverse-proxy.jpg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-arsitektur-reverse-proxy.jpg?resize=1024%2C575&amp;ssl=1 1024w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-arsitektur-reverse-proxy.jpg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-arsitektur-reverse-proxy.jpg?resize=1536%2C863&amp;ssl=1 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<p>Polanya seperti diagram di atas. Satu reverse proxy berdiri di depan dan menerima semua trafik HTTPS, lalu meneruskannya ke container masing-masing situs. Database hanya bisa diakses dari network internal situsnya, tidak pernah dibuka ke internet.<\/p>\n<h3>1. Struktur direktori<\/h3>\n<p>Saya memakai satu direktori per situs di <code>\/opt\/stack<\/code>:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-plain\" data-lang=\"Text\"><code>\/opt\/stack\/\n\u251c\u2500\u2500 proxy\/          # Caddy\n\u251c\u2500\u2500 situs-a\/        # WordPress\n\u2502   \u251c\u2500\u2500 compose.yaml\n\u2502   \u251c\u2500\u2500 .env\n\u2502   \u251c\u2500\u2500 app\/\n\u2502   \u2514\u2500\u2500 db\/\n\u2514\u2500\u2500 ojs\/<\/code><\/pre>\n<\/div>\n<h3>2. Reverse proxy<\/h3>\n<p>Buat network bersama untuk proxy, lalu jalankan Caddy. Caddy otomatis mengurus sertifikat Let&#8217;s Encrypt, fitur yang dulu menjadi alasan saya memilih CWP.<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>docker network create proxy<\/code><\/pre>\n<\/div>\n<p>Isi <code>proxy\/Caddyfile<\/code> cukup sesederhana ini:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-plain\" data-file=\"proxy\/Caddyfile\" data-lang=\"Caddyfile\"><code>situs-a.ac.id {\n    reverse_proxy situs-a-web-1:80\n}\n\njurnal.ac.id {\n    reverse_proxy ojs-app-1:80\n}<\/code><\/pre>\n<\/div>\n<h3>3. Compose untuk setiap situs<\/h3>\n<p>Contoh <code>situs-a\/compose.yaml<\/code> untuk WordPress:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-plain\" data-file=\"situs-a\/compose.yaml\" data-lang=\"YAML\"><code>services:\n  web:\n    image: nginx:1.27-alpine\n    volumes:\n      - .\/app:\/var\/www\/html:ro\n      - .\/nginx.conf:\/etc\/nginx\/conf.d\/default.conf:ro\n    networks: [internal, proxy]\n    restart: unless-stopped\n\n  php:\n    image: wordpress:php8.3-fpm\n    volumes:\n      - .\/app:\/var\/www\/html\n    env_file: .env\n    networks: [internal]\n    restart: unless-stopped\n\n  db:\n    image: mariadb:11.4\n    volumes:\n      - .\/db:\/var\/lib\/mysql\n    env_file: .env\n    networks: [internal]\n    restart: unless-stopped\n\nnetworks:\n  internal:\n  proxy:\n    external: true<\/code><\/pre>\n<\/div>\n<p>Perhatikan hanya container <code>web<\/code> yang tergabung ke network <code>proxy<\/code>. Container <code>php<\/code> dan <code>db<\/code> tidak bisa dijangkau dari luar.<\/p>\n<h2>Langkah migrasi dari panel<\/h2>\n<p>Proses migrasi setiap situs kurang lebih sama:<\/p>\n<h3>1. Turunkan TTL DNS beberapa hari sebelumnya, misalnya menjadi 300 detik, supaya perpindahan cepat terasa.<\/h3>\n<h3>2. Dump database dan salin file dari server lama.<\/h3>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>mysqldump --single-transaction -u user -p nama_db &gt; situs-a.sql\nrsync -avz user@server-lama:\/home\/user\/public_html\/ \/opt\/stack\/situs-a\/app\/<\/code><\/pre>\n<\/div>\n<h3>3. Jalankan container, lalu import database.<\/h3>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>cd \/opt\/stack\/situs-a\ndocker compose up -d\ndocker compose exec -T db mariadb -u root -p\"$DB_ROOT_PASSWORD\" nama_db &lt; situs-a.sql<\/code><\/pre>\n<\/div>\n<h3>4. Uji dengan mengarahkan domain ke IP server baru lewat file <code>hosts<\/code> di laptop sendiri. Jika semua normal, baru ubah record DNS.<\/h3>\n<h3>5. Hapus file dump setelah selesai.<\/h3>\n<p>Langkah terakhir ini sering terlupa. Saya pernah menulis kenapa <a href=\"https:\/\/zaf.web.id\/blog\/penting-hapus-file-sql-setelah-migrasi-web\/\">file .sql dan .zip sisa migrasi wajib dihapus<\/a>.<\/p>\n<h2>Update jadi lebih tenang<\/h2>\n<p>Upgrade versi PHP sekarang cukup mengganti tag image di <code>compose.yaml<\/code>. Kalau ternyata bermasalah, kembalikan tag lama dan jalankan ulang. Tidak ada lagi drama upgrade satu server penuh.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2240\" src=\"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-compose-ps.jpg?resize=1680%2C944&#038;ssl=1\" alt=\"Output terminal docker compose ps dan docker compose up\" width=\"1680\" height=\"944\" srcset=\"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-compose-ps.jpg?w=1680&amp;ssl=1 1680w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-compose-ps.jpg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-compose-ps.jpg?resize=1024%2C575&amp;ssl=1 1024w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-compose-ps.jpg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-compose-ps.jpg?resize=1536%2C863&amp;ssl=1 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>docker compose pull\ndocker compose up -d<\/code><\/pre>\n<\/div>\n<h2>Yang perlu diperhatikan<\/h2>\n<p>Docker bukan tanpa kekurangan. Tidak ada lagi tombol klik-klik seperti di panel, jadi perlu terbiasa dengan terminal. Jika butuh tampilan visual, Portainer bisa membantu. Image lama juga menumpuk dan memakan disk, sehingga perlu sesekali dibersihkan dengan <code>docker image prune<\/code>.<\/p>\n<p>Email adalah satu-satunya layanan yang tidak saya pindahkan ke Docker. Mengelola mail server sendiri terlalu merepotkan, jadi saya serahkan ke layanan pihak ketiga dan cukup mengatur record MX-nya.<\/p>\n<p>Terakhir, container tidak menggantikan backup. Volume database tetap harus dicadangkan ke luar server, misalnya dengan <a href=\"https:\/\/zaf.web.id\/blog\/backup-anti-ransomware-immutable-mysql-s3\/\">immutable backup ke object storage<\/a>.<\/p>\n<p>Setelah semua situs pindah, saya justru merasa lebih dekat dengan server. Semua yang berjalan tertulis jelas di file konfigurasi, bukan tersembunyi di balik panel.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hampir sepuluh tahun terakhir semua website yang saya kelola selalu berjalan di atas web panel.&hellip;<\/p>\n","protected":false},"author":1,"featured_media":2238,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_hide_featured_image":false,"_jetpack_featured_image_duplicate_dismissed":0,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[333,58],"tags":[355,345,354,356,357],"class_list":["post-2189","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-server","tag-caddy","tag-docker","tag-docker-compose","tag-migrasi","tag-web-panel"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Migrasi ke Docker - Ahmad Zafrullah<\/title>\n<meta name=\"description\" content=\"Pengalaman migrasi dari Webuzo, CWP, dan aaPanel ke Docker: struktur direktori, reverse proxy Caddy, contoh compose, dan langkah migrasi situs.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/\" \/>\n<meta property=\"og:locale\" content=\"id_ID\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Migrasi ke Docker - Ahmad Zafrullah\" \/>\n<meta property=\"og:description\" content=\"Pengalaman migrasi dari Webuzo, CWP, dan aaPanel ke Docker: struktur direktori, reverse proxy Caddy, contoh compose, dan langkah migrasi situs.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/\" \/>\n<meta property=\"og:site_name\" content=\"Ahmad Zafrullah\" \/>\n<meta property=\"article:publisher\" content=\"http:\/\/www.facebook.com\/23Pstars\" \/>\n<meta property=\"article:author\" content=\"http:\/\/www.facebook.com\/23Pstars\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-14T05:01:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-11-14T13:43:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1680\" \/>\n\t<meta property=\"og:image:height\" content=\"944\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Zaf\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@23Pstars\" \/>\n<meta name=\"twitter:site\" content=\"@23Pstars\" \/>\n<meta name=\"twitter:label1\" content=\"Ditulis oleh\" \/>\n\t<meta name=\"twitter:data1\" content=\"Zaf\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimasi waktu membaca\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 menit\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/\"},\"author\":{\"name\":\"Zaf\",\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/#\\\/schema\\\/person\\\/ba4e955d59a1e6a8284857e74b14e5ed\"},\"headline\":\"Migrasi ke Docker\",\"datePublished\":\"2026-10-14T05:01:29+00:00\",\"dateModified\":\"2026-11-14T13:43:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/\"},\"wordCount\":635,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/#\\\/schema\\\/person\\\/ba4e955d59a1e6a8284857e74b14e5ed\"},\"image\":{\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/zaf.web.id\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1\",\"keywords\":[\"caddy\",\"docker\",\"docker compose\",\"migrasi\",\"web panel\"],\"articleSection\":[\"DevOps\",\"Server\"],\"inLanguage\":\"id\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/\",\"url\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/\",\"name\":\"Migrasi ke Docker - Ahmad Zafrullah\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/zaf.web.id\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1\",\"datePublished\":\"2026-10-14T05:01:29+00:00\",\"dateModified\":\"2026-11-14T13:43:07+00:00\",\"description\":\"Pengalaman migrasi dari Webuzo, CWP, dan aaPanel ke Docker: struktur direktori, reverse proxy Caddy, contoh compose, dan langkah migrasi situs.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/#breadcrumb\"},\"inLanguage\":\"id\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"id\",\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/zaf.web.id\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/zaf.web.id\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1\",\"width\":1680,\"height\":944,\"caption\":\"Dari Webuzo, CWP, aaPanel, sampai akhirnya Docker.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/migrasi-ke-docker\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Migrasi ke Docker\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/\",\"name\":\"Ahmad Zafrullah\",\"description\":\"Work to Learn is better than Learn how to Work\",\"publisher\":{\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/#\\\/schema\\\/person\\\/ba4e955d59a1e6a8284857e74b14e5ed\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"id\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/#\\\/schema\\\/person\\\/ba4e955d59a1e6a8284857e74b14e5ed\",\"name\":\"Zaf\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"id\",\"@id\":\"https:\\\/\\\/i0.wp.com\\\/zaf.web.id\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/09\\\/zaf_auto_x2.jpeg?fit=300%2C300&ssl=1\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/zaf.web.id\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/09\\\/zaf_auto_x2.jpeg?fit=300%2C300&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/zaf.web.id\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/09\\\/zaf_auto_x2.jpeg?fit=300%2C300&ssl=1\",\"width\":300,\"height\":300,\"caption\":\"Zaf\"},\"logo\":{\"@id\":\"https:\\\/\\\/i0.wp.com\\\/zaf.web.id\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/09\\\/zaf_auto_x2.jpeg?fit=300%2C300&ssl=1\"},\"sameAs\":[\"http:\\\/\\\/zaf.web.id\",\"http:\\\/\\\/www.facebook.com\\\/23Pstars\",\"https:\\\/\\\/x.com\\\/23Pstars\"],\"url\":\"https:\\\/\\\/zaf.web.id\\\/blog\\\/author\\\/zaf\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Migrasi ke Docker - Ahmad Zafrullah","description":"Pengalaman migrasi dari Webuzo, CWP, dan aaPanel ke Docker: struktur direktori, reverse proxy Caddy, contoh compose, dan langkah migrasi situs.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/","og_locale":"id_ID","og_type":"article","og_title":"Migrasi ke Docker - Ahmad Zafrullah","og_description":"Pengalaman migrasi dari Webuzo, CWP, dan aaPanel ke Docker: struktur direktori, reverse proxy Caddy, contoh compose, dan langkah migrasi situs.","og_url":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/","og_site_name":"Ahmad Zafrullah","article_publisher":"http:\/\/www.facebook.com\/23Pstars","article_author":"http:\/\/www.facebook.com\/23Pstars","article_published_time":"2026-10-14T05:01:29+00:00","article_modified_time":"2026-11-14T13:43:07+00:00","og_image":[{"width":1680,"height":944,"url":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1","type":"image\/jpeg"}],"author":"Zaf","twitter_card":"summary_large_image","twitter_creator":"@23Pstars","twitter_site":"@23Pstars","twitter_misc":{"Ditulis oleh":"Zaf","Estimasi waktu membaca":"5 menit"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/#article","isPartOf":{"@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/"},"author":{"name":"Zaf","@id":"https:\/\/zaf.web.id\/blog\/#\/schema\/person\/ba4e955d59a1e6a8284857e74b14e5ed"},"headline":"Migrasi ke Docker","datePublished":"2026-10-14T05:01:29+00:00","dateModified":"2026-11-14T13:43:07+00:00","mainEntityOfPage":{"@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/"},"wordCount":635,"commentCount":0,"publisher":{"@id":"https:\/\/zaf.web.id\/blog\/#\/schema\/person\/ba4e955d59a1e6a8284857e74b14e5ed"},"image":{"@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1","keywords":["caddy","docker","docker compose","migrasi","web panel"],"articleSection":["DevOps","Server"],"inLanguage":"id","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/","url":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/","name":"Migrasi ke Docker - Ahmad Zafrullah","isPartOf":{"@id":"https:\/\/zaf.web.id\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/#primaryimage"},"image":{"@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1","datePublished":"2026-10-14T05:01:29+00:00","dateModified":"2026-11-14T13:43:07+00:00","description":"Pengalaman migrasi dari Webuzo, CWP, dan aaPanel ke Docker: struktur direktori, reverse proxy Caddy, contoh compose, dan langkah migrasi situs.","breadcrumb":{"@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/#breadcrumb"},"inLanguage":"id","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/"]}]},{"@type":"ImageObject","inLanguage":"id","@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/#primaryimage","url":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1","contentUrl":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1","width":1680,"height":944,"caption":"Dari Webuzo, CWP, aaPanel, sampai akhirnya Docker."},{"@type":"BreadcrumbList","@id":"https:\/\/zaf.web.id\/blog\/migrasi-ke-docker\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zaf.web.id\/blog\/"},{"@type":"ListItem","position":2,"name":"Migrasi ke Docker"}]},{"@type":"WebSite","@id":"https:\/\/zaf.web.id\/blog\/#website","url":"https:\/\/zaf.web.id\/blog\/","name":"Ahmad Zafrullah","description":"Work to Learn is better than Learn how to Work","publisher":{"@id":"https:\/\/zaf.web.id\/blog\/#\/schema\/person\/ba4e955d59a1e6a8284857e74b14e5ed"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/zaf.web.id\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"id"},{"@type":["Person","Organization"],"@id":"https:\/\/zaf.web.id\/blog\/#\/schema\/person\/ba4e955d59a1e6a8284857e74b14e5ed","name":"Zaf","image":{"@type":"ImageObject","inLanguage":"id","@id":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2024\/09\/zaf_auto_x2.jpeg?fit=300%2C300&ssl=1","url":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2024\/09\/zaf_auto_x2.jpeg?fit=300%2C300&ssl=1","contentUrl":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2024\/09\/zaf_auto_x2.jpeg?fit=300%2C300&ssl=1","width":300,"height":300,"caption":"Zaf"},"logo":{"@id":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2024\/09\/zaf_auto_x2.jpeg?fit=300%2C300&ssl=1"},"sameAs":["http:\/\/zaf.web.id","http:\/\/www.facebook.com\/23Pstars","https:\/\/x.com\/23Pstars"],"url":"https:\/\/zaf.web.id\/blog\/author\/zaf\/"}]}},"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1322,"url":"https:\/\/zaf.web.id\/blog\/mengganti-webuzo-dengan-centos-web-panel\/","url_meta":{"origin":2189,"position":0},"title":"Mengganti Webuzo dengan CentOS Web Panel","author":"Zaf","date":"Agustus 21, 2018","format":false,"excerpt":"Setelah beberapa tahun terakhir aktif menggunakan Webuzo, tiba saatnya move on kepada software lain. Kali ini tempat singgah berikutnya adalah CentOS Web Panel (CWP). CWP merupakan panel control untuk kebutuhan website pada server dengan distro CentOS. Dengan banyaknya domain yang terdistribusi dalam beberapa server LRsoft, proses migrasi mungkin akan memakan\u2026","rel":"","context":"dalam &quot;Internet&quot;","block_context":{"text":"Internet","link":"https:\/\/zaf.web.id\/blog\/category\/internet\/"},"img":{"alt_text":"CWP Pro","src":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2018\/09\/Screen-Shot-2018-09-21-at-09.58.12.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2018\/09\/Screen-Shot-2018-09-21-at-09.58.12.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2018\/09\/Screen-Shot-2018-09-21-at-09.58.12.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2018\/09\/Screen-Shot-2018-09-21-at-09.58.12.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1999,"url":"https:\/\/zaf.web.id\/blog\/home-assistant-di-raspberry-pi-dengan-docker-dan-cloudflare\/","url_meta":{"origin":2189,"position":1},"title":"Home Assistant di Raspberry Pi dengan Docker dan Cloudflare","author":"Zaf","date":"Maret 14, 2026","format":false,"excerpt":"Sudah lama Raspberry Pi di rumah saya hanya menganggur di laci. Akhirnya saya pakai untuk menjalankan Home Assistant, platform open source untuk mengendalikan perangkat rumah pintar dari berbagai merek dalam satu dashboard. Lampu, smart plug, sensor pintu, sampai CCTV bisa dikendalikan dan diotomasi tanpa bergantung pada aplikasi masing-masing vendor. Tantangannya\u2026","rel":"","context":"dalam &quot;DevOps&quot;","block_context":{"text":"DevOps","link":"https:\/\/zaf.web.id\/blog\/category\/devops\/"},"img":{"alt_text":"Ilustrasi Raspberry Pi terhubung ke Cloudflare untuk Home Assistant","src":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/home-assistant-raspberry-pi-cloudflare.jpg?fit=1200%2C674&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/home-assistant-raspberry-pi-cloudflare.jpg?fit=1200%2C674&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/home-assistant-raspberry-pi-cloudflare.jpg?fit=1200%2C674&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/home-assistant-raspberry-pi-cloudflare.jpg?fit=1200%2C674&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/home-assistant-raspberry-pi-cloudflare.jpg?fit=1200%2C674&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":326,"url":"https:\/\/zaf.web.id\/blog\/review-indonetmedia-com\/","url_meta":{"origin":2189,"position":2},"title":"Review indonetmedia.com","author":"Zaf","date":"Agustus 12, 2014","format":false,"excerpt":"Satu lagi\u00a0web hosting\u00a0dan domain registration provider\u00a0indonesia, CV. Indonetmedia Corporation. Saya hampir lupa kapan pertama kali mulai menggunakan layanan disana, yang jelas sudah lumayan banyak website yang saya percayakan untuk dihost disana,\u00a0sampai-sampai mendaftar untuk menjadi reseller akun hosting yang mana niatnya biar sedikit lebih hemat dan mudah ngelolanya, ngumpulin website-website dalam\u2026","rel":"","context":"dalam &quot;Coretan&quot;","block_context":{"text":"Coretan","link":"https:\/\/zaf.web.id\/blog\/category\/coretan\/"},"img":{"alt_text":"Logo Indonetmedia","src":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2014\/08\/logo.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":2217,"url":"https:\/\/zaf.web.id\/blog\/bahaya-memasang-mcp-server-ai-agent-di-server-produksi\/","url_meta":{"origin":2189,"position":3},"title":"Bahaya Memasang MCP Server \/ AI Agent di Server Produksi","author":"Zaf","date":"Desember 23, 2025","format":false,"excerpt":"AI kini tidak lagi sekadar menjawab pertanyaan. Lewat Model Context Protocol (MCP), sebuah AI agent bisa membaca database, menjalankan perintah, bahkan melakukan deploy. Sebagai orang yang sehari-hari mengurus server, saya melihat MCP sebagai pintu baru yang harus diperlakukan sama seriusnya dengan port SSH. Seberapa besar risikonya? Sejumlah riset keamanan di\u2026","rel":"","context":"dalam &quot;Security&quot;","block_context":{"text":"Security","link":"https:\/\/zaf.web.id\/blog\/category\/security\/"},"img":{"alt_text":"Ilustrasi AI agent memegang akses ke server produksi","src":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/AaGXhdf1A_mdSucUX8JpFQ-AaGXhdf1m2KMAawBBA-Ljw.png?fit=1200%2C674&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/AaGXhdf1A_mdSucUX8JpFQ-AaGXhdf1m2KMAawBBA-Ljw.png?fit=1200%2C674&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/AaGXhdf1A_mdSucUX8JpFQ-AaGXhdf1m2KMAawBBA-Ljw.png?fit=1200%2C674&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/AaGXhdf1A_mdSucUX8JpFQ-AaGXhdf1m2KMAawBBA-Ljw.png?fit=1200%2C674&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/AaGXhdf1A_mdSucUX8JpFQ-AaGXhdf1m2KMAawBBA-Ljw.png?fit=1200%2C674&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":586,"url":"https:\/\/zaf.web.id\/blog\/masalah-mysql-service-sering-mati-pada-cloud-digitalocean\/","url_meta":{"origin":2189,"position":4},"title":"Masalah MySQL service sering mati pada Cloud DigitalOcean","author":"Zaf","date":"September 22, 2015","format":false,"excerpt":"Beberapa bulan terakhir saya memutuskan untuk menggunakan layanan cloud server dari DigitalOcean untuk mengakomodir semua service, baik website maupun system management yang saya gunakan di kantor. Butuh beberapa hari untuk proses migrasi data dari layanan sebelumnya (shared hosting) dan berjalan cukup baik, sampai saat ini kami sudah menggunakan 3 server\u2026","rel":"","context":"dalam &quot;Server&quot;","block_context":{"text":"Server","link":"https:\/\/zaf.web.id\/blog\/category\/server\/"},"img":{"alt_text":"DigitalOcean Logo","src":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2015\/09\/digitalocean_logo-300x300.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1957,"url":"https:\/\/zaf.web.id\/blog\/rekomendasi-keamanan-upload-dir-pada-aplikasi-web\/","url_meta":{"origin":2189,"position":5},"title":"Rekomendasi Keamanan Upload Dir pada Aplikasi Web","author":"Zaf","date":"Mei 14, 2026","format":false,"excerpt":"Tidak sedikit serangan yang terjadi terhadap website yang mengincar File Upload Vulnerabilities, khususnya website yang berbasis engine populer seperti WordPress. Polanya hampir selalu sama: penyerang menemukan celah di form upload, plugin, atau theme, lalu mengunggah web shell berekstensi .php. Setelah web shell bisa dieksekusi, penyerang bebas menyisipkan malware ke file\u2026","rel":"","context":"dalam &quot;Security&quot;","block_context":{"text":"Security","link":"https:\/\/zaf.web.id\/blog\/category\/security\/"},"img":{"alt_text":"Ilustrasi folder terkunci dan file PHP yang diblokir","src":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/keamanan-upload-dir-chattr.jpg?fit=1200%2C674&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/keamanan-upload-dir-chattr.jpg?fit=1200%2C674&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/keamanan-upload-dir-chattr.jpg?fit=1200%2C674&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/keamanan-upload-dir-chattr.jpg?fit=1200%2C674&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/keamanan-upload-dir-chattr.jpg?fit=1200%2C674&ssl=1&resize=1050%2C600 3x"},"classes":[]}],"jetpack_likes_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p4zLnS-zj","jetpack_featured_media_url":"https:\/\/i0.wp.com\/zaf.web.id\/blog\/wp-content\/uploads\/2026\/11\/migrasi-docker-dari-panel-ke-container.jpg?fit=1680%2C944&ssl=1","_links":{"self":[{"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/posts\/2189","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/comments?post=2189"}],"version-history":[{"count":5,"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/posts\/2189\/revisions"}],"predecessor-version":[{"id":2258,"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/posts\/2189\/revisions\/2258"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/media\/2238"}],"wp:attachment":[{"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/media?parent=2189"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/categories?post=2189"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zaf.web.id\/blog\/wp-json\/wp\/v2\/tags?post=2189"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}