KATEGORI: CONTAINER

Installasi Docker Server dan Client di mesin berbeda menggunakan SSH

Untuk meningkatkan fleksibilitas akses terhadap server, kita membutuhkan Docker yang bisa diakses dari mana saja dan kapan saja. Juga bisa untuk menghemat sumber daya komputer pribadi.

Do Exploit

--

Akses docker daemon tanpa perlu buka port publik docker
Thumbnail!

Jika kalian mencari pengertian dan kegunaan Docker, bukan di artikel ini tempatnya, boleh pergi ke artikel yang telah saya sediakan diatas.

Latar Belakang Masalah

Biasanya, saat kita belajar docker pertama kali, Docker Client dan Docker Server harus digunakan dalam mesin yang sama. Bisa kalian pastikan dengan perintah docker version.

~# docker versionClient: Docker Engine - Community
Version: 19.03.15
API version: 1.40
Go version: go1.13.15
Git commit: 99e3ed8919
Built: Sat Jan 30 03:17:11 2021
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.15
API version: 1.40 (minimum version 1.12)
Go version: go1.13.15
Git commit: 99e3ed8919
Built: Sat Jan 30 03:15:40 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.3
GitCommit: 269548fa27e0089a8b8278fc4fc781d7f65a939b
runc:
Version: 1.0.0-rc92
GitCommit: ff819c7e9184c13b7c2607fe6c30ae19403a7aff
docker-init:
Version: 0.18.0
GitCommit: fec3683

Itu terjadi jika kalian mengikuti cara installasi dari dokumentasinya langsung.

~# apt-get install docker-ce docker-ce-cli containerd.io

Lihat perintah diatas, apa kegunaan install paket-paket tersebut?

  • docker-ce, berguna untuk menginstall paket docker daemon / server.
  • docker-ce-cli, sedangkan paket ini merupakan docker client.

Jadi hal yang akan kita lakukan hari ini adalah menginstall Docker Client dan Docker Daemon di mesin yang terpisah.

Keuntungan, berpikirlah misalnya kalian memiliki tim developer yang saling berkolaborasi membangun aplikasi. Ada kalanya kalian perlu berbagi image yang baru saja kalian buat kepada seorang yang lain, Docker Daemon (Lingkungan Pengembangan / Development) yang terpusat bisa menjadi jawaban untuk kasus ini.

Bisa juga kalian menggunakan Docker Daemon yang terpisah tersebut untuk menjadi jawaban dari komputer lokal kalian yang tidak punya cukup sumber daya menjalankan Docker Daemon.

Topology untuk Demo Docker Daemon & Client di Mesin Berbeda

Siapkan aplikasi virtualisasi kalian. Saya sendiri menggunakan VMWare sebagai aplikasi untuk membuat mesin virtual dengan sistem operasi Debian 9 semua.

Secara default, koneksi antara Docker Daemon tidak dibuka untuk bisa diakses dari luar. Saat installasi pertama, hanya bisa diakses melalui perangkat yang terinstall Docker Daemon saja.

Docker Daemon

Installasi

Ikuti cara installasi Docker Daemon dan Client diatas.

Sebelum kita lanjut, pasti kalian bertanya-tanya, katanya installnya terpisah tapi kok itu Docker Daemon sama Client diinstall bersamaan? 🤨

Iya sih, cuman kalau Docker Daemon nya aja yang diinstall, nanti gimana cara manajemen Docker Daemonnya didalam mesin yang sama? Sedangkan dibutuhkan Docker Client untuk hal tersebut.

Yang pasti, nanti di bagian selanjutnya, kita hanya perlu menginstall Docker Client tanpa Daemon.

Setelah itu, kalian bisa memastikan apakah Full Package Docker telah terinstall menggunakan perintah docker version. Pastikan outputnya sama seperti yang saya tunjukkan di bagian Latar Belakang.

~# systemctl disable --now docker.service docker.socket

Agar tidak mengganggu penyiapan Docker rootless, kita perlu disable permanen Docker yang sedang berjalan di atas user root.

Penyiapan Pengguna Docker

Agar Docker bisa diakses dari luar dengan aman, kita perlu 1 user yang bisa di remote SSH dan memiliki cukup akses untuk manajemen Docker.

