---
# System prepended metadata

title: Docker Fundamental
tags: [Templates, Documentation]

---

---
title: 'Docker Fundamental'
disqus: Docker
---

# **DOCKER FUNDAMENTAL**

![f1a9f981-759b-4f3f-b15e-5c65eab64870](https://hackmd.io/_uploads/Hy3luKIAa.png)

## Table of Content
[TOC]

## **Container**

### **1. Container Overview**
**Container** adalah mekanisme software packaging yang didalamnya terdapat aplikasi, sekaligus pendukungnya seperti framework, dependency, library, dsb. Container ini nantinya akan dibangun dengan standarisasi. Sehingga memudahkan penginstallan oleh developer lain.

**Keamanan** dari container sendiri bahkan lebih aman dibandingkan aplikasi lain di luar itu. Container memanfaatkan protokol keamanan seperti namespace dan cgroups. Sifat **container** yang **immutable** juga memudahkan untuk scannedd for CVEs, juga man-in-the-middle attack yang bertugas menjaga kontainer dari kerusakan selama transit maupun kerusakan akibat pengaruh node lain.

![image](https://hackmd.io/_uploads/BJeMO_cp6.png)
![image](https://hackmd.io/_uploads/SJczu_5pa.png)

Terlihat dari perbandingan di atas. Kebutuhan **sumber daya** container lebih ringan dibandingkan ketika menggunakan VM (Virtual Machine). Hal itu dikarenakan, dalam struktur container, OS di tiap aplikasi tidak dibutuhkan. Kebutuhan OS akan terpenuhi dengan instalasi yang memang dibutuhkan dalam container, dan kemudian mengemasnya seakan-akan telah terinstal OS secara utuh.

**Keunggulan** lainnya dari container ialah mudah untuk dikirimkan dan disimulasikan. Container ibarat sebuah paket lengkap yang didalamnya telah terdapat aplikasi beserta dependencynya yang dapat dikirmkan sekaligus kepada host lain. Sehingga host yang menerima paket tersebut dapat langsung menginstall dan menjalankannya. Begitu juga saat simulasi perlu untuk dilakakukan, database dapat sekaligus termuat di dalam container. Saat selesai simulasi pun, container dapat dihentikan dan dihapus tanpa meninggalkan sampah di PC. 


---

### **2. Penyedia Layanan Container**
#### **a. Docker**
![image](https://hackmd.io/_uploads/HkHhXuca6.png)
**Docker** memungkinkan penggunanya untuk memisahkan aplikasi dengan infrastrukturnya. Hal ini memudahkan dalam instalasi software sekaligus mengatur, mengirimkan, menguji dan mengembangkan aplikasi beserta dependency. **Docker** juga memungkinkan dalam implementasi secara utuh atau dengan penyesuaian pada container.
#### **b. Podman**
![image](https://hackmd.io/_uploads/HJJq4_5ap.png)
Podman dijalankan, dibangun, dan dibagikan menggunakan OCI (Open Containers Initiative)  Container dan Container Images. Spesialiasi layanan Podman ialah dalam membuat, menjalankan, dan memelihara container dalam lingkungan produksi, yang dapat dijalankan oleh root maupun non-previleged user.
#### **c. LXC**
![image](https://hackmd.io/_uploads/BJz9Hu5ap.png)
Spesialisasi dari LXC ialah membangun lingkungan semirip mungkin dengan standar Linux tanpa perlu kernel terpisah. LXC menekankan pada penggunaan API yang kuat namun sederhana, sehingga memudahkan pengguna untuk membangun dan mengelola container.
#### **d. LXD**
![image](https://hackmd.io/_uploads/HJLRIdc6p.png)
LXD merupakan next generation sistem container dan pengelola virtual machine. Menawarkan pengalaman dengan full Linux system yang berjalan container atau vm, dengan fleksibilitas, skalabilitas, storage bakend, network type, dsb untuk menginstall isi container. Dalam mengelola containernya, LXD menggunakan REST API.


---

### **3. Docker Environtment Lab**
Untuk membangun Docker dan melakukan Hands-on Lab yang disediakan oleh pihak **Akademi Digital Nusantara (ADINUSA)** pada materi Docker Fundamental, diperlukan 2 VM dengan spesifikasi berikut:
![image](https://hackmd.io/_uploads/Hk9Tduqaa.png)
Langkah yang perlu dilakukan untuk memilikinya ialah:
1. Mengunduh VirtualBox versi 7 atau terbaru, [temukan di sini](https://www.virtualbox.org/wiki/Downloads)
2. Mengunduh Ubuntu 22.04 OS melalui [OneDrive](https://btech18-my.sharepoint.com/:u:/g/personal/former_btech_id/Ec4u2MV5GIlIs-lnNSLCcToBsHLL3YloleXuZjN41nLvDA?e=XuXOby), [GoogleDrive](https://drive.google.com/file/d/18myvWc4yZIphCNK-KaOz3WLCjtQrkOJw/view?usp=sharing), [MediaFire](https://www.mediafire.com/file/vpozznfpdxt71oy/BTA-Server.ova/file).
3. Mengatur NAT Network melalui <kbd>Tools</kbd> option pada VirtualBox, dan mengaturnya sebagaimana berikut:![image](https://hackmd.io/_uploads/BkVTJccp6.png)
4. Mengatur Host-Only Network sebagaimana berikut: ![image](https://hackmd.io/_uploads/HJ31x59Ta.png)
5. Import VM melalui <kbd>File</kbd> kemudian pilih <kbd>Import Appliance</kbd> dan pilih file Ubuntu 22.04 yang telah diinstall serta ubah nama menjadi Docker-Node01, sebagaimana berikut:![image](https://hackmd.io/_uploads/rJj8x556T.png)
![image](https://hackmd.io/_uploads/rJhPg99pp.png)
6. Melakukan clone pada Docker-Node01, dan ubah nama file clone menjadi Docker-Node02 sebagaimana berikut:![image](https://hackmd.io/_uploads/Hkwhgccap.png)
![image](https://hackmd.io/_uploads/B1kaxccT6.png)
![image](https://hackmd.io/_uploads/rJQagqqpT.png)
7. Menjalankan Docker-Node01 dan Docker-Node02, serta memasukkan **user: student** dan **password: Adinusa2023**.
8. Melakukan Network Configuration pada masing-masing VM, dalam file /etc/netplan/50-cloud-init.yaml, dan mengisinya dengan konfigurasi sebagai berikut:
![Docker-Node01 [Running] - Oracle VM VirtualBox 09_03_2024 16_56_09](https://hackmd.io/_uploads/SJLFb5cpp.png)
10. Menjalankan sintaks `sudo netplan apply` untuk menjalankan konfigurasi network terbaru.
11. Mengubah hostname dengan sintaks `sudo hostnamectl set-hostname pod-username-node01` pada Docker-Node01 dan sintaks `sudo hostnamectl set-hostname pod-username-node02` pada Docker-Node02, sebagaimana berikut: ![eda01ef3-9d8f-4e16-92ca-b09ec1626dc4](https://hackmd.io/_uploads/HJYnzc5pT.png)![11086d20-7dd7-4cce-91f3-ee1c693e6856](https://hackmd.io/_uploads/r1UxX5c6a.png)
12. Menambahkan host ke dalam file /etc/hosts dengan sintaks `sudo nano /etc/hosts`pada masing-masing Docker-Node01 dan Docker-Node02, sebagaimana berikut:![Screenshot 2024-03-10 085736](https://hackmd.io/_uploads/BkkhQqqTa.png)
13. Membuat dan mendistribusikan SSH Keygen pada Docker-Node01 dan Docker-Node02, dengan sintaks pada `ssh-keygen -t rsa`, sebagaimana berikut: ![copy](https://hackmd.io/_uploads/rknUS5caT.png)
![Docker-Node01 [Running] - Oracle VM VirtualBox 10_03_2024 09_03_21](https://hackmd.io/_uploads/B1TNH996T.png)
13. Menyalin public key ke semua node dengan sintaks `ssh-copy-id student@pod-username-node01` dan sintaks `ssh-copy-id student@pod-username-node02`, sebagaimana berikut:![Docker-Node02 [Running] - Oracle VM VirtualBox 09_03_2024 18_19_23](https://hackmd.io/_uploads/SJUVL55p6.png)
 ![Docker-Node02 [Running] - Oracle VM VirtualBox 09_03_2024 18_18_36](https://hackmd.io/_uploads/ByakUq96T.png)
14. melakukan check pada host bisa mengakses tanpa password dengan sintaks `ssh student@pod-username-node01 "whoami; hostname"` dan sintaks `ssh student@pod-username-node02 "whoami; hostname"`di kedua VM, sebagaimana berikut:![Screenshot 2024-03-10 091048](https://hackmd.io/_uploads/rk36U99pa.png)
![Screenshot 2024-03-10 091100](https://hackmd.io/_uploads/HJgRUc9pT.png)
15. Melakukan konfigurasi nusactl (Docker Fundamental Learning from Adinusa) dengan membuat file /home/student/.nusactl/hosts.yaml pada Docker-Node01 dan mengisinya dengan konfigurasi berikut:![Docker-Node02 [Running] - Oracle VM VirtualBox 09_03_2024 18_27_20](https://hackmd.io/_uploads/SJ-UD9qTp.png)
16. Mengotomasi ssh saat masuk dengan sintaks `sudo apt install -y keychain && echo "eval $(keychain -q --eval id_rsa)" >> ~/.bashrc && source ~/.bashrc`, sebagaimana berikut: ![Docker-Node01 [Running] - Oracle VM VirtualBox 09_03_2024 18_33_56](https://hackmd.io/_uploads/S16nwccaT.png)

Dengan ini, lingkungan untuk membangun dan menjalankan Docker telah siap untuk digunakan.



---

## **Docker**
### **1. Docker Overview**
**Docker** merupakan perusahaan yang menawarkan layanan konsultasi untuk container aplikasi dengan pengembangan Docker Community Edition (**CE**) dan Docker Enterprise Edition (**EE**) berdasarkan Service Level Agreement (SLA).

Layanan **Docker** **CE** merupakan layanan gratis dengan produk seperti Docker Toolbox dan Docker for Desktop dengan target pada developer. Docker ini mudah untuk diinstal guna membangun, debug, dan menguji aplikasi di dalamnya, dan terintegrasi dengan hypervisor framework, network, dan filesystem. Layanan ini memiliki upgrade versi dua tahunan dengan pemeliharaan selama tujuh bulan sekali.

Sedangkan pada layanan **Docker EE**, menawarkan Universal Control Plane (UCP) dan Docker Trusted Registry (DTR), dengan komponen role-based access control (RBAC), multi-tenancy, mixed clusters of Docker swarm and Kubernetes, web-based UI, and content trust. Perbedaan Layanan Docker CE dan Docker EE secara singkat: ![image](https://hackmd.io/_uploads/BJfAoY9pT.png)

**Docker** menyediakan **layanan** gratis maupun berbayar. Layanan gratis ini disediakan untuk penggunaan pribadi, edukasi, dan non-comersial. Untuk layanan berbayar sediri, menyediakakn paket pro, team, dan business, dengan detail sebagai berikut:
![image](https://hackmd.io/_uploads/ByDM0YqTp.png)


---

### **2. Instalasi Docker**
Dalam bagian ini, akan **menginstal** **Docker** dan dependency tools yang diperlukan ke dalam pod-syafaa-node01 dan pod-syafaa-node02. Lakukan instalasi ini pada masing-masing node. Berikut ialah langkah untuk melakukan instalasi Docker:
1. Melakukan update VM pada Docker-Node01 dan Docker-Node02, dengan sintaks: 
```
sudo apt-get update
```
![Screenshot 2024-03-10 092110](https://hackmd.io/_uploads/HJIixsCp6.png)![Screenshot 2024-03-10 101526](https://hackmd.io/_uploads/Hy2JGj0pa.png)

2. Melakukan instalasi paket-paket yang diperlukan, seperti ca-certificates (sertifikat otoritas sertifikasi), curl (transfer data dengan URL), gnupg (enkripsi dan signature), dan lsb-release (informasi rilis distribusi Linux), dengan sintaks berikut:
```
sudo apt-get install ca-certificates curl gnupg lsb-release -y
```
![Screenshot 2024-03-10 092153](https://hackmd.io/_uploads/HJDBbsAaT.png)![WhatsApp Image 2024-03-13 at 11.30.17_18531be3](https://hackmd.io/_uploads/SkeCXhoAap.jpg)

3. Membuat direktori baru dengan menentukan hak akses menuju direktori ini, dengan sintaks berikut:
```
sudo mkdir -m 0755 -p /etc/apt/keyrings
```
4. Mengunduh dan menyimpan kunci publik Docker GPG ke dalam direktori "/etc/apt/keyrings/" dengan sintaks berikut:
```
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
```  
-fsSL merupakan opsi-opsi untuk melakukan pengunduhan dengan mendeteksi kegagalan sebagai fail, dijalankan diam-diam (silent), menapmpilkan kegagalan , dan mengikuti URL secara otomatis. Sebagaimana berikut: ![Screenshot 2024-03-10 093632](https://hackmd.io/_uploads/rJ2m9sCTa.png) ![WhatsApp Image 2024-03-13 at 11.30.29_cbb74c6a](https://hackmd.io/_uploads/rka4noCaa.jpg)

5.  Menambahkan konfigurasi baru ke dalam file repositori APT ke dalam folder khusus (/etc/apt/sources.list.d/docker.list) dari repositori Docker yang diinput untuk arsitektur distribusi  yang sedang berjalan, dengan sintaks berikut: 
```
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```  
Menjalankannya sebagaimana berikut:![Screenshot 2024-03-10 094230](https://hackmd.io/_uploads/S1hrciAaa.png)![Screenshot 2024-03-10 102216](https://hackmd.io/_uploads/rkeuni0pa.png)

6. Melakukan update pada vm untuk menjalankan semua konfigurasi yang dilakukan, dengan sintaks berikut:
```
sudo apt-get update
```
9. Melakukan instalasi docker beserta dependencynya, dengan sintaks berikut: 
```
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y`
```
![Screenshot 2024-03-10 100642](https://hackmd.io/_uploads/S1wPqjR66.png)![Screenshot 2024-03-10 102357](https://hackmd.io/_uploads/Sk2_hiRaT.png)

10. Melihat versi docker yang terinstal , dengan sintaks berikut: 
```
docker version
```
![Screenshot 2024-03-10 100920](https://hackmd.io/_uploads/Hk1d9sR66.png)![Screenshot 2024-03-10 102621](https://hackmd.io/_uploads/SyXKhiCap.png)

11. Melihat informasi detail mengenai docker yang terinstal , dengan sintaks berikut:
```
docker info
```
![Screenshot 2024-03-10 100953](https://hackmd.io/_uploads/HJr_qsRpT.png)![Screenshot 2024-03-10 102703](https://hackmd.io/_uploads/Hk9FniCT6.png)

12. Menambahkan pengguna non-root saat ini ke dalam akses docker, dengan sintaks berikut:
```
groupadd docker
sudo usermod -aG docker $USER
sudo chmod 666 /var/run/docker.sock
```
![Screenshot 2024-03-10 101159](https://hackmd.io/_uploads/HJ3_csR6a.png)![Screenshot 2024-03-10 102759](https://hackmd.io/_uploads/rJSiniCpT.png)

13. Melakukan tes pada Docker yang sudah diinstal , dengan sintaks berikut:
```
docker run registry.adinusa.id/btacademy/hello-world
```
![Screenshot 2024-03-10 102845](https://hackmd.io/_uploads/HkVh2sRTT.png)

14. Menampilkan image yang ada , dengan sintaks berikut:
```
docker image ls
```
![Screenshot 2024-03-10 101227](https://hackmd.io/_uploads/B1eY5s06p.png)![WhatsApp Image 2024-03-13 at 11.35.21_254e6017](https://hackmd.io/_uploads/Sy3SToAp6.jpg)

15. Menampilkan semua container Docker yang ada, dengan sintaks berikut:
```
docker container ls -a
``` 
![Screenshot 2024-03-10 101311](https://hackmd.io/_uploads/SymKqoR6p.png)![WhatsApp Image 2024-03-13 at 11.35.39_ca786214](https://hackmd.io/_uploads/HJv8TsRaa.jpg)


---

### **3. Hands-On Managing Docker**
Setelah melakukan instalasi Docker, maka, kita sudah bisa menjalankan Docker tersebut. ADINUSA, platfrom belajar Docker Fundamental, menyediakan lab sebagai sarana latihan secara langsung. Berikut untuk detail tiap lab yang saya jalankan:
#### **Lab 2.2 -1**

Pada bagian pertama, berfokus pada mengakses serta dapat menjalankan redis yang dijalankan pada node01. Berikut ialah langkah yang perlu dilakukan:
1. Mencari image redis dari docker hub dan dari harbor dengan sintaks berikut:
```
docker search redis 
skopeo list-tags docker://registry.adinusa.id/btacademy/redis
``` 
![Screenshot 2024-03-10 114359](https://hackmd.io/_uploads/SkWRB7y06.png)
![Screenshot 2024-03-10 114506](https://hackmd.io/_uploads/r1mGLXyRp.png)

2. Menjalankan image redis, dengan sintaks berikut:
```
docker run registry.adinusa.id/btacademy/redis
docker run -d registry.adinusa.id/btacademy/redis 
docker run -d --name redis1 registry.adinusa.id/btacademy/redis
```
![Screenshot 2024-03-10 120635](https://hackmd.io/_uploads/HkGkr410p.png)
![Screenshot 2024-03-10 120740](https://hackmd.io/_uploads/ryUeBEyCT.png)

3. Menampilkan container yang berjalan, dengan sintaks berikut:
```
docker ps 
docker container ls
```
![Screenshot 2024-03-10 120813](https://hackmd.io/_uploads/rJLOH4yRp.png)

5. Menampilkan deskripsi detail dari container redis1, dengan sintaks berikut:
```
docker inspect redis1
```
![Screenshot 2024-03-10 121214](https://hackmd.io/_uploads/HyjqBEyRa.png)

6. Menampilkan logs dari container redis1, dengan sintaks berikut:
```
docker logs redis1
```
![Screenshot 2024-03-10 121254](https://hackmd.io/_uploads/S1WiS4y0p.png)
7. Menampilkan live resource yang digunakan di container redis1, dengan sintaks berikut:
```
docker stats redis1
```
![Screenshot 2024-03-10 121321](https://hackmd.io/_uploads/HkwsSEk0T.png)

8. Menampilkan proses berjalannya container redis1, dengan sintaks berikut:
```
docker top redis1
```
![Screenshot 2024-03-10 121345](https://hackmd.io/_uploads/SyJRHV1Ca.png)

9. Menonaktifkan container redis1, dengan sintaks berikut:
```
docker stop redis1
```
![Screenshot 2024-03-10 121404](https://hackmd.io/_uploads/SyRkINyRp.png)

---
#### **Lab 2.3**
Pada bagian ini berfokus pada membuat container baru untuk nginx1 dan nginx2 dan melakukan curl pada keduanya, Berikut ialah langkah yang perlu dilakukan:
1. Mencari image nginx dari DockerHub dan Harbor dengan sintaks berikut:
```
docker search nginx
skopeo list-tags docker://registry.adinusa.id/btacademy/nginx
```
![Screenshot 2024-03-10 121435](https://hackmd.io/_uploads/HJceI41Rp.png)
![Screenshot 2024-03-10 121545](https://hackmd.io/_uploads/ByTlUNkC6.png)

2. Menjalankan image nginx1 dan meneruskan dari port host ke container,  dengan sintaks berikut:
```
docker run -d --name nginx1 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
``` 
![Screenshot 2024-03-10 121708](https://hackmd.io/_uploads/SkwZI4JAp.png)

3. Menampilkan deskripsi dari container nginx1,  dengan sintaks berikut:
```
docker inspect nginx1
```
![Screenshot 2024-03-10 121737](https://hackmd.io/_uploads/BknbINyAa.png)

4. Menjalankan image nginx2 dan mendeklarasikan port container,  dengan sintaks berikut:
```
docker run -d --name nginx2 -p 80 registry.adinusa.id/btacademy/nginx:latest
```
![Screenshot 2024-03-10 121821](https://hackmd.io/_uploads/ByPfLVyAp.png)

5. Melakukan uji coba curl,  dengan sintaks berikut:
```
curl localhost:$(docker port nginx2 80 | cut -d : -f 2)
```
![Screenshot 2024-03-10 121930](https://hackmd.io/_uploads/B1CfUEJRa.png)

6. Menampilakn container yang ada,  dengan sintaks berikut:
```
docker ps -a 
docker container ls -a
```
![Screenshot 2024-03-10 121953](https://hackmd.io/_uploads/Skq4UVk0p.png)
![Screenshot 2024-03-10 122025](https://hackmd.io/_uploads/r1h484k0a.png)

7. Menampilkan image Docker yang ada,  dengan sintaks berikut:
```
docker images
```
![Screenshot 2024-03-10 122047](https://hackmd.io/_uploads/HkLBLEJA6.png)
---
#### **Lab 2.3 -1**
Pada bagian ini berfokus pada mengakses dengan curl ke nginx1 dan nginx2, Berikut ialah langkah yang perlu dilakukan:
1. Mencari image nginx dari DockerHub dan Harbor dengan sintaks berikut: 
```
docker search nginx
skopeo list-tags docker://registry.adinusa.id/btacademy/nginx
```
![Screenshot 2024-03-10 122548](https://hackmd.io/_uploads/SylU8LNkR6.png)
![Screenshot 2024-03-10 122621](https://hackmd.io/_uploads/S1tI84yAT.png)

2. Menjalankan image nginx1 dan meneruskan dari port host ke container,  dengan sintaks berikut:
```
docker run -d --name nginx1 -p 8080:80 registry.adinusa.id/btacademy/nginx:latest
```
![Screenshot 2024-03-10 122811](https://hackmd.io/_uploads/SkmvLEJAa.png)

3. Menampilkan deskripsi dari container nginx1, dengan sintaks berikut:
```
docker inspect nginx1
```
![Screenshot 2024-03-10 122837](https://hackmd.io/_uploads/rkdDUVJRa.png)

4. Menjalankan image nginx2 dan meneruskan dari port host ke container,  dengan sintaks berikut:
```
docker run -d --name nginx2 -p 8081:80 registry.adinusa.id/btacademy/nginx:latest
```
![Screenshot 2024-03-10 122910](https://hackmd.io/_uploads/HJkdUNkCa.png)

5. Menampilkan container yang ada, dengan sintaks berikut:
```
docker ps -a 
docker container ls -a
```
![Screenshot 2024-03-10 122955](https://hackmd.io/_uploads/HJuOI4JRa.png)

6. Melakukan output dengan curl dari nginx1 dan nginx2, dengan sintaks berikut:
```
curl localhost:8080
curl localhost:8081
```
![Screenshot 2024-03-10 123031](https://hackmd.io/_uploads/S1vtPAXAa.png)
![Screenshot 2024-03-10 123103](https://hackmd.io/_uploads/rywjUV1CT.png)

7. Mengakses dalam container, dengan sintaks berikut:
```
docker exec -it nginx2 /bin/bash
``` 
![Screenshot 2024-03-10 123158](https://hackmd.io/_uploads/Syr3LN1CT.png)

8. Melakukan update dan instal nano di dalam container, dengan sintaks berikut:
```
apt-get update -y && apt-get install nano -y
```
![Screenshot 2024-03-10 123210](https://hackmd.io/_uploads/rJRnU4yAa.png)

9. Mengedit index.html dan memindahkannya  ke direktori /usr/share/nginx/html, dengan sintaks berikut:
```
nano index.html
```
![Screenshot 2024-03-10 123250](https://hackmd.io/_uploads/BkHp84yC6.png) 
![Screenshot 2024-03-10 123356](https://hackmd.io/_uploads/H1GWP4JAT.png)

10. Memulai ulang sevice nginx, dengan sintaks berikut:
```
service nginx restart
```
![Screenshot 2024-03-10 123421](https://hackmd.io/_uploads/HkjGPNJ0T.png)

11. Menjalankan container nginx2, dengan sintaks berikut:
```
docker start nginx2
```
![Screenshot 2024-03-10 123445](https://hackmd.io/_uploads/ryhQw4JCT.png)

12. Menampilkan container yang berjalan, dengan sintaks berikut:
```
docker ps
docker container ls
```
![Screenshot 2024-03-10 123511](https://hackmd.io/_uploads/B1HNP4JCp.png)

13. Melakukan output nginx1 dan nginx2 dengan perintah curl, dengan sintaks berikut:
```
curl localhost:8080
curl localhost:8081
```
![Screenshot 2024-03-10 123532](https://hackmd.io/_uploads/Hy7Sw4J0a.png)
![Screenshot 2024-03-10 123552](https://hackmd.io/_uploads/r1BSwEyA6.png)

14. Menampilkan deskripsi container nginx1 dan nginx2, dengan sintaks berikut:
```
docker inspect nginx1
docker inspect nginx2
```
![Screenshot 2024-03-10 123609](https://hackmd.io/_uploads/SJkLDNkRp.png) ![Screenshot 2024-03-10 123625](https://hackmd.io/_uploads/SJJwwEy0T.png)

15. Menampilkan logs content dari container nginx1 dan nginx2, dengan sintaks berikut:
```
docker logs nginx1
docker logs nginx2
```
![Screenshot 2024-03-10 123701](https://hackmd.io/_uploads/B1X_DEyC6.png)
![Screenshot 2024-03-10 123711](https://hackmd.io/_uploads/S1H_wNkCa.png)

16. Menampilkan live resource yang digunakan dalam container, dengan sintaks berikut:
```
docker stats nginx1
docker stats nginx2
```
![Screenshot 2024-03-10 123701](https://hackmd.io/_uploads/HysNOVy0T.png)
![Screenshot 2024-03-10 123711](https://hackmd.io/_uploads/HkA4_N10a.png)

17. Menampilkan proses yang berjalan dalam container, dengan sintaks berikut:
```
docker top nginx1
docker top nginx2
```
![Screenshot 2024-03-10 123733](https://hackmd.io/_uploads/S1NSdEJAa.png)

---
#### **Lab 2.3 -2**
Pada bagian ini berfokus pada membuat container ubuntu1, Berikut ialah langkah yang perlu dilakukan:
1. Mencari image ubuntu dari DockerHub dan Harbor dengan sintaks berikut:
```
docker search ubuntu 
skopeo list-tags docker://registry.adinusa.id/btacademy/ubuntu
```
![Screenshot 2024-03-10 123814](https://hackmd.io/_uploads/ryc0uVJCp.png)
![Screenshot 2024-03-10 123848](https://hackmd.io/_uploads/HkA0dEk0p.png)

2. Mengambil image ubuntu dari harbor, dengan sintaks berikut:
```
docker pull registry.adinusa.id/btacademy/ubuntu
```
![Screenshot 2024-03-10 123957](https://hackmd.io/_uploads/SkUbYVk0a.png)

3. Menjalankan container ubuntu1 dan mengakses console container, dengan sintaks berikut:
```
docker run -it --name ubuntu1 registry.adinusa.id/btacademy/ubuntu
```
![Screenshot 2024-03-10 124220](https://hackmd.io/_uploads/Hkkd54y0T.png)

4. Menjalankan container ubuntu2 dan lalu menghapusnya, dengan sintaks berikut:
```
docker run -it --rm --name ubuntu2 registry.adinusa.id/btacademy/ubuntu
```
![Screenshot 2024-03-10 124230](https://hackmd.io/_uploads/BJcdqEJCa.png)


---
#### **Lab 2.4 -1**
Pada bagian ini berfokus pada menjalankan container mysql, Berikut ialah langkah yang perlu dilakukan:
1. Menjalankan container mysql dengan parameter tambahan, dengan sintaks berikut:
```
docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD=RAHASIA -e MYSQL_DATABASE=latihan05 -p 3306:3306 \
registry.adinusa.id/btacademy/mysql
```
![Screenshot 2024-03-10 124928](https://hackmd.io/_uploads/SkSq9Nk0a.png)

2. Mengambil image phpmyadmin dari harbor, dengan sintaks berikut:
```
docker pull registry.adinusa.id/btacademy/phpmyadmin:latest
```
![Screenshot 2024-03-10 125351](https://hackmd.io/_uploads/ByMiqVkRT.png)

3. Menjalankan container phpmyadmin dan menghubungkan dengan mysql container, dengan sintaks berikut:
```
docker run --name my-phpmyadmin -d --link my-mysql:db -p 8090:80 \
registry.adinusa.id/btacademy/phpmyadmin
```
![Screenshot 2024-03-10 125621](https://hackmd.io/_uploads/B1Q3cVkRa.png)

4. Melakukan uji coba browsing, dengan mengakses `http://10.10.10.11:8090`, sebagaimana berikut:
![Screenshot 2024-03-16 153936](https://hackmd.io/_uploads/Hy3KqC7AT.png)
___
#### **Lab 2.4 -2**
Pada bagian ini berfokus pada menjalankan container mysql, Berikut ialah langkah yang perlu dilakukan:
1. Menjalankan container ubuntu1 dan ubuntu2 dengan sintaks berikut:
```
docker run -dit --name ubuntu1 registry.adinusa.id/btacademy/ubuntu
docker run -dit --name ubuntu2 registry.adinusa.id/btacademy/ubuntu
```
![Screenshot 2024-03-10 130936](https://hackmd.io/_uploads/BJ_pqEJCp.png)

2. Menampilkan daftar container yang ada, dengan sintaks berikut:
```
docker ps
```
![Screenshot 2024-03-10 130954](https://hackmd.io/_uploads/ry1RcV106.png)
3. Menghentikan sementara container ubuntu1 dan ubuntu2, dengan sintaks berikut:
```
docker pause ubuntu1
docker pause ubuntu2
```
![Screenshot 2024-03-10 131016](https://hackmd.io/_uploads/ryL054kC6.png)

4. Melihat status masing-masing ubuntu untuk memastikan pause berhasil dijalankan, dengan sintaks berikut:
```
docker ps
```
![Screenshot 2024-03-10 131034](https://hackmd.io/_uploads/HyRRqN106.png)

5. Melihat penggunaan resource saat container dihentikan sementara, dengan sintaks berikut:
```
docker stats ubuntu1
docker stats ubuntu2
```
![Screenshot 2024-03-10 131059](https://hackmd.io/_uploads/SyH1oEy06.png)![Screenshot 2024-03-10 131109](https://hackmd.io/_uploads/Syo1sEJRa.png)

6. Menjalankan kembali layanan container ubuntu1, dengan sintaks berikut:
```
docker unpause ubuntu1
```
![Screenshot 2024-03-10 131130](https://hackmd.io/_uploads/BJBxjNk0a.png)

---
#### **Lab 2.4 -3**
Pada bagian ini berfokus pada mengakses wordpress, Berikut ialah langkah yang perlu dilakukan:
1. Membuat database container dengan mengatur spesifikasi, dengan sintaks berikut:
```
docker container run -d --name ch6_mariadb --memory 256m --cpu-shares 1024 --cap-drop net_raw \
 -e MYSQL_ROOT_PASSWORD=test registry.adinusa.id/btacademy/mariadb:5.5
```
![Screenshot 2024-03-10 131537](https://hackmd.io/_uploads/r1LXiE1A6.png)

2. Membuat container wordpress dan menghubungkannya dengan container database, dengan sintaks berikut:
```
docker container run -d -p 80:80 -P --name ch6_wordpress  --memory 512m --cpu-shares 512 \
--cap-drop net_raw --link ch6_mariadb:mysql -e WORDPRESS_DB_PASSWORD=test \
registry.adinusa.id/btacademy/wordpress:5.0.0-php7.2-apache
```
![Screenshot 2024-03-10 132109](https://hackmd.io/_uploads/HyQ4jEJAT.png)

3. Menampilkan logs status dari container database dan container wordpress, dengan sintaks berikut:
```
docker logs ch6_mariadb
docker logs ch6_wordpress
```
![Screenshot 2024-03-10 132220](https://hackmd.io/_uploads/SyxpsE10a.png)

4. Menampilkan proses yang berjalan pada container database dan wordpress, dengan sintaks berikut:
```
docker top ch6_mariadb
docker top ch6_wordpress
```
![Screenshot 2024-03-10 132237](https://hackmd.io/_uploads/BJUTjVyRp.png)
5. Menampilkan penggunaan live resource pada container, dengan sintaks berikut:
```
docker stats ch6_mariadb
docker stats ch6_wordpress
```
![Screenshot 2024-03-10 132253](https://hackmd.io/_uploads/B1naoNyA6.png)
![Screenshot 2024-03-10 132311](https://hackmd.io/_uploads/S1PRsE1A6.png)

6. Melakukan uji coba browsing dengan http://10.10.10.11.
![Screenshot 2024-03-16 154030](https://hackmd.io/_uploads/S1w1n0XRa.png)


---

## **Managing Docker**
### **1. Command yang biasa digunakan** 
Agar bisa membuat ataupun mengelola container, maka **Docker client** memiliki **command** yang dapat dijalankan oleh docker dalam mengelola container. Sebagai gambaran, berikut adalah proses yang biasanya dilakukan oleh client beserta commandnya:![image](https://hackmd.io/_uploads/B1RXiQTp6.png)
Jika gambar tersebut menunjukkan command untuk mengelola container, maka gambar berikut berisi command untuk mengetahui **informasi** seputar container: ![image](https://hackmd.io/_uploads/Bycjj7app.png)
1. Membuat Container baru, dengan sintaks 
```
docker run -d --name [custom-name] [containerimage]
```
2. Membuat container baru, sekaligus mengeksekusi bash shell, dengan sintaks:
```
docker run --name [custom-name] -it [containerimage] /bin/bash
```
3. Menjalankan proses tambahan di dalam container, dengan sintaks: 
```
docker exec [custom-name] cat [specifyfile]
```
4. Menampilkan daftar container yang berjalan, dengan sintaks:
```
docker ps
```
Didalamnya terdapat informasi sebagai berikut:
```
ubuntu@ubuntu20:~$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
2ef4addadf8b        nginx               "/docker-entrypoint.…"   18 hours ago        Exited (137) 18 hours ago                       busy_newton
9aa8f1ff1c03        nginx               "/docker-entrypoint.…"   21 hours ago        Up 21 hours                 80/tcp              my-nginx-container
```
* Container ID menunjukkan angka hexadecimal yang bersifat unix.
* Image, container image yang digunakan untuk memulai container.
* Command, perintah yang dieksekusi ketika container dijalankan.
* Created, informasi tanggal dan waktu pembuatan container.
* Status, total container uptime maupun sejak container dihentikan.
* Port, menampilkan informsi port yang digunakan maupun yang diteruskan pada container.
* Names, nama dari container.
5. Menampilkan daftar container yang berjalan maupun berhenti, dengan sintaks 
```
docker inspect namecontainer
```
Contoh output yang ditampilkan:
```
ubuntu@ubuntu20:~$ docker inspect my-nginx-container
[
    {
        "Id": "9aa8f1ff1c0399cbb24b657de6ce0a078c7ce69dc0c07760664670ea7593aaf3",
...OUTPUT OMITTED....
"NetworkSettings": {
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "9e91a2e58d8a7c21532b0a48bb4d36093a347aa056e85d5b7f3941ff19eeb840",
                    "EndpointID": "9d847b45ad4c55b2c1fbdaa8f44a502f2215f569c08cbcc6599b6ff1c25a2869",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
...OUTPUT OMITTED....
```
6. Menampilkan daftar container yang berjalan maupun berhenti dalam format string untuk mengambil data tertentu, dengan sintaks:
```
docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)
```
contoh output yang ditampilkan:
```
ubuntu@ubuntu20:~$ docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)
/busy_newton - 
/my-nginx-container - 172.17.0.2
```
7. Menghentikan container yang sedang berjalan dengan baik, menggunakan sintaks 
```
docker stop my-nginx-container
```
8. Menghentikan container yang sedang berjalan dengan paksa, menggunakan sintaks 
```
docker kill my-nginx-container
```
9. Menghentikan container yang sedang berjalan dengan signal tertentu:
```
docker kill -s SIGNAL containername
```
Berikut ialah daftar signal dan aksinya:

| Signal	|   Default action  |	      Description         |
| :-------: | :---------------: | :-------------------------: |
| SIGHUP	| Terminate process	| Terminate line hangup       |
| SIGINT	| Terminate process	| Interrupt program           | 
| SIGQUIT   | Create core image	| Quit program                |
| SIGABRT   | Create core image	| Abort program               |
| SIGKILL   | Terminate process	| Kill program                |
| SIGTERM   | Terminate process	| Software termination signal |
| SIGUSR1   | Terminate process	| User-defined signal 1       |
| SIGUSR2   | Terminate process	| User-defined signal 2       |

10. Memulai kembali container yang dihentikan, dengan sintaks:
```
docker restart my-nginx-container
```
11. Menghapus container berdasarkan nama container, dengan sintaks 
```
docker rm my-nginx-container
```
12. Menghapus seluruh container secara bersamaan, dengan sintaks
```
docker rm $(docker ps -aq)
```


---

### **2. Registry** 
**Registry** merupakan tempat penyimpanan image yang terpusat, di dalamnya terdapat image stack seperti php, mysql, nginx, dsb. bahkan image dari pihak ketiga. Registry sendiri terdiri atas 2 jenis berdasarkan pada akses penggunaannya. Berikut ialah penjelasan lebih lanjut:
#### **Public Registry**
Sebuah layanan yang merupakan tempat penyimpanan image yang dapat diunduh dan digunakan oleh siapapun, baik yang terdaftar maupun yang tidak.
Salah satu penyedia layanan public registry ialah **DockerHub** bagian dari **Docker Registry**, yaitu sistem penyimpanan dan pendistribusian untuk image Docker yang diberi nama, dalam beberapa versi. Sehingga memungkinkan pengguna Docker  untuk menarik (`pull`) image dan memasukkan image baru ke registry.
#### **Private Registry**
Sebuah layanan repository untuk menyimpan dan mengelola Docker pribadi, yang dapat dihosting oleh pribadi atau penyedia layanan pihak ketiga. Jika public registry tidak membatasi penggunaan image yang disediakan, maka pada **private registry** memastikan pengunduhan dan penggunaan image hanya dapat dilakukan oleh pengguna berwenang. Bahkan pengempang dapat mengontrol siapa yang memiliki akses ke image. Salah satu contoh penyedia layanan public registry ialah **Harbour**, opensource registry yang mengamankan image dengan policy dan control akses, signature image, dan memastikan image bebas dari kerentanan. 


---

### **3. Docker Volume**
**Volume** adalah mekanisme yang dipilih untuk menyimpan data yang dihasilkan dan digunakan oleh container Docker. Berbeda dengan bind mount yang mengaitkan direktori dari host OS ke sebuah container, volume lebih mudah untuk dicadangkan dan dipindahkan. Selain itu, **Driver volume** memungkinkan pengguna untuk manyimpan volume di host remote atau cloud, serta mengelola volume menggunakan perintah docker CLI atau Docker API.
Ketika mengirimkan sebuah container menggunakan driver volume ini, maka pengguna mengabstraksi sistem penyimpanan menggunakan **logika**, sehingga dapat diadaptasi meskipun dengan driver lain.
Berikut ialah contoh penggunaan volume dengan driver volume:
Langkah awal ialah menginstal plugin vieux/sshfs, dengan sintaks berikut:
```
$ docker plugin install --grant-all-permissions vieux/sshfs
```
- Membuat volume menggunakan driver volume, dengan sintaks berikut:
```
$ docker volume create --driver vieux/sshfs \
  -o sshcmd=test@node2:/home/test \
  -o password=testpassword \
  sshvolume
```
- Menjalankan container dengan volume dari driver volume, dengan sintaks berikut:
```
$ docker run -d \
  --name sshfs-container \
  --volume-driver vieux/sshfs \
  --mount src=sshvolume,target=/app,volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \
  nginx:latest
```
- Membuat layanan yang membuat **volume NFS**, Contoh ini menggunakan 10.0.0.10 sebagai server NFS dan /var/docker-nfs sebagai direktori yang diekspor pada server NFS, dengan sintaks berikut:
*NFSV3*
```
$ docker service create -d \
  --name nfs-service \
  --mount 'type=volume,source=nfsvolume,target=/app,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/var/docker-nfs,volume-opt=o=addr=10.0.0.10' \
  nginx:latest
```
*NFSV4*
```
$ docker service create -d \
    --name nfs-service \
    --mount 'type=volume,source=nfsvolume,target=/app,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/var/docker-nfs,"volume-opt=o=addr=10.0.0.10,rw,nfsvers=4,async"' \
    nginx:latest
```
- Membuat **volume CIFS/Samba** tanpa mengkonfigurasi titik pemasangan di host, dengan sintaks berikut:
```
docker volume create \
    --driver local \
    --opt type=cifs \
    --opt device=//uxxxxx.your-server.de/backup \
    --opt o=addr=uxxxxx.your-server.de,username=uxxxxxxx,password=*****,file_mode=0777,dir_mode=0777 \
    --name cif-volume
```
- Melakukan **pencadangan** container dbstore, dengan sintaks berikut:
```
$ docker run -v /dbdata --name dbstore ubuntu /bin/bash
```
kemudian menjalankan container baru dbstore, memasang volume dari dbstore, menentukan backup pada /backup, sertakan perintah tar isi volume ke backup, dengan sintaks berikut:
```
$ docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
When the command completes and the container stops, we are left with a backup of our dbdata volume.
```
- **Memulihkan** cadangan container, membuat container baru, misalkan dbstore2 dengan sintaks berikut:
 ```
$ docker run -v /dbdata --name dbstore2 ubuntu /bin/bash
 ```
Kemudian menghapus tar file cadangan, dengan sintaks berikut:
```
$ docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"
```
- Menghapus volume, untuk volume anonim dengan sintaks berikut:
```
$ docker run --rm -v /foo -v awesome:/bar busybox top
```
sedangkan untuk menghapus semua volume, menggunakan sintaks berikut:
```
$ docker volume prune
```


---

### **4. Docker Network**
**Docker network** memungkinkan penggunanya untuk menghubungkan containernya dengan container lain, bahkan saat menggunakan layanan container yang berbeda selama dalam OS yang sama. Untuk menyalakan Docker networking dapat menggunakan **network driver**. Beberapa driver default yang ada, seperti berikut:
- **Bridge**: biasanya digunakan saat aplikasi berjalan pada container mandiri perlu untuk berkomunikasi. ![image](https://hackmd.io/_uploads/HJn3Pak0a.png)
- **Host**: menggunakan jaringan host secara langsung untuk berkomunikasi dengan container. 
- **Overlay**: menghubungkan beberapa daemon container mandiri dan memungkinkan untuk berkomunikasi satu sama lain.![image](https://hackmd.io/_uploads/HJyCDT10T.png)
- **Macvlan**: menetapkan alamat MAC ke dalam container sehingga dapat terhubung ke container melalui jaringan fisik.
- **None**: menonaktifkan semua jaringan bersama dengan driver jaringan khusus.
- **Plugin**: mengintegrasikan Docker dengan network specialized stacks.


---

### **5. Hands-on Managing Container**
Dalam menjalankan hands-on managing container ini, ADINUSA membagi ke dalam beberapa lab dengan fokus tertentu. 
#### **Lab 3.1**
Pada bagian pertama ini berfokus dalam membuat container, terpasang, dan berisi file yang dibuat. berikut ialah langkah untuk menjalankannya:
1. Membuat direktori kerja, dengan sintaks sebagai berikut:
```
cd $HOME
mkdir -p latihan/latihan01-volume
cd latihan/latihan01-volume
```
![Screenshot 2024-03-14 080343](https://hackmd.io/_uploads/rJ8w1DeCa.png)

2. Membuat file dan container untuk data volume dengan nama my-volume, dengan sintaks sebagai berikut:
```
for i in {1..10};do touch file-$i;done
sudo docker create -v /my-volume --name my-volume registry.adinusa.id/btacademy/busybox
sudo docker cp . my-volume:/my-volume 
```
![Screenshot 2024-03-14 080606](https://hackmd.io/_uploads/r1z_1PxCa.png)

3. Memasang volume ke dalam container, dengan sintaks sebagai berikut:
```
docker run --volumes-from my-volume registry.adinusa.id/btacademy/ubuntu ls /my-volume
```
![Screenshot 2024-03-14 080949](https://hackmd.io/_uploads/HkFJykNAT.png)

---
#### **Lab 3.2**
Pada bagian kedua berfokus dalam membuat container, terpasang, dan berisi file yang dibuat. berikut ialah langkah untuk menjalankannya:
1. Membuat direktori kerja baru /data/nfs-storage01/ pada node01, dengan sintaks sebagai berikut:
```
sudo mkdir -p /data/nfs-storage01/
```
![Screenshot 2024-03-14 081204](https://hackmd.io/_uploads/Hk8glPeAT.png)

2. Membuat NFS Server dengan docker pada node01, menggunakan sintaks sebagai berikut:
```
docker run -itd --privileged --restart unless-stopped -e SHARED_DIRECTORY=/data -v /data/nfs-storage01:/data -p 2049:2049 registry.adinusa.id/btacademy/nfs-server-alpine:12
```
![Screenshot 2024-03-14 081640](https://hackmd.io/_uploads/HkPbevlCa.png)

3. Menginstal paket yang dibutuhkan, memasang volume ke NFS client pada node02, dengan sintaks sebagai berikut:
```
ssh 10.7.7.20
sudo apt install nfs-client -y
sudo mount -v -o vers=4,loud 10.7.7.10:/ /mnt
atau
sudo mount -v -t nfs4 10.7.7.10:/ /mnt
df -h

sudo touch /mnt/file1.txt
sudo touch /mnt/file2.txt
exit
```
![Screenshot 2024-03-14 081726](https://hackmd.io/_uploads/Sk1XevxCa.png)
![Screenshot 2024-03-14 081753](https://hackmd.io/_uploads/Hy_XlPgCp.png)
![Screenshot 2024-03-14 081806](https://hackmd.io/_uploads/rJp4evxRp.png)
![Screenshot 2024-03-14 081858](https://hackmd.io/_uploads/HkKrevlAa.png)
![Screenshot 2024-03-14 082001](https://hackmd.io/_uploads/S1LvxPxC6.png)
![Screenshot 2024-03-14 082044](https://hackmd.io/_uploads/rkEFewx06.png)
4. Melakukan verifikasi dengan melihat isi dari /data/nfs-storage01/ pada node01, dengan sintaks sebagai berikut:
```
ls /data/nfs-storage01/
```
![Screenshot 2024-03-14 082105](https://hackmd.io/_uploads/SJ_5lveCa.png)

---
#### **Lab 3.3**
Pada bagian **ketiga** berfokus dalam membuat docker volume, dan ketika menjalankan curl sesuai dengan adinusa, serta dapat menjalankan nginxtest-rovol container dengan read only volume. Berikut ialah langkah untuk menjalankannya dengan dijalankan pada node01:
1. Membuat docker volume, menampilkan daftar docker volume dan menampilkan detail volume my-vol dengan sintaks sebagai berikut: 
```
docker volume create my-vol
docker volume ls
docker volume inspect my-vol
```
![Screenshot 2024-03-14 082243](https://hackmd.io/_uploads/rkDsgPg06.png)![Screenshot 2024-03-14 082303](https://hackmd.io/_uploads/ByERxPgRp.png)
3. Menjalankan containet dengan akses melihat  dan menulis volume, dengan sintaks sebagai berikut: 
```
docker run -d --name=nginx-rwvol -v my-vol:/usr/share/nginx/html -p 4005:80 registry.adinusa.id/btacademy/nginx:latest
```
![Screenshot 2024-03-14 082816](https://hackmd.io/_uploads/r1x1Z-DxRp.png)
4. Menampilkan IP Address dari container, dengan sintaks sebagai berikut: 
```
docker inspect nginx-rwvol | jq -r '.[].NetworkSettings.IPAddress'
```
![Screenshot 2024-03-14 082922](https://hackmd.io/_uploads/BJfEbwgA6.png)
5. Melakukan uji coba browsing pada IP Address container, dengan sintaks sebagai berikut: 
```
curl http://172.17.X.X
```
![Screenshot 2024-03-14 082947](https://hackmd.io/_uploads/S1mvWDxA6.png)
6. Membuat index.html dan memindahkannya ke direktori /var/lib/docker/volumes/my-vol/_data, dengan sintaks sebagai berikut: 
```
sudo echo "This is from my-vol source directory" > index.html
sudo mv index.html /var/lib/docker/volumes/my-vol/_data
```
![Screenshot 2024-03-14 083712](https://hackmd.io/_uploads/HJNxfPgCT.png)
7. Melakukan uji coba browsing ke IP Address container, dengan sintaks sebagai berikut: 
```
curl http://172.17.X.X
```
![Screenshot 2024-03-14 083720](https://hackmd.io/_uploads/BJQGfPeAp.png)
8. Menjalankan container dengan volume read access only, dengan sintaks sebagai berikut: 
```
docker run -d --name=nginx-rovol -v my-vol:/usr/share/nginx/html:ro registry.adinusa.id/btacademy/nginx:latest
```
![Screenshot 2024-03-14 083256](https://hackmd.io/_uploads/SJoq-weRT.png)
9. Melihat nginx-rovol container detail khususnya pada bagian Mount, dengan sintaks sebagai berikut: 
```
docker inspect nginx-rovol | jq '.[].Mounts'
```
![Screenshot 2024-03-14 083326](https://hackmd.io/_uploads/HyDjZPeA6.png)

---
#### **Lab 3.4**

Pada bagian **keempat** berfokus dalam membuat docker volume,dengan driver sshfs, dan memastikan direktory share memiliki file index.html. Berikut ialah langkah untuk menjalankannya dengan dijalankan pada node01:
1. Membuat direktori /share dan membuat file index.html pada node02, dengan sintaks sebagai berikut: 
```
sudo mkdir /share
sudo chmod 777 /share
echo "Hello Adinusa!" > /share/index.html
```
![Screenshot 2024-03-14 084400](https://hackmd.io/_uploads/SkfqfDeA6.png)
2. Melakukan instalasi plugin sshfs dan mengatur plugin sshfs pada node01, dengan sintaks sebagai berikut: 
```
docker plugin install --grant-all-permissions vieux/sshfs
docker plugin ls
docker plugin disable [PLUGIN ID]
docker plugin set vieux/sshfs sshkey.source=/home/student/.ssh/
docker plugin enable [PLUGIN ID]
docker plugin ls 
#Make Sure node01 can ssh passwordless to User student In node02
```
![Screenshot 2024-03-14 084750](https://hackmd.io/_uploads/SkN3zwgR6.png)
![Screenshot 2024-03-14 085148](https://hackmd.io/_uploads/SJPzlJNAp.png)
![WhatsApp Image 2024-03-17 at 10.15.41_c54b89f5](https://hackmd.io/_uploads/H1h_lJVC6.jpg)


3. Membuat docker volume dengan driver sshfs, dengan sintaks sebagai berikut: 
```
docker volume create --driver vieux/sshfs -o sshcmd=student@10.7.7.20:/share  -o allow_other sshvolume
```
![Screenshot 2024-03-14 085443](https://hackmd.io/_uploads/H1GVQPe0T.png)
4. Melakukan uji coba dengan menjalankan container dengan volume dan melakukan uji coba browsing, dengan sintaks sebagai berikut: 
```
docker run -d --name=nginxtest-sshfs -p 8090:80 -v sshvolume:/usr/share/nginx/html registry.adinusa.id/btacademy/nginx:latest
docker ps
curl http://localhost:8090
```
![Screenshot 2024-03-14 090028](https://hackmd.io/_uploads/rkwHmPlRa.png)![Screenshot 2024-03-14 090041](https://hackmd.io/_uploads/ryd8QwxCT.png)

---

#### **Lab 3.5**
Pada bagian **kelima** berfokus dalam membuat bridge antara container apine1 dan dapat menjalankan ping google. Berikut ialah langkah untuk menjalankannya dengan dijalankan pada node01:
1. Menampilkan daftar container, dengan sintaks sebagai berikut: 
```
sudo docker network ls
```
![Screenshot 2024-03-14 090211](https://hackmd.io/_uploads/SymKQDe06.png)

2. Menjalankan container alpine1 dan alpine2 sebagai shell, dengan sintaks sebagai berikut: 
```
docker run -dit --name alpine1 registry.adinusa.id/btacademy/alpine ash
docker run -dit --name alpine2 registry.adinusa.id/btacademy/alpine ash
docker container ls
```
![Screenshot 2024-03-14 090427](https://hackmd.io/_uploads/Byc5QPxRa.png)

3. Menbuat docker baru dan menghubungkannya dengan alpine1, dengan sintaks sebagai berikut: 
```
docker network create --driver bridge bridge1
docker network connect bridge1 alpine1
```
![Screenshot 2024-03-14 090522](https://hackmd.io/_uploads/B1sj7weAa.png)

4. Mengecek IP Address dari alpine2, dengan sintaks sebagai berikut: 
```
docker inspect alpine2  | jq -r '.[].NetworkSettings.IPAddress'
```
![Screenshot 2024-03-14 090600](https://hackmd.io/_uploads/r1Y27wl0p.png)

5. Mengakses alpine1 container, menampilkan IP Address dari container alpine1dengan sintaks sebagai berikut: 
```
docker exec -it alpine1 sh
ip add
```
![Screenshot 2024-03-14 090756](https://hackmd.io/_uploads/rynTmvgCp.png)

6. Melakukan test ping ke internet pada container alpine1, dengan sintaks sebagai berikut: 
```
ping -c 3 8.8.8.8
```
![Screenshot 2024-03-14 090805](https://hackmd.io/_uploads/B1mZ4Pg0T.png)

7. Melakukan tes ping ke IP Address dari alpine2 container, dengan sintaks sebagai berikut: 
```
ping -c 3 172.17.X.X
```
![Screenshot 2024-03-14 090813](https://hackmd.io/_uploads/HJaGNwgAp.png)

8. Menjalankan ping test ke alpine2 container, dengan sintaks sebagai berikut: 
```
ping -c 3 alpine2
```
![Screenshot 2024-03-14 090833](https://hackmd.io/_uploads/B1I7VDlA6.png)

---
#### **Lab 3.6**
Pada bagian **keenam** berfokus dalam mengakses curl localhost. Berikut ialah langkah untuk menjalankannya dengan dijalankan pada node01:
1. Menjalankan container dari nginx image dengan nework host, dengan sintaks sebagai berikut: 
```
docker run -itd --network host --name my_nginx registry.adinusa.id/btacademy/nginx
```
![Screenshot 2024-03-14 095007](https://hackmd.io/_uploads/H1CKEPxAp.png)
2. Melakukan test browsing ke localhost, dengan sintaks sebagai berikut: 
```
curl http://localhost
```
![Screenshot 2024-03-14 095020](https://hackmd.io/_uploads/r1Ui4DlCa.png)
3. Verifikasi IP address dan menghubungkannya dengan port 80, dengan sintaks sebagai berikut: 
```
ip add
sudo netstat -tulpn | grep :80
```
![Screenshot 2024-03-14 095051](https://hackmd.io/_uploads/rJq24wlR6.png)
![Screenshot 2024-03-14 095120](https://hackmd.io/_uploads/Bk16EDlCa.png)



---

## **Docker Image**
### **1. Image Overview**
Pada Linux, semua operating system berbasis filesystem dengan file dan folder disimpan pada localdisk. Konsep ini serupa dengan **image container**, yang merupakan **filesystem** berlapis. Sekaligus menjadi template darimana container dibuat. Berikut ilustrasinya:
![image](https://hackmd.io/_uploads/H1lyLPlAa.png)
Untuk berkomunikasi antar layer, storage driver bertanggung jawab atas hal itu. Meski begitu, image container bersifat **immutable**, yakni ketika telah dibuat maka tidak dapat dilakukan perubahan. Contoh proses komunikasi akan dijelaskan melalui gambar ini:
![image](https://hackmd.io/_uploads/SymmY_g0a.png)
Ketika dijalankan, maka yang pertama dijalankan adalah base image atau layer 1, kemudian dilanjut ke layer atasnya. Untuk berkomunikasi, setiap lapisan hanya berisi delta perubahan yang berkaitan dengan kumpulan lapisan sebelumnya. **Content** setiap lapisan dipetakan ke folder khusus pada sistem host. Keuntungan dari sifat immutable dari image container ini dirasakan oleh pengguna saat menggunakan **image** yang sama secara bersamaan. Lihat pada ilustrasi berikut:
![image](https://hackmd.io/_uploads/Hk-Wc_gR6.png)
Proses ini jauh menghemat **sumber daya** yang dipakai sekaligus memudahkan pengiriman dan pemuatan container.
**Layanan** yang menyediakan Docker image ialah:
1. **Docker Registry**, berikut ilustrasi kerja dari Docker Registry:
![image](https://hackmd.io/_uploads/HJIa9_l06.png)
Melalui layanan ini, pengguna dapat menjadi host dan manage registry pribadi sebagai private, public, atau keduanya. Pengguna dapat menjalankan registry ini menggunakan command dan dapat mengatur skalabilitas sesuai kebutuhan.
2. **Docker Hub**, Docker Hub mendukung kerjasama tim dalam membangun image container. Dengan interface GUI untuk mengelola image tanpa harus mengelola server sekaligus menyiapkan lokasi di cloud untuk lokasi image public ataupun private. Untuk mengunggah image ke DockerHub, dilakukan dengan melakukan pull pada image.


---

### **2. Memanipulasi Image Container**
Untuk membagikan image container ketika pengembang telah membangunnya kepada developer lain dapat dengan cara menyimpan image container dalam format **.tar** atau mengunggah image container ke image **registry**.
Beberapa perintah yang biasa dijalankan untuk mengelola image container:
1. Menyimpan dan memuat image, dengan sintaks:
```
docker save [-o FILE_NAME] IMAGE_NAME[:TAG]
docker load [-i FILE_NAME]
``` 
2. Publishing image e Registry, dengan sintaks:
```
docker image tag IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
docker login -u [USERNAME/] -p [PASSWORD]
docker image push [USERNAME/]NAME[:TAG]
``` 
3. Menghapus seluruh image yang tidak digunakan, dengan sintaks:
```
docker rmi $(docker images -q)
``` 


---
### **3. Dockerfile**
Dockerfile merupakan file berisi text yang memuat seperangkat perintah yang dibangun oleh developer. Dockerfile inilah yang akan membangun image container berdasarkan langkah perintah yang dibuat. Beberapa komponen perintah yang digunakan pada Dockerfile:
- FROM, instruksi yang memberitahu Docker tentang base yang ingin digunakan sebagai image.
- LABEL, memuat informasi tambahanyang bukan perintah.
- RUN, instruksi untuk menjalankan perintah yang dimasukkan.
- COPY & ADD, menyalin file dari file di host image berada ke lokasi yang diinginkan.
- EXPOSE, instruksi mengenai port dan protokol yang digunakan saat runtime.
- ENTRYPOINT, perintah default untuk dijalankan ketika container dibuat.
- CMD, memberikan argumen default untuk instruksi ENTRYPOINT. 
- USER, menentukan pengguna selain root yang digunakan saat menjalankan instruksi dan perintah.
- WORKDIR, mengatur direktori kerja untuk menempatkan instruksi dari USER.


---

### **4. Hands-on Dockerfile**
Pada hands-on ini dibagi menjadi 3 lab dengan fokus masing-masing. Berikut detail tiap lab yang dijalankan:
#### **Lab 4.1**
Lab ini berfokus pada membuat **image baru**. Langkah yang diperlukan untuk mendapatkannya ialah:
1. Melakukan clone melalui repository sebagai latihan, dengan sintaks berikut:
```
git clone https://github.com/spkane/docker-node-hello.git \
    --config core.autocrlf=input latihan01
```
![Screenshot 2024-03-14 203450](https://hackmd.io/_uploads/rJFn3qZ06.png)
2. Pindah ke direktori latihan, dengan sintaks berikut:
```
cd latihan01
```

3. Membuat image dari repository yang sudah diunduh, dengan sintaks berikut:
```
docker build -t node-latihan01 .
```
![Screenshot 2024-03-14 203641](https://hackmd.io/_uploads/Byp0h5bRp.png)
4. Menjalankan container dengan image yang sudah dibuat sebelumnya dan menyatakan port pada 8080, dengan sintaks berikut:
```
docker run -d --rm --name node-latihan01 -p 8080:8080 node-latihan01
```
![Screenshot 2024-03-14 204454](https://hackmd.io/_uploads/Hk-xTqbRT.png)

5. Melakukan uji coba mengakses container, dengan sintaks berikut:
```
curl localhost:8080
```
![Screenshot 2024-03-14 204500](https://hackmd.io/_uploads/HkcKYsWRp.png)
6. Membuat direktori latihan02, dengan sintaks berikut:
```
cd $HOME
mkdir latihan02
cd latihan02
```
![Screenshot 2024-03-14 204531](https://hackmd.io/_uploads/Ske9YsZ06.png)
7. Membuat Dockerfile, sebagai berikut:
```
vim Dockerfile
...
# Use whalesay image as a base image
FROM registry.adinusa.id/btacademy/whalesay:latest

# Install fortunes
RUN apt -y update && apt install -y fortunes

# Execute command
CMD /usr/games/fortune -a | cowsay
...
```
![Screenshot 2024-03-14 205304](https://hackmd.io/_uploads/HkcqtibCa.png)
8. Membuat image dari Dockerfile, dengan sintaks berikut:
```
docker build -t docker-whale .
```
![Screenshot 2024-03-14 210331](https://hackmd.io/_uploads/SyEhKob0T.png)
9. Menampilkan image yang telah dibuat, dengan sintaks berikut:
```
docker image ls
```
![Screenshot 2024-03-14 210355](https://hackmd.io/_uploads/S15nYiZRT.png)
10. Menjalankan image docker-whale, dengan sintaks berikut:
```
docker run docker-whale
```
![Screenshot 2024-03-14 210416](https://hackmd.io/_uploads/HygaYobAa.png)
11. Menampilkan container yang ada, dengan sintaks berikut:
```
docker ps
docker container ls -a
```
![Screenshot 2024-03-14 210620](https://hackmd.io/_uploads/SJsptiZR6.png)

---
#### **Lab 4.2**
Pada bagian **kedua** berfokus pada membuat image baru dari applikasi **Flask**. Langkah yang diperlukan untuk mendapatkannya ialah:
1. Masuk ke dalam akun Docker, dengan sintaks berikut:
```
docker login
```
![Screenshot 2024-03-14 211332](https://hackmd.io/_uploads/BySRFsWAT.png)
2. membuat direktori latihan03, dengan sintaks berikut:
```
cd $HOME
mkdir latihan03
cd latihan03
```
![Screenshot 2024-03-14 211404](https://hackmd.io/_uploads/SyqRtjWCp.png)
3. Membuat file Flask, dengan sintaks berikut:
```
vim app.py
...
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hey, we have Flask in a Docker container!'


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')
...
```
![Screenshot 2024-03-14 211906](https://hackmd.io/_uploads/HJsk5oZAa.png)
4. Membuat file requirements.txt, dengan sintaks berikut:
```
vi requirements.txt
...
Flask==0.10.1
Werkzeug==1.0.0
Jinja2==2.8.1
MarkupSafe==1.1.1
itsdangerous==1.1.0
...
```
![Screenshot 2024-03-14 211841](https://hackmd.io/_uploads/BkQxcjZCa.png)
5. Membuat file Dockerfile, sebagai berikut:
```
vim Dockerfile
...
FROM registry.adinusa.id/btacademy/ubuntu:16.04
RUN mkdir /app
RUN apt-get update -y && \
        apt-get install python-pip python-dev -y

COPY ./requirements.txt /app
COPY . /app

WORKDIR /app
RUN pip install -r requirements.txt

ENTRYPOINT ["python"]
CMD ["app.py"]
...
```
![Screenshot 2024-03-14 212253](https://hackmd.io/_uploads/SyXW9jbRa.png)
6. Membangun image dari Dockerfile, dengan sintaks berikut:
```
docker build -t flask-latihan03 .
```
![Screenshot 2024-03-14 213037](https://hackmd.io/_uploads/rkh-5ibRT.png)
7. Tag image dengan docker username, dengan sintaks berikut:
```
docker tag flask-latihan03 [usernamedocker]/flask-latihan03:latest

```
![Screenshot 2024-03-14 214504](https://hackmd.io/_uploads/SkhScsbCT.png)

8. Push image ke dockerhub, dengan sintaks berikut:
```
docker push [usernamedocker]/flask-latihan03:latest
```
9. Menjalankan image flask03, dengan sintaks berikut:
```
docker run -d -p 5000:5000 --name flask03 [usernamedocker]/flask-latihan03
```
![Screenshot 2024-03-14 214818](https://hackmd.io/_uploads/rymO5ibRp.png)

10. Melakukan uji coba browsing, dengan sintaks berikut:
```
curl localhost:5000
```
![Screenshot 2024-03-14 214833](https://hackmd.io/_uploads/Bknv5iWA6.png)

---
#### **Lab 4.3**
Pada bagian **ketiga** ini, berfokus untuk mengakses image dengan bukan tampilan default nginx web. Berikut langkah untuk menyelesaikannya:
1. Membuat direktori baru, dengan sintaks berikut:
```
$HOME
mkdir latihan-quiz01
cd latihan-quiz01
```
![Screenshot 2024-03-14 215027](https://hackmd.io/_uploads/r1G2cs-AT.png)
2. Melakukan clone repositori dari github, dengan sintaks berikut:
```
git clone https://github.com/rivawahyuda/mywebsite.git
```

3. Membuat Dockerfile, dengan sintaks berikut:
```
vim Dockerfile
...
FROM registry.adinusa.id/btacademy/nginx:latest
```
![Screenshot 2024-03-14 215831](https://hackmd.io/_uploads/B1jC9i-R6.png)
4. Membangun image latihan-quiz01-image, dengan sintaks berikut:
```
docker build -t latihan-quiz01-image .
```
![Screenshot 2024-03-14 220025](https://hackmd.io/_uploads/S1jeijZCp.png)
![Screenshot 2024-03-14 220048](https://hackmd.io/_uploads/B1K-isbAT.png)
5. Menjalankan container dengan image latihan-quiz01-image, expose port 80, and dinamakan quiz01, dengan sintaks berikut:
```
docker run -d --rm --name quiz01 -p 80:80 latihan-quiz01-image
```
![Screenshot 2024-03-14 220213](https://hackmd.io/_uploads/rJJvis-Ca.png)
6. Test browsing


---


## **Docker Compose**
### **1. Docker Compose Overview**

**Docker Compose** merupakan alat untuk mengatur dan menjalankan container pada satu host docker, baik pada development, Continuous Integration, pengujian, ataupun demo. Alat ini menggunakan pendekatan **deklaratif** dalam menjalankan containernya. Dimana, dalam mendeskripsikan dan menjalankan aplikasi dalam beberapa container tidak menginputkan pemrograman prosedur pasti yang harus diikuti ketika menemui sebuah masalah.
Docker Compose sangat berguna ketika ingin menjalankan beberapa container sekaligus/ multilayanan. Docker Compose akan mendefinisikan program secara deklaratif pada file .yaml. Contoh file yang dimaksud:

```
version: "3.2"
services:
 web:
    image: palopalepalo/web:1.0
    build: web
    ports:
    - 80:3000
 db:
    image: palopalepalo/db:1.0
    build: db
    volumes:
    - pets-data:/var/lib/postgresql/data

volumes:
 pets-data:
```
- version: menentukan versi format Docker Compose yang digunakan.
- services: mentukan layanan yang membentuk aplikasi.
- web: layanan web yang digunakan dengan detail didalamnya.
- db: database yang digunakan.
- volume: volume yang digunakan oleh layanan.

Docker Compose juga menyediakan layanan untuk melakukan scaling yang berguna ketika terdapat lonjakan pengguna ke suatu web. Alat ini dapat dipanggil dengan sintaks `docker-compose up --scale [web]=[banyakunit]`, yang dalam artian lain ialah menjalankan lebih banyak instance untuk menampung pengguna.


---

### **2. Hands-on Docker Compose**
#### **Lab 5.1**
Pada bagian ini berfokus dalam menginstall Docker Compose. Berikut langkah untuk menyelesaikannya:
1. Mengunduh dan menginstall Compose dan memastikan Docker Compos telah terinstal, dengan sintaks berikut:
```
VERSION=$(curl --silent https://api.github.com/repos/docker/compose/releases/latest | jq .name -r) && \
DESTINATION=/usr/bin/docker-compose && \
sudo curl -sL https://github.com/docker/compose/releases/download/${VERSION}/docker-compose-$(uname -s)-$(uname -m) -o $DESTINATION && \
sudo chmod 755 $DESTINATION
docker-compose --version
```
![Screenshot 2024-03-15 161011](https://hackmd.io/_uploads/ryyE3kEC6.png)

2. Membuat direktori my_wordpress dan masuk ke dalamnya, dengan sintaks:
```
cd $HOME
mkdir -p latihan/my_wordpress
cd latihan/my_wordpress
``` 
![Screenshot 2024-03-15 161626](https://hackmd.io/_uploads/HyJ831EAT.png)

3. Membuat filee docker-compos.yml, dengan sintaks:
```
vim docker-compose.yml
``` 
![Screenshot 2024-03-16 164404](https://hackmd.io/_uploads/Sycs21VCa.png)

4. Menjalankan compose, dengan sintaks:
```
docker-compose up -d
``` 
![Screenshot 2024-03-16 164641](https://hackmd.io/_uploads/BkJ0hJNAp.png)

5. Menampilkan list container yang ada, dengan sintaks:
```
docker container ls
``` 
![Screenshot 2024-03-16 164929](https://hackmd.io/_uploads/HkUA2yNRa.png)



---

## **Continuous Integration**
### **1. Overview CI**
**CI/CD** menggabungkan pengembangan dengan pengujian, memungkinkan pengembang menjalankan pengujian secara paralel dan mengotomatiskannya sehingga mereka dapat terus bekerja pada proyek lain saat pengujian dijalankan. Secara garis besar, berikut proses CI:
![image](https://hackmd.io/_uploads/SJ_XCyER6.png)
1. Developer push ke GitHub
2. GitHub menggunakan webhook untuk memberi tahu Jenkins tentang pembaruan
3. Jenkins pull repositori GitHub, termasuk berkas Docker image, serta aplikasi dan test code.
4. Jenkins membangun image Docker pada lave node Jenkins.
5. Jenkins menginstansiasi kontainer Docker pada slave node, dan menjalankan pengujian yang sesuai
6. Jika pengujian berhasil, citra kemudian didorong ke Dockerhub atau Docker Trusted Registry.


---

### **2. AutoBuild DockerHub**
**Docker Hub** dapat secara otomatis membangun image dari source code di repositori eksternal dan secara otomatis push image yang telah dibangun ke repositori Docker.
Ketika membuat daftar cabang dan tag yang ingin dibangun menjadi image Docker dan push code ke cabang source code akan menggunakan webhook untuk memicu build baru, yang menghasilkan **image Docker**.yang kemudian di push ke **registry** Docker. Dengan begitu, repositori selalu diperbarui dengan perubahan kode secara otomatis.


---

## **Docker Swarm & Portainer**
### **1. Swarm Overview**
Swarm adalah layanan yang memungkinkan sekelompok komputer yang menjalankan suatu Docker. Sehingga, ketika container berjalan sebagai layanan, maka swarm akan mengelola siklus hidup layanan tersebut.
Docker Swarm sendiri merupakan sekelompok mesin yang menjalankan aplikasi Docker secara bersamaaan dalam suatu cluster. ![image](https://hackmd.io/_uploads/HyXF-x40T.png)
Layanan yang dimiliki Docker Swarm, diantaranya:
* Cluster management integrated with Docker Engine
* Decentralized design
* Declarative service model
* Scaling
* Desired state reconciliation
* Multi-host networking
* Service discovery
* Load balancing
* Secure by default
* Rolling updates
---
### **2. Portainer Overview**
Portainer adalah alat manajemen kontainer universal berbasis GUI yang dapat bekerja pada Docker maupun Kubernetes untuk mengelola aplikasi dan layanan dalam kontainer menjadi lebih mudah dan efisien. Portainer memungkinkan untuk manage seluruh sumber daya docker yang ada. termasuk container, image, volume, network, registry, dsb. ![image](https://hackmd.io/_uploads/SyCFGlVAa.png)


---

### **3. Hands-on Swarm & Portainer**
#### **Lab 7.1**
Pada bagian ini berfokus untuk membuat Docker Swarm. Berikut langkah untuk menyelesaikannya:
1. Menginisialisai Docker Swarm, dengan sintaks berikut:
```
docker swarm init --advertise-addr 10.7.7.10
```
![Screenshot 2024-03-16 165233](https://hackmd.io/_uploads/SJVrLf40a.png)

2. Menjadikan node02 sebagai worker pada swarm, dengan sintaks:
```
docker swarm join --token [TOKEN] 10.7.7.10:2377
```
![Screenshot 2024-03-16 165243](https://hackmd.io/_uploads/H1jrIzVAp.png)

3. Memastikan node02 telah bergabung, dengan sintaks:
```
docker node ls
```
![Screenshot 2024-03-16 165321](https://hackmd.io/_uploads/H1Q8IGER6.png)

---
#### **Lab 7.2**
Pada bagian ini berfokus untuk membuat 2 replika dan dapat diakses dari semua node. Berikut langkah untuk menyelesaikannya:
1. Membuat layanan nginx dengan 2 replica, dengan sintaks:
```
docker service create --name web --replicas 2 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
``` 
![Screenshot 2024-03-16 165506](https://hackmd.io/_uploads/HJEDIGNAp.png)

2. Memastikan layanan berjalan dengan baik, dengan sintaks:
```
docker service ls
``` 
![Screenshot 2024-03-16 165608](https://hackmd.io/_uploads/r1OvLM406.png)

3. Melakukan uji browsing dari node01 dan node02, dengan sintaks:
```
curl http://10.XX.XX.10
curl http://10.XX.XX.20
``` 
![Screenshot 2024-03-16 165640](https://hackmd.io/_uploads/H1pvIzERT.png)
![Screenshot 2024-03-16 165648](https://hackmd.io/_uploads/HJ-O8MEAa.png)

4. Melihat informasi layanan dan memastikan layanan berjalan, dengan sintaks:
```
docker service inspect --pretty web
docker service ps web
```
![Screenshot 2024-03-16 165742](https://hackmd.io/_uploads/H18oUzVAp.png)


6. Membuat container dengan limit cpu dan memory, dengan sintaks:
```
docker service create --name [username] --reserve-cpu 1 --limit-cpu 1 \
--reserve-memory  256mb --limit-memory 128mb registry.adinusa.id/btacademy/httpd:latest
```
![Screenshot 2024-03-16 165925](https://hackmd.io/_uploads/HyMnUzNRT.png)

7. Memastikan spesifikasi container, dengan sintaks:
```
docker service inspect --pretty [username]
```
![Screenshot 2024-03-16 165947](https://hackmd.io/_uploads/Bk8nUG406.png)

---
#### **Lab 7.3**
Pada bagian ini berfokus untuk membuat 1 replika dan dan mengupdate image layanan sistyo/myweb:latest. Berikut langkah untuk menyelesaikannya:
1. Membuat nginx dengan 3 replica, dengan sintaks:
```
docker service create --name web2 --replicas 3 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
``` 
![Screenshot 2024-03-16 195205](https://hackmd.io/_uploads/S1m0UGVAa.png)

2. Mengubah replika layanan, dengan sintaks:
```
docker service scale web2=1
``` 
![Screenshot 2024-03-16 195213](https://hackmd.io/_uploads/BJP0LGVRT.png)

3. Memastikan reolika sudah diperbarui, dengan sintaks:
```
docker service ls
docker service ps web2
``` 
![Screenshot 2024-03-16 195228](https://hackmd.io/_uploads/r12ZPGECa.png)

4. Mengupdate layanan sistyo/myweb, dengan sintaks:
```
docker service update --image sistyo/myweb web2
docker service inspect --pretty web2
```
![Screenshot 2024-03-16 195248](https://hackmd.io/_uploads/S17GPM40p.png)
![Screenshot 2024-03-16 195353](https://hackmd.io/_uploads/rJerwf4A6.png)


---
#### **Lab 7.4**
Pada bagian ini berfokus untuk menginstal layanan portainer dan menghubungkannya dengan node02. Berikut langkah untuk menyelesaikannya: 
1. Menginstal portainer di node01, dengan sintaks:
```
docker volume create portainer_data
docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart=always \
-v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
``` 
![Screenshot 2024-03-17 055412](https://hackmd.io/_uploads/Sy2pPMNRT.png)

2. Mengakses dasbor portainer.
 ![Screenshot 2024-03-16 200441](https://hackmd.io/_uploads/r1yJuGEAp.png)

3. Menghubungkan portainer dengan node02.
![Screenshot 2024-03-17 055424](https://hackmd.io/_uploads/HJvfdGNCa.png)

4. Memastikan node02 telah terhubung.
![Screenshot 2024-03-17 055448](https://hackmd.io/_uploads/SyQ7df406.png)


---
#### **Lab 7.5**
Pada bagian ini berfokus untuk membuat container syafaa-web. Berikut langkah untuk menyelesaikannya: 
1. Mengakses web portainer.
2. Menambahkan container baru.
![Screenshot 2024-03-17 055808](https://hackmd.io/_uploads/H1lruf4A6.png)

3. Memastikan container telah ditambahkan.
![Screenshot 2024-03-17 060246](https://hackmd.io/_uploads/SkwSufERa.png)
![Screenshot 2024-03-17 060234](https://hackmd.io/_uploads/HJhUufNRT.png)


---
#### **Lab 7.5**
Pada bagian ini berfokus untuk melakukan push image ke registry. Berikut langkah untuk menyelesaikannya: 
1. Mengakses Portainer.
2. Membangun image baru.
![Screenshot 2024-03-17 060551](https://hackmd.io/_uploads/HyuPOf40T.png)
3. Push image ke Registry repo-syafaa.
![Screenshot 2024-03-17 060811](https://hackmd.io/_uploads/SkXk6gwA6.png)



---

## **Logging Driver**
### **1. Logging Driver Overview**
Logging Driver merupakan mekanisme yang berisi multiple logging yang memberikan informasi mengenai container maupun layanan yang sedang berjalan. Biasanya, Docker menggunakan json-file logging driver. Contoh konfigurasi json logging driver:
```
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "labels": "production_status",
    "env": "os,customer"
  }
}
```
Jika ingin menghindari penyimpanan terlalu besar, menggunakan local logging driver dengan log rotation  dan menggunakan format file yang lebih efektif.
```
{
  "log-driver": "local"
}
```
Berikut merupakan **logging drivers** yang dapat digunakan pada suatu **container**:
![image](https://hackmd.io/_uploads/BkCrb-VCa.png)

---

### **2. Hands-on Logging Driver**
#### **Lab 8.1**
Pada bagian ini berfokus untuk membuat log ke dalam direktori. Berikut langkah untuk menyelesaikannya:
1. Membuat file daemon.json, dengan sintaks:
```
sudo vim /etc/docker/daemon.json
``` 
![Screenshot 2024-03-17 065512](https://hackmd.io/_uploads/Hks9uMNA6.png)

2. Restart Daemon dan Docker, dengan sintaks:
```
sudo systemctl daemon-reload
sudo systemctl restart docker
``` 
![Screenshot 2024-03-17 065603](https://hackmd.io/_uploads/Bkyo_zVAp.png)

3. Menjalankan container, dengan sintaks:
```
docker run --log-driver json-file --log-opt max-size=10m registry.adinusa.id/btacademy/alpine echo hello world   
``` 
![Screenshot 2024-03-17 065616](https://hackmd.io/_uploads/B1VjdfE0T.png)

4. Memeriksa logs di dalam direktori docker, dengan sintaks:
```
sudo cat /var/lib/docker/containers/$(docker ps --no-trunc -a | grep 'alpine' | awk '{print $1}')/$(docker ps --no-trunc -a | grep 'alpine' | awk '{print $1}')-json.log | jq .
```
![Screenshot 2024-03-17 065645](https://hackmd.io/_uploads/rJni_fVRp.png)


---

## **Health Check**
### **1. Health Check Overview**
Instruksi ini berfungsi untuk memastikan bahwa container tertentu tetap berjalan. HEALTHCHECK dapat mendeteksi kasus seperti web server berjalan dalam keadaan looping, dsb. 
Untuk melakukan check dapat menggunakan bentuk `HEALTHCHECK [OPTIONS] CMD command` yang memiliki opsi berikut:
- --interval=DURATION (default: 30s)
- --timeout=DURATION (default: 30s)
- --start-period=DURATION (default: 0s)
- --retries=N (default: 3)

Status command exit menunjukkan status kesehatan container. Nilai yang mungkin adalah:
0: success - container sehat dan siap digunakan
1: unhealthy - container tidak berfungsi dengan benar
2: reserved - jangan gunakan kode keluar ini

Contoh perintah ketika menjalankan Health Check saat mendefinisikan image:
![image](https://hackmd.io/_uploads/BkyqEZ4A6.png)

Contoh perintah ketika menjalankan Health Check bersamaan dengan container: ![image](https://hackmd.io/_uploads/BJHcV-4Cp.png)


---

### **2. Hands-0n Health Check**
#### **Lab 9.1**
Pada bagian ini berfokus untuk membuat  http-healthcheck container sedang dalam keadaan unhealthy. Berikut langkah untuk menyelesaikannya:
1. Membuat direktori kerja baru, dengan sintaks:
```
cd $HOME
mkdir hc-latihan01
cd hc-latihan01
``` 
![Screenshot 2024-03-17 065921](https://hackmd.io/_uploads/SkV3dMV0T.png)

2. Membuat Dockerfile, dengan sintaks:
```
vim Dockerfile
``` 
![Screenshot 2024-03-17 065945](https://hackmd.io/_uploads/SJF3_MV06.png)

3. Membuat image dari Dockerfile, dengan sintaks:
```
docker build -t http-healthcheck .
``` 
![Screenshot 2024-03-17 070023](https://hackmd.io/_uploads/rynp_fVAp.png)

4. Menjalankan image, dengan sintaks:
```
docker run -d -p 80:80 --name http-healthcheck http-healthcheck
```
![Screenshot 2024-03-17 070042](https://hackmd.io/_uploads/B110OME0T.png)

5. Melihat status image, dengan sintaks:
```
docker ps
```
![Screenshot 2024-03-17 070057](https://hackmd.io/_uploads/ry4RdMNRp.png)

6. Check melalui curl http://ilocalhost/ dapat diakses, dengan sintaks:
```
curl http://localhost/
```
![Screenshot 2024-03-17 070112](https://hackmd.io/_uploads/HJnC_zNC6.png)

7. Check untuk unhealthy, dengan sintaks:
```
curl http://localhost/unhealthy
```
![Screenshot 2024-03-17 070134](https://hackmd.io/_uploads/SyHkFf4Ap.png)


8. Melihat docker container status, dengan sintaks:
```
docker container ls
```
![Screenshot 2024-03-17 070148](https://hackmd.io/_uploads/SyhkKfVA6.png)

9. Chech dengan curl, dengan sintaks:
```
curl http://localhost/
```
![Screenshot 2024-03-17 070206](https://hackmd.io/_uploads/HyGltfN0T.png)

---
#### **Lab 9.1**
Pada bagian ini berfokus untuk membuat node-server container dalam keadaan healthy. Berikut langkah untuk menyelesaikannya:

1. Membuat direktori baru, dengan sintaks:
```
cd $HOME
mkdir hc-latihan02
cd hc-latihan02
```
![Screenshot 2024-03-17 070238](https://hackmd.io/_uploads/H12etzNRT.png)

2. Membuat file server.js, dengan sintaks:
```
vim server.js
``` 
![Screenshot 2024-03-17 070311](https://hackmd.io/_uploads/SJgZtMNAp.png)

3. Membuat Dockerfile, dengan sintaks:
```
vim Dockerfile
``` 
![Screenshot 2024-03-17 070339](https://hackmd.io/_uploads/Hk8ZYz4Aa.png)

4. Membuat image dari Dockerfile, dengan sintaks:
```
docker build -t node-server .
```
![Screenshot 2024-03-17 072633](https://hackmd.io/_uploads/SyA-tzECT.png)

5. Menjalankan image, dengan sintaks:
```
docker run -d --name nodeserver -p 8080:8080 -p 8081:8081 node-server
```
![Screenshot 2024-03-17 072649](https://hackmd.io/_uploads/SymfFfNC6.png)

6. Check container, dengan sintaks:
```
curl 127.0.0.1:8080
docker ps 
docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
```
![Screenshot 2024-03-17 072812](https://hackmd.io/_uploads/S1fQFz4A6.png)




---
## **Security**

### **1. Securitas pada Docker**
Yang membantu layanan Docker berada dalam keamanan, pertama ialah **namespaces**, yang membuat antar container saling terisolasi. Proses yang berjalan di sutu container tidak dapat dijalankan oleh container lain maupun di host system.
**Control Goups** berperan dalam berperan dalam menghitung dan membatasi sumber daya yang digunakan. Khususnya memastikan setiap container mendapatkan memory yang dibagikan secara adil.
Ketika menjalankan container dengan Docker. Maka, akan dijalankan **Docker daemon**, yang hanya bisa diakses oleh trusted users. Saat ini juga, titik akhir REST API diubah menggunakan socket UNIX dibandingkan socket TCP yang lebih rentan. dengan ini, pengguna dapat membatasi akses ke controll socket.

Berbeda pada **server** lainnya, container dapat menjalankan tugas daemon SSH, logging, dsb tanpa harus menjadi pengguna **root**. Sedangkan root yang sebenarnya memiliki hak lebih spesifik seperti menolak semua mount, menolak akses, atau membuat node baru, dsb.  Jadi, meskipun seseorang menyusup ke sistem container, selama tidak menjadi root user, maka tidak ada kerusakan serius yang terjadi.

Untuk konfigurasi lebih lanjut, mesin Docker dapat hanya menjalankan **image** yang **diverifikasi** di dalam biner Docker. lebih tepatnya pada daemon.json. Hal ini memastikan repository yang digunakan ialah yang telah diverifikasi sebelumya.

---

### **2. Docker CIS**
Center for Internet Security (CIS) merupakan sistem keamanan siber yang menggunakan crowdsourcing untuk menentukan rekomendasi keamanan pada suatu container Docker. Benchmark CIS untuk Docker menyediakan pemeriksaan konfigurasi, seperti menetapkan resource, mengurangi hak istimewa, dan read only mode saat menjalankan image.

---

### **3. Secure Computing Mode**

Secure computing mode (seccomp) merupakan fitur kernel linux untuk membatasi tindakan yang ada dalam container. Untuk mendapatkan layanan ini, maka kernel perlu dikonfigurasi dengan CONFIG_SECCOMP diaktifkan. Dan Docker dibangun dengan seccomp. Nantinya, container yang menggunakan layanan seccomp dapat mengatur panggilan default act, dan mengatur panggilan yang spesifik.seccomp berperan penting untuk menjalankan container Docker dengan hak istimewa paling rendah.

---

### **4. Secret**

Merupakan kumpulan data yang harus terenskripsi di Dockerfile untuk dikirimkan maupun disimpan. seperti, ussername dan password, ssh key, database internal, dsb. Untuk itu, dapat menggunakan layanan Docker secret untuk mengelola data secara terpusat dan mengirimkannya dengan aman hanya ke container yang memerlukan akses ke data tersebut. 
Saat menambahkan secret ke swarm, Docker mengirimkan rahasia itu ke manajer swarm melalui koneksi TLS bersama. di dalam log terenskripsi.


---

## **Storage Driver**
### **1. Docker Storage Driver**
Storage driver berperan dalam memberikan akses kepada pengguna ke dalam lapisan container writeable. Storage driver juga berperan pada penyimpanan dan pengelolaan image juga container di host Docker pengguna. Berikut storage driver yang dapat digunakan pada Docker:
- **overlay2**: driver untuk semua distribusi Linux  dan tidak memerlukan konfigurasi tambahan.
- **aufs**: driver untuk Docker 18.06 dan yang lebih lama, ketika dijalankan di Ubuntu yang tidak mendukung overlay2.
- **fuse-overlayfs**: untuk menjalankan Rootless Docker pada host yang tidak menyediakan dukungan untuk rootless overlay2.
- **devicemapper**:dapat dijalankan tapi memerlukan direct-lvm untuk lingkungan produksi, karena loopback-lvm, meskipun konfigurasi nol, memiliki kinerja yang sangat buruk.
- **btrfs** dan **zfs**: penyimpanan digunakan jika ada sistem file pendukung yang memungkinkan opsi lanjutan, seperti membuat “snapshot”.
- **vfs**: penyimpanan dimaksudkan untuk tujuan pengujian, dan untuk situasi di mana tidak ada sistem file copy-on-write yang dapat digunakan.
Berikut merupakan rekomendasi penggunaan driver:
![image](https://hackmd.io/_uploads/rk58IDHR6.png)
Sedangkan pada tabel berikut, menunjukkan sistem file pendukung dari driver:
![image](https://hackmd.io/_uploads/BJfnLPSRa.png)


---

### **2. Hand-On Storage Driver**
#### **Lab 11.1**
Pada bagian ini berfokus untuk mmengubah storage driver sesui kondisi yang diminta. Berikut langkah untuk menyelesaikannya:
1. Membuat file daemon.json, dengan sintaks:
```
sudo vim /etc/docker/daemon.json
``` 
![Screenshot 2024-03-17 081145](https://hackmd.io/_uploads/BJwKqfN0T.png)

2. Restart layanan docker, dengan sintaks:
```
sudo service docker restart
```
![Screenshot 2024-03-17 081219](https://hackmd.io/_uploads/rJjF5fNRp.png)

3. Docker info, dengan sintaks:
```
docker info
```
![Screenshot 2024-03-17 081227](https://hackmd.io/_uploads/r1x5cf4Rp.png)

4. Memastikan dengan docker pull, dengan sintaks:
```
docker pull registry.adinusa.id/btacademy/ubuntu
```
![Screenshot 2024-03-17 081607](https://hackmd.io/_uploads/SJB9qfNRa.png)

5. Memastikan direktori docker, dengan sintaks:
```
sudo ls -al /var/lib/docker/vfs/dir/
sudo du -sh /var/lib/docker/vfs/dir/
```
![Screenshot 2024-03-17 081613](https://hackmd.io/_uploads/rJA99GEAp.png)
![Screenshot 2024-03-17 081638](https://hackmd.io/_uploads/Hk4icf4R6.png)



---

## **Logging dan Error Handling**

**Docker log** atau Docker service log biasanya menampilakn output jika menjalankannya di terminal interaktif. Pada UNIX dan LINUX command akan menghasilkan 3 streams, yaitu **STDIN**, berisi input dari keyboard adau command lain. **STDOUT**, command output normal. dan **STDERR**, digunakan untuk pesan output error. Namun terkadang, docker log tidak efektif ketika untuk menjalankan suatu layanan seperti mengirimkan logs ke sebuah file, database, dsb. Dalam kondisi ini biasanya **logs** diproses di bagian lain. Atau ketika image menjalankan non-interactive process seperti database atau webserver, solusi akan ditampilkan oleh oficial nginx image dan httpd Apache.
Contoh melakukan Log Check:
1. Check history image, dengan sintaks berikut: 
```
docker history registry.adinusa.id/btacademy/nginx:latest
```
2. Run nginx, dengan sintaks berikut:
```
docker run -dit -p 80:80 --name nginx1 registry.adinusa.id/btacademy/nginx
```
3. Check the filesystem on nginx, dengan sintaks berikut:
```
docker diff nginx1
```
4. Cek Log, dengan sintaks berikut:
```
docker logs --details nginx1
docker logs --timestamps nginx1
docker logs nginx1
```

## **Lab Challenge**
### **Challenge 1**
1. Create a challenge1 directory, and go into that directory
2. Create 2 container with name web1 using image
![Screenshot 2024-03-18 202547](https://hackmd.io/_uploads/HkmtTgwCT.png)

3.  Save the haproxy configuration file inside the challenge1 folder with the name haproxy.cfg
![Screenshot 2024-03-19 185528](https://hackmd.io/_uploads/BJEjpewRp.png)

4. Create 1 container haproxy with name username-haproxy using image registry.adinusa.id/btacademy/haproxy-alpine:2.4
![Screenshot 2024-03-18 202912](https://hackmd.io/_uploads/ryk-AlvAT.png)

---