~# adduser devops

Saat ini, Docker hanya bisa berjalan diatas user root. Tentu jika kita ingin mengubah aksesnya agar bisa diakses dari luar, membutuhkan user lain yang pasti bukan root (bahaya ni user).

Penyiapan Docker dengan akses root-less

Jadi intinya proses disini akan menyiapkan Docker yang bisa diakses dari user DevOps tadi saja, dan tidak memerlukan akses dari root.

~# apt-get install uidmap curl
  • uidmap,
  • cURL, paket untuk mentransfer dan mengambil data ke server menggunakan URL. Ini digunakan nanti saat konfigurasi docker untuk user devops.
~# echo kernel.unprivileged_userns_clone=1 >> /etc/sysctl.conf
~# sysctl --system
~# modprobe overlay permit_mounts_in_userns=1
  • Perintah pertama.
  • Perintah kedua, menerapkan konfigurasi sysctl yang baru saja ditambahkan.
  • Perintah ketiga; belajar dulu 😅.
~# logout# Login menggunakan user devops
~$ wget https://get.docker.com/rootless -O- | bash -

Setelah perintah terakhir tersebut, secara otomatis linux kalian akan menjalankan Bash Scripting dari link https://get.docker.com/rootless. Proses tersebut bertujuan untuk menyiapkan Docker yang bisa diakses dari user devops.

~$ echo export PATH=/home/devops/bin:$PATH >> /home/devops/.bashrc
~$ echo export DOCKER_HOST=unix:///home/devops/.docker/run/docker.sock >> /home/devops/.bashrc

Membuat environment variable. Pada akhir proses sebelumnya, biasanya kalian akan diminta untuk mengeksekusi perintah export blablbla sebelum menggunakan Docker rootless.

Untuk membuat proses tersebut otomatis, kita bisa masukkan kedua perintah tersebut kedalam file /home/devops/.bashrc.

  • Perintah pertama, jika kalian menyadari, beberapa perintah yang kita jalani seperti cat, ls, mkdir dan lain-lain sebenarnya itu terdapat pada direktori /bin.
    Lalu jika kalian liat juga, dalam direktori devops saat ini terdapat direktori bin juga loh. Lihat dalam direktori tersebut, ada beberapa perintah Docker yang bisa dijalankan oleh user devops.
    Jadi kita perlu menambahkan direktori /home/devops/bin tersebut kedalam environment variable $PATH. Sehingga setiap kali perintah Docker ingin dijalankan, tidak perlu di ketik secara eksplisit; /home/devops/bin/dockerd, namun secara implisit; dockerd.
  • Perintah kedua, disini kita membuat environment variable $DOCKER_HOST. Dimana variabel tersebut digunakan Docker client untuk mencari host Docker Daemon yang aktif. Dalam kasus ini, docker client akan menggunakan file socket dalam /home/devops/.docker/run/docker.sock.
~$ nano /home/devops/.config/systemd/user/docker.serviceDari 
ExecStart=/home/devops/bin/dockerd-rootless.sh
Menjadi
ExecStart=/home/devops/bin/dockerd-rootless.sh --iptables=FALSE -H unix:///home/devops/.docker/run/docker.sock

— iptables=FALSE tidak direkomendasikan digunakan untuk production.

Docker memiliki 3 tipe koneksi yang berbeda-beda. Pertama, unix, secara default akan membuat file di /var/run/docker.sock sebagai media komunikasi antara Docker Daemon dan Client. Maka dari itu, kita harus mendefinisikannya sendiri, dimana socket akan dibuat?

Lalu TCP, koneksi yang dibuka ke jaringan lokal atau publik. Untuk lokal sendiri kita bisa menggunakan alamat IP 127.0.0.1 dengan port bebas, tapi jika ingin bisa diakses dari luar, pakailah 0.0.0.0 dengan port bebas juga.

Nah alamat IP 0.0.0.0 itulah solusi lain dari koneksi Docker Daemon & Client tanpa fitur rootless.

~$ systemctl --user start docker

Oiiii bang! Kenapa gak langsung systemctl start docker aja sih?

Perlu diingatkan sekali lagi, kita membuat Docker yang dibangun diatas user devops, bukan root. Jadi kita harus membuat layanan sistem Docker yang bisa diaktifkan dari user biasa.

  • Berjalan diatas root = /lib/systemd/system/docker.service
  • Berjalan diatas devops = /home/devops/.config/systemd/docker.service

Memastikan Docker sudah berjalan lancar

devops@docker-daemon:~$ docker version
Client:
Version: 20.10.6
API version: 1.41
Go version: go1.13.15
Git commit: 370c289
Built: Fri Apr 9 22:42:10 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.6
API version: 1.41 (minimum version 1.12)
Go version: go1.13.15
Git commit: 8728dd2
Built: Fri Apr 9 22:46:14 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.4.4
GitCommit: 05f951a3781f4f2c1911b05e61c160e9c30eaa8e
runc:
Version: 1.0.0-rc93
GitCommit: 12644e614e25b05da6fd08a38ffa0cfe1903fdec
docker-init:
Version: 0.19.0
GitCommit: de40ad0

Docker Client

Instalasi

Ikuti cara installasi Docker Client diatas.

Sebelumnya pada Docker Daemon, kita menginstall seluruh paket docker. Disini kalian hanya perlu menginstall paket docker-ce-cli. Karena kita hanya akan melakukan remote docker daemon.

Remote Docker

~# ssh-keygen
~# ssh-copy-id devops@IP_ADDRESS_DOCKER_DAEMON

Saya asumsikan saat ini koneksi SSH Client dengan Server masih bisa diakses menggunakan password. Disini kita membuat akses SSH Client terhadap Server tanpa password, jadi menggunakan Public Key dan Private Key. Silahkan baca artikel saya sebelumnya untuk penjelasan lebih lanjut.

~# mkdir -p ~/.docker/
~# ssh -nNT -L ~/.docker/docker.sock:/home/devops/.docker/run/docker.sock devops@IP_ADDRESS_DOCKER_DAEMON

Kita baru saja membuat linked-file dari docker.sock server, jadi seakan-akan kita memiliki docker.sock pribadi, padahal itu terhubung dengan Docker Daemon dari server lain.

Sekarang kalian buka terminal yang lain untuk mencoba koneksi melalui docker.sock yang terdapat dalam folder ~/.docker.

root@docker-cli:~# export DOCKER_HOST=~/.docker/docker.sock
root@docker-cli:~# docker version
Client: Docker Engine - Community
Version: 19.03.15
API version: 1.40
Go version: go1.13.15
Git commit: 99e3ed8919
Built: Sat Jan 30 03:17:11 2021
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 20.10.6
API version: 1.41 (minimum version 1.12)
Go version: go1.13.15
Git commit: 8728dd2
Built: Fri Apr 9 22:46:14 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.4.4
GitCommit: 05f951a3781f4f2c1911b05e61c160e9c30eaa8e
runc:
Version: 1.0.0-rc93
GitCommit: 12644e614e25b05da6fd08a38ffa0cfe1903fdec
docker-init:
Version: 0.19.0
GitCommit: de40ad0

Hasil Akhir

Proses mendapatkan Docker rootless memang lumayan panjang. Tapi yang kita tahu sekarang, Docker sudah tidak berdiri diatas user root, namun user lain yang dalam artikel ini saya gunakan devops.

Ada tambahan lain jika kalian ingin makin aman:

  • Tutup akses password terhadap user devops, jadi hanya boleh menggunakan akses Public dan Private key.
  • Batasi akses perintah yang bisa dilakukan saat SSH user devops, saat ini user devops bisa di remote SSH langsung, dan menjalankan perintah apapun didalamnya, termasuk mematikan layanan Docker.
  • Layanan Docker hanya berjalan saat di server login menggunakan user devops, jadi artinya tidak aktif ketika server booting up.
  • Masih banyak lagi tentunya, kasih tau saya kalau ada yang perlu ditambah yaa. 😉

Lalu catatan tambahan saat mengelola docker rootless:

  • Port <1024 tidak bisa digunakan untuk memetakan port dari container internal agar bisa diakses publik.

Konfigurasi dengan Ansible

Referensi

--

--

Do Exploit

I share stories about what I've learned in the past and now. Let's connect to Instagram! @do.exploit