---
# System prepended metadata

title: 'Title : Docker Fundamental'

---

# **Docker Fundamental**

## **1. Introduction of Container**
Pada materi ini, kita akan belajar menjalankan layanan kecil hingga membangun sistem yang dapat melakukan *scalling* secara elastis menggunakan containerisasi dengan **DOCKER**.

Dalam materi ini, kita akan mempelajari tentang:
> 1. Apa itu container dan mengapa kita membutuhkannya?
> 2. Tempat Docker di dunia container
> 3. Berpikir dengan pola pikir container


### **Apa itu Container ?**
Dahulu, *Developer* dan *operations engineers* menghadapi masalah kompleks dalam menginstal dan menjalankan aplikasi di server produksi. Solusi awal masalah tersebut ialah menggunakan *Virtual Machines* (VMs), namun VMs terlalu berat karena 1 VMs digunakan untuk 1 aplikasi. Solusi utama dalam masalah ini adalah **Docker Containers**, yang memungkinkan pengemasan aplikasi beserta dependensinya dalam sebuah *blackbox* yang telah terstandarisasi. Docker Containers memungkinkan untung **Building** (Membangun), **shipping** (Mengirim), dan **Running** (Menjalankan) di mana saja dengan lebih mudah dan efisien.

### **Mengapa Container sangat penting ?**

Semakin kompleksnya proyek *software* dan meningkatnya *cyber attack*, diperlukan cara untuk menyederhanakan *supply chain software* dan meningkatkan keamanannya. **Container** dapat membantu meningkatkan keamanan aplikasi melalui penggunaan fitur-fitur keamanan Linux, seperti **Linux Kernel Namespaces** untuk melakukan *sandboxing* aplikasi yang berbeda namun berjalan di komputer yang sama,  dan **control groups** (cgroups) yang mengelola serta membatasi resource untuk menghindari terjadinya *noisy-neighbour*, serta dengan memanfaatkan kegunaan *image container* yang tidak dapat diubah untuk memindai **Common Vulnerabilities and Exposures** (CVEs). Selain itu, penggunaan **content trust** dapat memastikan bahwa pengguna dan pembuat *image container* memiliki jaminan keamanan terhadap serangan **man-in-the-middle** (MITM)

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

**Container** penting bukan hanya karena alasan keamanan, namun juga karena kemampuannya untuk menyerdehanakan pengembangan *software* dan pengelolaan infrastruktur. **Container** memungkinkan *developer* dengan mudah mensimulasikan lingkungan produksi, bahkan di laptop *developer*. Dengan **Container**, *Developer* dapat menjalankan *database* dalam container dengan mudah tanpa menghabiskan banyak *storage*. **Container** lebih ringan bila dibandingkan dengan VMs, sehingga memungkinkan container berjalan bersamaan tanpa membebani laptop *developer*. **Container** juga memungkinkan operator untuk fokus pada tugas-tugas aslinya, yaitu *provisioning* infrastruktur dan menjalankannay serta melakukan *monitoring* aplikasi. Sehingga, operator tidak perlu lagi memiliki pengetahuan mendalam tentang internal aplikasi karena aplikasi tersebut berjalan dengan mandiri dalam **Container**.
    
### **Contoh Teknologi *Containerized***
    
**1. Docker**
    ![image](https://hackmd.io/_uploads/rkp_VXcT6.png)
    
**Docker** adalah platform *opensource* untuk **Developping** (Membangun), **shipping** (Mengirim), dan **Running** (Menjalankan) aplikasi. ini memungkinkan pemisahan aplikasi dari infrastruktur, mempercepat pengiriman *software*. **Docker** menggunakan **Container** untuk mengemas dan menjalankan aplikasi secara terisolasi, memungkinkan banyak **Container** berjalan pada satu **host**.Dengan **Docker**, anda dapat mengelola infrastruktur seperti mengelola aplikasi dengan alat dan platform yang disediakan.


**2. Podman**
    ![image](https://hackmd.io/_uploads/B1Q7I7cTp.png)
    
**Podman** adalah platform *opensource* untuk mengelola aplikasi dalam **Container OCI** (Open Containers Initiative ). Dibandingkan dengan **Docker**, Podman tidak memelukan *daemon*. Podman menyediakan *Command Line Interface* yang mirip dengan **Docker** dan menggunakan runtime **Container OCI** untuk membuat dan menjalankan **Container**. Podman dapat dijalankan baik oleh *root* maupun *common user*, untuk mengelola seluruh ekosistem **Container** termasuk, **Pod, Container, Image Container, dan Volume Container** menggunakan **libpod**. Selain itu, **Podman** memiliki **RESTFul API** untuk mengelola **Container**. **Podman** juga *support remote user* untuk berkomunikasi dengan **RESTFul Service**. Saat ini **Podman** mendukung klien di **Linux, Mac, dan Windows.** Namun Layanan **RESTFul Service** hanya bisa dijalankan di **Linux.**
    
**3. LXC**
    ![image](https://hackmd.io/_uploads/SJdGKQcTT.png)

**LXC** adalah *usespace interface* untuk **Linux Kernel Containment features.** Menggunakan **API** yang *powerful* dan sederhana, memungkinkan pengguna **Linux** dengan mudah membuat dan mengelola **Container** sistem dan aplikasi.
**LXC** memiliki beberapa fitur diantaranya:
* Kernel namespaces (ipc, uts, mount, pid, network and user)
* Apparmor and SELinux profiles
* Seccomp policies
* Chroots (using pivot_root)
* Kernel capabilities
* CGroups (control groups)

**LXC** bertujuan untuk membuat lingkungan yang sesuai dengan standar **Linux** tanpa perlu kernel yang terpisah.
**LXC** terdiri dari beberapa bagian yang terpisah:
* library liblxc
* beberapa bahasa untuk **API**:
    * python3
    * lua
    * Go
    * ruby
    * Haskell
* serangkaian alat standar untuk mengontrol **Container**
* Template kontainer distribusi

**4. LXD**
    ![image](https://hackmd.io/_uploads/r1Hsi7qT6.png)

**LXD** adalah manajer **Container** dan VMs **Next-Generation** yang menawarkan pengalaman *user* untuk sistem **Linux** yang lengkap di dalam **Container** atau **Virtual Machine** (VM). **LXD** berbasis *image* yang fleksibel, dan dapat diinstal di berbagai perangkat keras, dari laptop hingga server. **LXD** dapat dikelola di **Command Line Interface** langsung melalui **REST API**. **LXD** dikelola oleh *Canonical Ltd.* dengan kontribusi dari berbagai perusahaan dan individu.

* **Host, Virtual Machine dan Container**

**Container** adalah abstraksi pengemasan kode dan dependansi di dalam lapisan aplikasi, yang memungkikan beberapa **Container** berjalan pada satu mesin dengan berbagi kernel **Operating System** (OS), yang membutuhkan sedikit *storage* (biasanya puluhan MB). Sementara itu, **Virtual Machine** (VM) adalah replika perangkat keras fisik yang memungkinkan beberapa VM berjalan pada satu mesin perangkat keras, dengan setiap VM menyertakan salinan lengkap OS dan aplikasi, serta menghabiskan *storage* yang lebih besar (puluhan GB). Mari kita lihat perbedaan antara **Container** dan **Virtual Machine**
    
![image](https://hackmd.io/_uploads/BkGYAmcpa.png)

Gambar menunjukkan bahwa dengan VM, kita dapat menjalankan 3 aplikasi dengan 2 tumpukan *software*. Dalam konteks **Container** menggunakan **Docker**, aplikasi oranye dan hijau dapat dijalankan dalam **Container** yang sama:

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

**Docker** memiliki keunggulan besar dalam menghilangkan kebutuhan OS lengkap dalam setiap penyebaran **Container**, yang secara signifikan mengurangi ukuran dari **Container**. dengan memanfaatkan kernel **Linux** dari OS host, **Docker** dapat menjalankan berbagai OS berbasis linux, seperti **Red Hat**, **CentOS**, dan **Ubuntu**. Hal ini memungkinkan fleksibilitas dalam memilih OS host tanpa perlu instalasi yang rumit. Selain itu **Image Docker** menjadi lebih kecil dan ringan karena tidak menyertakan kernel atau OS yang penuh, dan membuatnya efisien dalam distribusi dan penyebaran

### **Lab 1.1 Persiapan Lab**

Tutosial ini menggunakan 2 virtual machine dengan spesifikasi sebagai berikut:
![image](https://hackmd.io/_uploads/HkyYzh2pT.png)
Pada Tutorial ini kita akan menggunakan OS Ubuntu 22.04, sebelum melanjutkan ke tahap berikutnya, lakukan *step by step* berikut ini :
1. Download dan Insatll VirtualBox versi 7 atau versi yang sesuai dengan OS yang anda gunakan. Anda bisa mendapatkan VirtualBox [disini](https://www.virtualbox.org/wiki/Downloads)
2. Download *image* Ubuntu 22.04 OS. Download BTA-Server.ova [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).

#### Setup NAT Network

1. Untuk membuat NAT Network baru, klik **File** menu, select **Tools** option dan klik pilihan **Network Manager**.
2. Di tab **Network**, pilih menu **NAT Network**, dan pilih **Create**.
3. Lalu masukkan IP network yang akan digunakan **192.168.0.0/24** dan klik OK
![image](https://hackmd.io/_uploads/SJVH4h36a.png)

#### Setup Host-Only Network
1. Untuk adapter **Host-Only**, pilih menu **Host-Only**
2. Didalam menu **Host-Only**, masukkan IP **10.10.10.1**, netmask **255.255.255.0**, **Disable DHCP**, lalu apply
![image](https://hackmd.io/_uploads/ByShNn2aT.png)

#### Import VM
1. Untuk *import* VM, klik menu **File** dan pilih **Import Appliance**
2. Didalam menu **Import Virtual Appliance**, Masukkan File .ova yang sudah di download sebelumnya, klik **Next**, ubah nama nya menjadi **Docker-Node01** lalu **Finish**. Tunggu beberapa saat.
![image](https://hackmd.io/_uploads/Sym7Bn36a.png)
![image](https://hackmd.io/_uploads/B1HmH23Tp.png)

#### Clone VM
1. Klik Kanan di VM **Docker-Node01** dan pilih **Clone**

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

2. Ubah nama menjadi **Docker-Node01** lalu klik **Next**

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

3. Pilih tipe **Full Clone** dan klik **Finish**

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

#### Konfigurasi Network dan Host di VM Docker-Node01
Sebelum anda memulai konfigurasi, anda harus melakukan **nusactl login** dengan kredensial login sesuai username dan password yang kalian daftarkan di platform Adinusa. Bagi kalian yang belum registrasi di Adinusa, silahkan klik link berikut [Adinusa](https://adinusa.id/)
1. Nyalakan VM **Docker-Node01** dengan klik *start*
2. Setelah *console* menyala, login dengan kredensial:
   user:**student**
   password: Adinusa2023
   kalian bebas untuk mengubah password.
3. Edit file `/etc/netplan/50-cloud-init.yaml` dengan command
   `sudo nano /etc/netplan/50-cloud-init.yaml` 
   ubah seperti gambar dibawah ini
![image](https://hackmd.io/_uploads/rkYoL22TT.png)

4. Ketik command `sudo netplan apply` untuk apply perubahan terakhir di konfigurasi network, lalu verifikasi dengan command **ip a**

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

5. Ubah Hostname

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

6. Masuk ke file `/etc/hosts` dengan command 
  `sudo nano /etc/hosts`
  ubah seperti gambar dibawah ini
 
![image](https://hackmd.io/_uploads/H1oXw33Ta.png)


#### Konfigurasi Network dan Host di VM Docker-Node02
Sebelum anda memulai konfigurasi, anda harus melakukan **nusactl login** dengan kredensial login sesuai username dan password yang kalian daftarkan di platform Adinusa. Bagi kalian yang belum registrasi di Adinusa, silahkan klik link berikut [Adinusa](https://adinusa.id/)
1. Nyalakan VM **Docker-Node02** dengan klik *start*
2. Setelah *console* menyala, login dengan kredensial:
   user:**student**
   password: Adinusa2023
   kalian bebas untuk mengubah password.
3. Edit file `/etc/netplan/50-cloud-init.yaml` dengan command
   `sudo nano /etc/netplan/50-cloud-init.yaml` 
   ubah seperti gambar dibawah ini

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

4. Ketik command `sudo netplan apply` untuk apply perubahan terakhir di konfigurasi network, lalu verifikasi dengan command **ip a**

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

5. Ubah Hostname

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

6. Masuk ke file `/etc/hosts` dengan command 
  `sudo nano /etc/hosts`
  ubah seperti gambar dibawah ini

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

#### Membuat dan mendistribusi keygen SSH
Eksekusi di semua Nodes

4. Buat keygen ssh, agar anda bisa meremote nodes tanpa password
```
student@pod-username-node01:~$ ssh-keygen -t rsa
student@pod-username-node02:~$ ssh-keygen -t rsa
```

5. Copy semua public key dari user reguler untuk semua nodes
```
student@pod-username-node01:~$ ssh-copy-id student@pod-username-node01
student@pod-username-node01:~$ ssh-copy-id student@pod-username-node02
...
student@pod-username-node02:~$ ssh-copy-id student@pod-username-node01
student@pod-username-node02:~$ ssh-copy-id student@pod-username-node02
```

6. Cek apakah host dapat akses tanpa menggunakan password
```
student@pod-username-node01:~$ ssh student@pod-username-node01 "whoami; hostname"
student@pod-username-node01:~$ ssh student@pod-username-node02 "whoami; hostname"
...
student@pod-username-node02:~$ ssh student@pod-username-node01 "whoami; hostname"
student@pod-username-node02:~$ ssh student@pod-username-node02 "whoami; hostname"
```

#### Konfigurasi nusactl
Eksekusi hanya di pod-username-node01

7. Buat file `/home/student/.nusactl/hosts.yaml` dengan command
```
student@pod-username-node01:~$ sudo nano /home/student/.nusactl/hosts.yaml
```
edit file nya seperti command dibawah
```
nodes:
  pod-node1: "10.7.7.10"
  pod-node2: "10.7.7.20"
ssh-key: "/home/student/.ssh/id_rsa" # must be static path
ssh-passwd: "password_access_vm" # change the password and password must be same every node
```
8. Otomatisasi ssh ketika login
```
sudo apt install -y keychain && echo "eval $(keychain -q --eval id_rsa)" >> ~/.bashrc && source ~/.bashrc
```

#### NOTE:
#### Jangan lewatkan tahap nomor 8. jika kamu melewatkan tahap tersebut, akan terjadi error saat penilaian.
#### Catatan penting : jangan menjalankan command nusactl dengan user root
#### Hints
*    Validasi anda dapat ssh ke setiap nodes tanpa password
*    Validasi anda dapat ping setiap nodes menggunakan hostname
*    Jika anda menemukan kata **username** ubah itu menjadi username **Adinusa** anda.

#### Tugas
Jalankan **nusactl grade do-001-1** untuk penilaian
```
[student@pod-username-node01 ~]$ nusactl grade do-001-1
```


## 2. Introduction To Docker
Tujuan memahami materi ini:
> 1. Memahami konsep dasar Docker dan cara kerjanya dalam membangun, mengirimkan, dan menjalankan aplikasi dalam container.
> 2. Mengetahui perbedaan antara Docker CE dan Docker EE serta fitur-fitur yang ditawarkan oleh masing-masing edisi.
> 3. Memahami bagaimana Docker dapat digunakan dalam lingkungan pengembangan dan produksi, serta keuntungan dan tantangan yang terkait dengan penggunaannya.
> 4. Memahami model langganan dan harga yang diterapkan oleh Docker, serta manfaat dan fitur yang ditawarkan oleh setiap tier langganan.
> 5. Membuat keputusan yang tepat dalam memilih versi Docker yang sesuai dengan kebutuhan pengembangan dan bisnis.

### Apa itu Docker ?
Docker adalah proyek *opensource* untuk **Building** (membangun), **Shipping** (Mengirimkan), dan **Running** (Menjalankan) sebuah program.

### Produk Docker
**Docker, Inc.** adalah perusahaan yang dibentuk untuk mengembangkan **Docker CE** dan **Docker EE**. **Docker** menawarkan layanan konsultasi kepada perusahaan yang ingin menggunakan aplikasi mereka dan memasukkannya ke dalam **Container** sebagai bagian dari program **Modernize Traditional Apps** (MTA).

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

  Saat ini, **Docker** membagi produknya menjadi 2, yaitu **Community Edition** (CE), yang berupa *closed-source* namun sepenuhnya gratis, ada pula **Enterprise Edition** (EE), yang juga *closes-source* dan perlu membeli lisensi setiap tahunnya. **Docker** memberikan layanan 24/7 dan juga **bug fixes**.

* **Docker CE**
  **Docker Community Edition** (DCE) mencakup produk seperti **Docker Toolbox** dan **Docker for Desktop** yang mudah diinstal dan digunakan untuk membangun, debug, dan menguji aplikasi atau layanan yang diberi Container Docker di mesin **MacOS** atau **Windows**. **Docker for MacOS** dan **Docker for Windows** adalah lingkungan pengembangan lengkap yang terintegrasi secara mendalam dengan **framework hipervisor**, jaringan, dan sistem file masing-masing. ini merupakan cara paling cepat dan handal untuk menjalankan **Docker** di **Mac** atau **Windows**.
  
  ![image](https://hackmd.io/_uploads/ryXp0nnpT.png)

* **Docker EE**
  
  **Docker Enterprise Edition** (DEE) terdiri dari **Universal Control Plane** (UCP) dan **Docker Trusted Registry** (DTR), yang keduanya berjalan di atas **Docker Swarm**. **Docker EE** membangun di atas komponen upstream dari proyek Moby dan menambahkan fitur-fitur kelas enterprise seperti **role-based access control** (RBAC), **multi-tenancy**, **mixed clusters of Docker swarm and Kubernetes**, **web-based UI**, dan **content trust**, serta pemindaian **image** di atasnya.
  
  Berikut perbedaan fitur antara **Docker CE** dan **Docker EE**
  
  ![image](https://hackmd.io/_uploads/SksFkan6p.png)


### Harga dan Langganan

* **Langganan Docker**

**Docker** telah menerapkan Perjanjian Layanan Pelanggan baru yang membutuhkan organisasi besar untuk membeli langganan berbayar, dengan harga mulai dari $5 per pengguna per bulan. **Docker Desktop** tetap gratis untuk penggunaan pribadi, pendidikan, proyek *open-source* non-komersial, dan bisnis kecil. Mereka juga meluncurkan rencana langganan bisnis baru untuk perusahaan besar. Ketentuan baru sejak 31 Agustus, dengan masa tenggang hingga 31 Januari 2022. Langganan tersedia dalam  pilihan **Docker Pro**, **Docker Team**, dan **Docker Business**.

****Perbedaan Harga setiap Tier****

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

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

referensi : https://www.docker.com/pricing/

### Lab 2.1 Instalasi Docker
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-002-1` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-002-1
```
#### Instruksi
**Eksekusi di seluruh Node**
> **Note**:  Jika terdapat [username], ubah menjadi username Adinusa kalian. Jika terdapat [X] didalam IP itu adalah nomor *attendance* kalian.

#### Install Docker
```
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release -y
sudo mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
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
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
```

#### Lihat Versi Docker
```
docker version
```
#### Lihat detail Instalasi Docker
```
docker info
```
#### Tambah User ke group Docker
```
groupadd docker
sudo usermod -aG docker $USER
sudo chmod 666 /var/run/docker.sock
```

#### Tes Instalasi Docker
```
docker run registry.adinusa.id/btacademy/hello-world
```

#### Lihat Image yang telah ter install
```
docker image ls
```

#### Lihat seluruh Container
```
docker container ls -a

```

#### Verifikasi
* Dapat menjalankan Docker tanpa command `sudo`
* Seluruh Nodes telah terinstall Docker


#### Tugas
Jalankan command `nusactl grade do-002-1` untuk menghasilkan nilai kalian.
```
[student@pod-username-node01 ~]$ nusactl grade do-002-1

```

### Lab 2.2 Jalankan Docker
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-002-2` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-002-2
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**
#### Praktek nomer 1
#### Cari image redis dari dockerhub & harbor
```
# From DockerHub
docker search redis

# From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/redis
```

#### Jalankan Image Redis
```
docker run registry.adinusa.id/btacademy/redis  # CTRL + c untuk keluar
docker run -d registry.adinusa.id/btacademy/redis  # menjalankan di background
docker run -d --name redis1 registry.adinusa.id/btacademy/redis # memberi nama Container
```

#### Lihat Container yang sedang berjalan
```
docker ps 
docker container ls
```

#### Lihat seluruh Docker Container
```
docker ps -a
docker container ls -a
```

#### Lihat deskripsi Container
```
# docker inspect CONTAINER_NAME/CONTAINER_ID
docker inspect redis1
```

#### Lihat konten dan Log Container
```
# docker logs CONTAINER_NAME/CONTAINER_ID
docker logs redis1
```

#### Lihat secara langsung Resource yang digunakan Container
```
# docker stats CONTAINER_NAME/CONTAINER_ID
docker stats redis1
```

#### Lihat proses yang sedang berjalan di Container
```
# docker top CONTAINER_NAME/CONTAINER_ID
docker top redis1
```

#### Mematikan Sebuah Container
```
# docker stop CONTAINER_NAME/CONTAINER_ID
docker stop redis1
```

#### Praktek Nomer 2
#### Cari image nginx dari DockerHub & Harbor
```
# From DockerHub
docker search nginx

# From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/nginx
```

#### Jalankan image nginx dan buka ke port host
```
docker run -d --name nginx1 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
```

#### Lihat deskripsi dari nginx container.
```
docker inspect nginx1
```

#### Jalankan image Nginx dan deklarasi port Container
```
docker run -d --name nginx2 -p 80 registry.adinusa.id/btacademy/nginx:latest
```

#### Test Browsing
```
curl localhost:$(docker port nginx2 80 | cut -d : -f 2)
```

####  Lihat Container (aktif / exit)
```
docker ps -a 
docker container ls -a
```

#### Lihat Image Docker
```
docker images
```

#### Verifikasi
* Dapat menjalankan curl ke Container nginx1 & nginx2 containers
* Container redis1 berjalan

#### Tugas
Jalankan command `nusactl grade do-002-2` untuk menampilkan nilai kalian.
```
nusactl grade do-002-2
```

Lalu jalankan command `nusactl finish do-002-2` untuk membersihkan konfigurasi yang ada.
```
nusactl finish do-002-2
```

### Lab 2.3 Jalankan Docker - Part 2
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-002-3` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-002-3
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**
#### Praktek nomer 3
#### Cari image nginx dari DockerHub & Harbor
```
# From DockerHub
docker search nginx

# From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/nginx
```

####  Jalankan image nginx dengan nama nginx1 dan jalankan di port 8080
```
docker run -d --name nginx1 -p 8080:80 registry.adinusa.id/btacademy/nginx:latest
```

#### Lihat deskripsi Container nginx1
```
docker inspect nginx1
```

#### Jalankan Image nginx image dengan nginx2 dan jalankan di port 8081
```
docker run -d --name nginx2 -p 8081:80 registry.adinusa.id/btacademy/nginx:latest
```

#### Lihat container (aktif/exit)
```
docker ps -a 
docker container ls -a
```

#### Cek output Nginx di Container
```
curl localhost:8080
curl localhost:8081
```

#### Akses Container
```
docker exec -it nginx2 /bin/bash
```

#### Update dan install text editor di Container
```
apt-get update -y && apt-get install nano -y
```

#### Edit file index.html dan pindah file ke direktori default nginx
```
nano index.html
...
hello, username.
...

mv index.html /usr/share/nginx/html
```

#### Restart service Nginx
```
service nginx restart
```

#### Jalankan ulang service Nginx
```
docker start nginx2
```

#### Lihat Container
```
docker ps
docker container ls
```

#### Cek output Nginx di Container
```
curl localhost:8080
curl localhost:8081
```

#### Lihat deskripsi Container
```
docker inspect nginx1
docker inspect nginx2
```

#### Lihat log konten dalam Container
```
docker logs nginx1
docker logs nginx2
```

#### Lihat langsung Penggunaan resource Container
```
docker stats nginx1
docker stats nginx2
```

#### Lihat proses yang berjalan di Container
```
docker top nginx1
docker top nginx2
```

#### Praktek Nomer 4
#### Cari image ubuntu dari DockerHub & Harbor
```
# From DockerHub
docker search ubuntu

# From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/ubuntu
```

#### Pull image ubuntu dari Harbor
```
docker pull registry.adinusa.id/btacademy/ubuntu
```

#### Jalankan Container Ubuntu dan jalankan console
```
docker run -it --name ubuntu1 registry.adinusa.id/btacademy/ubuntu

Exit the container with Ctrl+D or exit

docker ps -a
```

#### Jalankan Container Ubuntu dan hapus ketika keluar dari Container
```
docker run -it --rm --name ubuntu2 registry.adinusa.id/btacademy/ubuntu

Exit the container with Ctrl+D or exit

docker ps -a
```

#### Verifikasi
* Dapat curl nginx1 [default nginx]
* Dapat curl nginx2 dan output nginx2 [hello, username]
* Terdapat Container Ubuntu1

#### Tugas
Jalankan command `nusactl grade do-002-3` untuk menampilkan nilai kalian.
```
nusactl grade do-002-3
```

Lalu jalankan command `nusactl finish do-002-3` untuk membersihkan konfigurasi.
```
nusactl finish do-002-3
```

### Lab 2.4 Jalankan Docker - Part 3
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-002-4` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-002-4
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**
#### Praktek nomer 5
#### Jalankan container MySQL dengan parameter tambahan
```
docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD=RAHASIA -e MYSQL_DATABASE=latihan05 -p 3306:3306 \
registry.adinusa.id/btacademy/mysql
```

#### Pull Image phpmyadmin dari Harbor
```
docker pull registry.adinusa.id/btacademy/phpmyadmin:latest
```

#### Jalankan Container phpmyadmin dan koneksikan dengan Container mysql
```
docker run --name my-phpmyadmin -d --link my-mysql:db -p 8090:80 \
registry.adinusa.id/btacademy/phpmyadmin
```

#### Test Di Browser Host
Buka broser kalian, ketik `http://10.10.10.11:8090` login dengan user: 'root' dan password 'RAHASIA'

#### Praktek nomer 6
#### Jalankan Container ubuntu dengan nama ubuntu1 & ubuntu2
```
docker run -dit --name ubuntu1 registry.adinusa.id/btacademy/ubuntu
docker run -dit --name ubuntu2 registry.adinusa.id/btacademy/ubuntu
```

#### Lihat list Container
```
docker ps
```

#### Pause Container Ubuntu
```
docker pause ubuntu1
docker pause ubuntu2
```

#### Cek Container apakah statusnya paused.
```
docker ps
```

#### Cek penggunaan resource ketika Container di paused
```
docker stats ubuntu1
docker stats ubuntu2
```

#### Jalankan kembali (unpause) Container Ubuntu1
```
docker unpause ubuntu1
```

#### Praktek Nomer 7
#### Buat Container Database dengan limit spesifikasi
```
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
 ```
 
 #### Buat sebuah Container Wordpress dan koneksikan dengan Container Database
 ```
 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
```

#### Cek logs, proses running, dan resource
```
docker logs ch6_mariadb
docker logs ch6_wordpress

docker top ch6_mariadb
docker top ch6_wordpress

docker stats ch6_mariadb
docker stats ch6_wordpress
```

#### Tes Browsing
Buka browser host kalian, ketik `http://10.10.10.11` lalu selesaikan instalasinya

#### Verifikasi
* Dapat akses wordpress dengan English
* phpmyadmin dapat di akses
* Status ubuntu2 paused
* Container wordpress sesuai spesifikasi yang ada

#### Tugas
Jalankan command `nusactl grade do-002-4` untuk menampilkan nilai kalian.
```
nusactl grade do-002-4
```

Lalu jalankan command `nusactl finish do-002-4` untuk membersihkan konfigurasi.
```
nusactl finish do-002-4
```

## 3. Mengelola Docker Container
Tujuan yang akan dicapai:
> 1. Memahami perintah-perintah dasar Docker Client untuk membuat, menjalankan, dan mengelola siklus hidup container.
> 2. Mengerti cara membuat container baru, menjalankan perintah di dalam container yang sedang berjalan, serta menjalankan container dalam mode interaktif.
> 3. Memahami konsep Docker Registry, baik untuk registry publik maupun private, serta kegunaan dan perbedaannya.
> 4. Mengetahui penggunaan Docker Volume untuk menyimpan dan berbagi data antar container atau mesin.
> 5. Memahami konsep dasar Docker Network, termasuk driver jaringan yang tersedia dan cara kerjanya.
> 6. Mengerti pilihan dan kasus penggunaan yang tepat untuk setiap driver jaringan Docker.
> 7. Memahami pentingnya manajemen siklus hidup container dalam pengembangan dan pengelolaan aplikasi menggunakan Docker.
### Mengelola siklus Hidup Container - Part 1
Tujuan dari bagian ini, kalian mampu mengelola siklus hidup suatu Container mulai dari pembuatan hingga penghapusan

**Docker Client Verbs**
Klien Docker, diimplementasikan dengan perintah docker, menyediakan serangkaian kata kerja untuk membuat dan mengelola container. Gambar berikut menunjukkan ringkasan kata kerja yang paling umum digunakan untuk mengubah status container.
![image](https://hackmd.io/_uploads/S1bWOEyRp.png)

Klien Docker juga menyediakan serangkaian kata kerja untuk memperoleh informasi tentang menjalankan dan menghentikan container. Gambar berikut menunjukkan ringkasan kata kerja yang paling umum digunakan untuk menanyakan informasi terkait kontainer Docker.
![image](https://hackmd.io/_uploads/SJyX_NkA6.png)

Gunakan kedua gambar ini sebagai referensi saat Anda mempelajari kata kerja perintah Docker.

**Membuat Container**
Perintah docker run membuat container baru dari image dan memulai proses di dalam container baru. Jika gambar kontainer tidak tersedia, perintah ini juga mencoba mendownloadnya:
```
ubuntu@ubuntu20:~$ docker run -d nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
d121f8d1c412: Pull complete 
ebd81fc8c071: Pull complete 
655316c160af: Pull complete 
d15953c0e0f8: Pull complete 
2ee525c5c3cc: Pull complete 
Digest: sha256:c628b67d21744fce822d22fdcc0389f6bd763daac23a6b77147d0712ea7102d0
Status: Downloaded newer image for nginx:latest
bc17ead1a9a36294d511aa3ce40a667aa851b4337bbd404edb7b78087e81da54
ubuntu@ubuntu20:~$
```
> Opsi penting lainnya adalah menjalankan container sebagai daemon, menjalankan proses dalam container di latar belakang. Opsi -d bertanggung jawab untuk berjalan dalam mode terpisah.

Perintah `docker ps` bertanggung jawab menampilkan deskripsi tentang container.
![image](https://hackmd.io/_uploads/SkNRuE1Ap.png)

**Container ID** di generated secara otomatis dan harus unik
**Names** dapat di generated secara otomatis atau secara manual dengan menggunakan `--name`
```
ubuntu@ubuntu20:~$ docker run -d --name my-nginx-container nginx
```

> **Note:** nama harus unik, dan akan error ketika nama sudah pernah digunakan.

Image Container itu sendiri menentukan perintah yang akan dijalankan untuk memulai proses yang dikontainerisasi, tetapi perintah yang berbeda dapat ditentukan setelah nama image kontainer di docker run:
```
ubuntu@ubuntu20:~$ docker run nginx ls /usr
bin
games
include
lib
local
sbin
share
src
```
> karena command spesifik di berikan di contoh sebelumnya, nginx service tidak berjalan

Untuk menjalankan container di Bash Shell, dapat menggunakan command berikut:
```
ubuntu@ubuntu20:~$ docker run --name my-nginx-container -it nginx /bin/bash
root@190caba3547d:/# 
```

**Menjalankan Command di Container**
Ketika sebuah Container dibuat, perintah default dijalankan sesuai dengan apa yang ditentukan oleh image container. Namun, mungkin perlu menjalankan perintah lain untuk mengelola container yang sedang berjalan. Perintah docker exec memulai proses tambahan di dalam container yang sedang berjalan:
```
ubuntu@ubuntu20:~$ docker exec 5d0c8fa3c1d9 cat /etc/hostname
5d0c8fa3c1d9
```

Contoh sebelumnya menggunakan ID kontainer untuk menjalankan perintah. Dimungkinkan juga untuk menggunakan nama Container:
```
ubuntu@ubuntu20:~$ docker exec my-nginx-container cat /etc/hostname
5d0c8fa3c1d9
```

### Mengelola siklus hidup Container - Part 2
### Mengelola Container
Docker Menyediakan perintah berikut untuk mengelola Container:
**docker ps** : Perintah ini bertanggung jawab untuk menampilkan daftar kontainer yang sedang berjalan.
**CONTAINER ID** Setiap kontainer, saat dibuat, mendapatkan ID kontainer, yang merupakan nomor heksadesimal dan terlihat seperti ID imager, tetapi sebenarnya tidak terkait.
**IMAGE** Image kontainer yang digunakan untuk memulai kontainer.
**COMMAND** Perintah yang dieksekusi saat kontainer mulai.
**CREATED** Tanggal dan waktu kontainer dimulai.
**STATUS** Total waktu kontainer berjalan, jika masih berjalan, atau waktu sejak ditutup.
**PORT** Port yang diungkapkan oleh kontainer atau penerusan port, jika dikonfigurasi.
**NAMES** Nama kontainer.

### Docker Registry
### Tentang Public Registry
Registry adalah penyimpanan image yang terpusat di mana pengguna dapat menyimpan image yang telah dibuat atau mereka ikut berpartisipasi dalam pembuatan image tersebut. Fungsi utama dari registry adalah menyediakan tempat penyimpanan yang terpusat untuk berbagai jenis image. Seperti halnya situs hub.docker.com, di registry tersebut terdapat berbagai macam image yang populer seperti php, mysql, nginx, python, golang, dan lain sebagainya.

### Docker Registry
Docker registry adalah sistem penyimpanan dan distribusi untuk image Docker. image dapat memiliki beberapa versi yang berbeda, diidentifikasi oleh tag. Registry terorganisir ke dalam repositori, di mana setiap repositori menyimpan semua versi dari sebuah image. Pengguna Docker dapat menarik (pull) image dari registry dan mengunggah (push) image baru ke dalamnya. Secara default, Docker engine berinteraksi dengan DockerHub sebagai registry publik, tetapi juga memungkinkan untuk menjalankan registry Docker secara lokal atau menggunakan registry publik lainnya yang tersedia secara online.
![image](https://hackmd.io/_uploads/SJhlJHk06.png)

### Private Registry
Docker private registry adalah tempat penyimpanan dan manajemen image Docker pribadi. Ini bisa diselenggarakan oleh penyedia layanan atau secara mandiri. Registry ini memungkinkan berbagi image di dalam organisasi atau dengan kelompok terbatas. Dengan private registry, Anda dapat mengendalikan akses image Anda, penting terutama untuk data sensitif atau image yang tidak boleh dipublikasikan secara terbuka.

### Harbor
Harbor adalah registry open-source yang menawarkan keamanan dengan kebijakan akses dan kontrol berbasis peran, pemindaian image untuk mengidentifikasi kerentanan, serta penandaan image sebagai terpercaya. Proyek ini, sebagai bagian dari CNCF, memberikan kepatuhan, kinerja, dan interoperabilitas untuk pengelolaan artefak yang konsisten dan aman di platform komputasi cloud native seperti Kubernetes dan Docker.
![image](https://hackmd.io/_uploads/Sk6uJSkRa.png)

### Docker Volume
Volumes adalah mekanisme yang disukai untuk menyimpan data yang dihasilkan dan digunakan oleh Container Docker. Mereka lebih mudah dicadangkan dan dipindahkan daripada bind mounts, dapat dikelola menggunakan Docker CLI atau API, berfungsi di berbagai sistem operasi, lebih aman untuk dibagikan di antara kontainer, dan dapat memiliki fungsionalitas tambahan seperti enkripsi. Volumes juga memiliki kinerja yang lebih tinggi di Docker Desktop dibandingkan dengan bind mounts. Lebih baik daripada menyimpan data di dalam lapisan yang dapat ditulis oleh kontainer karena tidak memperbesar ukuran kontainer dan kontennya ada di luar siklus hidup kontainer. Jika kontainer menghasilkan data keadaan non-persisten, pertimbangkan untuk menggunakan tmpfs mount untuk meningkatkan kinerja dan menghindari penyimpanan data permanen.

### Share Data among Machines
Untuk membangun aplikasi fault-tolerant, Anda perlu memastikan bahwa beberapa replika layanan dapat mengakses file yang sama. Anda bisa menyimpan file pada sistem penyimpanan objek cloud seperti Amazon S3 atau menggunakan volume dengan driver yang mendukung penulisan ke sistem penyimpanan eksternal seperti NFS atau Amazon S3. Dengan menggunakan driver volume, Anda bisa mengabstraksi sistem penyimpanan dari logika aplikasi, memungkinkan Anda untuk mengubah penyimpanan tanpa perlu mengubah logika aplikasi.

### Docker Network
### Networking Overview
Container dan layanan Docker dapat terhubung satu sama lain atau dengan beban kerja non-Docker dengan lancar tanpa perlu menyadari lingkungan implementasinya. Docker menyediakan manajemen yang tidak tergantung pada platform, memungkinkan pengelolaan yang mudah tanpa memperhatikan sistem operasi yang digunakan. Memahami konsep jaringan Docker memungkinkan perancangan dan implementasi aplikasi yang efektif untuk memaksimalkan kemampuan ini.

### Driver Network
Sistem jaringan Docker dapat disesuaikan dengan menggunakan driver. Ada beberapa driver yang sudah tersedia secara default dan memberikan fungsionalitas inti jaringan:
- bridge: Ini adalah driver jaringan default. Jika Anda tidak menyebutkan driver, maka jaringan yang dibuat akan menggunakan tipe ini. Jaringan bridge umumnya digunakan saat aplikasi berjalan di dalam kontainer mandiri yang perlu berkomunikasi.

- host: Ini digunakan untuk kontainer mandiri yang ingin dihubungkan langsung ke jaringan host tanpa isolasi.

- overlay: Jaringan overlay menghubungkan beberapa daemon Docker bersama dan memungkinkan layanan swarm berkomunikasi antara satu sama lain.

- macvlan: Driver ini memungkinkan kontainer muncul sebagai perangkat fisik pada jaringan, berguna saat berurusan dengan aplikasi yang membutuhkan koneksi langsung ke jaringan fisik.

- none: Nonaktifkan semua jaringan untuk kontainer ini, sering digunakan bersama dengan driver jaringan kustom.

Plugin Jaringan: Anda juga bisa menggunakan plugin jaringan pihak ketiga dengan Docker. Plugin ini bisa diunduh dari Docker Hub atau vendor lainnya.

### Ringkasan Driver Jaringan
Ringkasan Driver Jaringan;
- Jaringan bridge berguna saat banyak kontainer perlu berkomunikasi di host Docker yang sama.
- Jaringan host cocok jika Anda ingin kontainer terhubung langsung ke jaringan host.
- Jaringan overlay berguna saat kontainer berjalan di host Docker yang berbeda atau saat aplikasi bekerja bersama menggunakan layanan swarm.
- Jaringan macvlan berguna saat Anda ingin kontainer terlihat seperti host fisik pada jaringan.
- Plugin jaringan pihak ketiga memungkinkan integrasi Docker dengan tumpukan jaringan tertentu.

### Lab 3.1 Mount Volume
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-003-1` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-003-1
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Buat working directory
```
cd $HOME
mkdir -p latihan/latihan01-volume
cd latihan/latihan01-volume
```

#### Buat file dan container untuk data volum dengan `my-volume`
```
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 
```

#### Mount Volume ke Container
```
docker run --volumes-from my-volume registry.adinusa.id/btacademy/ubuntu ls /my-volume
```

#### Verifikasi
* my-volume Container terbuat, mounted dan memuat file yang barusan di buat

#### Tugas
Jalankan command `nusactl grade do-003-1` untuk menampilkan nilai kalian.
```
nusactl grade do-003-1
```

Lalu jalankan command `nusactl finish do-003-1` untuk membersihkan konfigurasi.
```
nusactl finish do-003-1
```

### Lab3.2 Mount Volume dengan NFS Server
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-003-2` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-003-2
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Buat Working Direktori
```
sudo mkdir -p /data/nfs-storage01/
```

#### Buat NFS server dengan Docker
```
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
```

#### Instruksi
**Eksekusi di pod-[username]-node02**

#### Install Paket yang diperlukan, pasang volume pada klien NFS dan buat file untuk memeriksa volume
```
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
```

#### Instruksi
**Eksekusi di pod-[username]-node01**
#### Verifikasi Volume
```
ls /data/nfs-storage01/
```

#### Verifikasi
* Pastikan seluruh file di direktori yang di kaitkan sudah Mounted ke node1

#### Tugas
Jalankan command `nusactl grade do-003-2` untuk menampilkan nilai kalian.
```
nusactl grade do-003-2
```

Lalu jalankan command `nusactl finish do-003-2` untuk membersihkan konfigurasi.
```
nusactl finish do-003-2
```

### Lab 3.3 Mount Volume dengan mode Read-Only
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-003-3` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-003-3
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Buat volume docker
```
docker volume create my-vol
```

#### Liat list volume docker
```
docker volume ls
```

#### Liat detail volume docker
```
docker volume inspect my-vol
```

#### Jalankan Container dengan akses volume read and write
```
docker run -d --name=nginx-rwvol -v my-vol:/usr/share/nginx/html -p 4005:80 registry.adinusa.id/btacademy/nginx:latest
```

#### Lihat IP address Container
```
docker inspect nginx-rwvol | jq -r '.[].NetworkSettings.IPAddress'
```

#### Test browsing IP address Container
```
curl http://172.17.X.X
```
> Untuk IP address sesuaikan dengan IP address Container

#### Buat file index.html dan pindah ke source direktori volume
```
sudo echo "This is from my-vol source directory" > index.html
sudo mv index.html /var/lib/docker/volumes/my-vol/_data
```

#### Test browsing IP address Container
```
curl http://172.17.X.X
```
> Untuk IP address sesuaikan dengan IP address Container

#### Jalankan Container dengan akses volume read-only
```
docker run -d --name=nginx-rovol -v my-vol:/usr/share/nginx/html:ro registry.adinusa.id/btacademy/nginx:latest
```

#### Lihat detail container nginx-rovol dan beri perhatian ke mode di bagian Mounts
```
docker inspect nginx-rovol | jq '.[].Mounts'
```

#### Verifikasi
* Pastikan volume docker telah terbuat dan ketika di curl spesifik seperti modul
* Pastikan container nginxtest-rovol berjalan dengan read-only

#### Tugas
Jalankan command `nusactl grade do-003-3` untuk menampilkan nilai kalian.
```
nusactl grade do-003-3
```

Lalu jalankan command `nusactl finish do-003-3` untuk membersihkan konfigurasi.
```
nusactl finish do-003-3
```

### Lab 3.4 Volume Driver
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-003-4` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-003-4
```
#### Instruksi
**Eksekusi di node pod-[username]-node02**

#### Buat direktori /share dan buat file index.html
```
sudo mkdir /share
sudo chmod 777 /share
echo "Hello Adinusa!" > /share/index.html
```

#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Install plugin sshfs dan set plugin sshfs
```
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
```
>**Note:** Pastikan node01 dapat ssh ke node02 tanpa password

#### Jalankan Container dengan Volume
```
docker run -d --name=nginxtest-sshfs -p 8090:80 -v sshvolume:/usr/share/nginx/html registry.adinusa.id/btacademy/nginx:latest
```

#### Test browsing
```
docker ps
curl http://localhost:8090
```

#### Verifikasi
* Pastikan direktori share sudah terbuat dan file index.html ada dalam folder
* Volume Docker terbuat dengan sshfs driver

#### Tugas
Jalankan command `nusactl grade do-003-4` untuk menampilkan nilai kalian.
```
nusactl grade do-003-4
```

Lalu jalankan command `nusactl finish do-003-4` untuk membersihkan konfigurasi.
```
nusactl finish do-003-4
```

### Lab 3.5 Default Bridge Network
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-003-5` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-003-5
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Lihat list network docker
```
sudo docker network ls
```

#### Jalankan container 2 alphine di ash shell
```
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
```

#### Buat baru network docker dan kaikan dengan container alpine 1
```
docker network create --driver bridge bridge1
docker network connect bridge1 alpine1
```

#### Cek IP address container alpine2
```
docker inspect alpine2  | jq -r '.[].NetworkSettings.IPAddress'
```

#### Akses Container alpine1
```
docker exec -it alpine1 sh
```

#### Lihat IP Address container alpine1
```
ip add
```

#### Tes ping ke internet (Sukses)
```
ping -c 3 8.8.8.8
```

#### Tes ping ke container Alpine2 (sukses)
```
ping -c 3 172.17.X.X
```

#### Tes ping ke nama container alpine2 (gagal)
```
ping -c 3 alpine2
```

#### Keluar dari container alpine 1 tanpa menutup shell, tekan Ctrl+P, Ctrl+Q.

#### Verifikasi
* Pastikan network bridge1 telah terbentuk dan terkoneksi ke container alpine 1 dan dapat ping google

#### Tugas
Jalankan command `nusactl grade do-003-5` untuk menampilkan nilai kalian.
```
nusactl grade do-003-5
```

Lalu jalankan command `nusactl finish do-003-5` untuk membersihkan konfigurasi.
```
nusactl finish do-003-5
```

### Lab 3.6 Host Network
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-003-6` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-003-6
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Jalankan Container nginx dengan network host
```
docker run -itd --network host --name my_nginx registry.adinusa.id/btacademy/nginx
```

#### Tes browsing localhost
```
curl http://localhost
```

#### Verifikasi IP address dan terhubung di port 80
```
ip add
sudo netstat -tulpn | grep :80
```

#### Tugas
Jalankan command `nusactl grade do-003-6` untuk menampilkan nilai kalian.
```
nusactl grade do-003-6
```

Lalu jalankan command `nusactl finish do-003-6` untuk membersihkan konfigurasi.
```
nusactl finish do-003-6
```

## 4. Membuat Custom Image Container Docker

Docker memungkinkan Anda untuk membuat, mengelola, dan mengakses kontainer aplikasi. Anda dapat menggunakan image kontainer yang telah dibuat sebelumnya atau membuat image kustom menggunakan Dockerfile. Dengan Docker, Anda dapat mengelola siklus hidup kontainer dari pembuatan hingga penghapusan, menyimpan data aplikasi melalui penyimpanan persisten, dan memberikan akses jaringan ke kontainer melalui penerusan port.
Tujuan yang akan dicapai:
> 1. Memahami konsep dasar Docker Images dan bagaimana struktur lapisan file digunakan untuk membuat image container.
> 2. Mengerti peran Docker Registry dalam menyimpan dan mendistribusikan image Docker, serta perbedaannya dengan Docker Hub.
> 3. Mampu menjalankan Docker Registry sendiri untuk keperluan penyimpanan dan distribusi image Docker secara lokal.
> 4. Memahami penggunaan Dockerfile sebagai instruksi untuk merakit image container Docker.
> 5. Mampu membuat image container Docker kustom menggunakan Dockerfile dengan instruksi yang tepat sesuai kebutuhan aplikasi.
### Docker Images
### Apa itu Images ?
Di Linux, segalanya adalah sebuah file. Sistem operasi secara mendasar adalah sebuah sistem file dengan file dan folder disimpan di disk lokal. Ini adalah fakta penting yang perlu diingat ketika mempertimbangkan apa yang merupakan image kontainer. Seperti yang akan kita lihat, sebuah image pada dasarnya adalah sebuah tarball besar yang berisi sebuah sistem file. Lebih spesifik, image tersebut mengandung sebuah sistem file berlapis.

### Sistem layer file

image kontainer adalah templat dari mana kontainer dibuat. image-image ini tidak terdiri dari satu blok monolitik saja, tetapi terdiri dari banyak lapisan. Lapisan pertama dalam image juga disebut sebagai lapisan dasar. Ini dapat dilihat dalam grafik berikut: [gambar yang mengilustrasikan struktur lapisan image kontainer].

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


Image kontainer terdiri dari tumpukan lapisan yang berisi perubahan terhadap sistem file dari lapisan yang mendasarinya. Lapisan-lapisan ini bersifat tak berubah, yang berarti sekali dibuat, mereka tidak dapat diubah kecuali dihapus. Berbagai driver penyimpanan mengelola cara lapisan-lapisan ini berinteraksi. Ini membuka peluang besar dalam manajemen kontainer. Sebuah contoh image kustom untuk aplikasi web menggunakan Nginx sebagai server web dapat dilihat:

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

Sebuah sampel image kostum berdasarkan Alpine dan Nginx


image ini terdiri dari tiga lapisan: Alpine Linux sebagai lapisan dasar, Nginx ditambahkan di atasnya, dan lapisan ketiga berisi file-file aplikasi web. Image-image biasanya dimulai dengan image dasar seperti distro Linux resmi dari Docker Hub, namun juga bisa dibuat dari awal.

### Docker Registry

Docker Registry adalah aplikasi open-source untuk menyimpan image Docker di mana pun Anda inginkan. Dibandingkan dengan Docker Hub, kita akan memahami perbedaan antara keduanya dan bagaimana memilih yang sesuai. Pada akhirnya, Anda akan belajar cara menjalankan Docker Registry sendiri untuk menentukan apakah cocok untuk kebutuhan Anda.

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


Docker Registry memungkinkan Anda untuk meng-host dan mengelola registry sendiri, menyesuaikan visibilitas repositori, dan penskalaan sesuai kebutuhan, semuanya melalui antarmuka baris perintah.

#### Docker Hub

Docker Hub adalah platform untuk membuat, mengelola, dan menyebarkan aplikasi kontainer tim Anda. Repositori Docker Hub memungkinkan berbagi image kontainer dengan tim, pelanggan, atau komunitas Docker. Pengguna mengunggah image Docker ke Docker Hub menggunakan perintah docker push, di mana satu repositori dapat menyimpan banyak image (disebut tag).

Docker Hub memberikan antarmuka berbasis GUI untuk mengelola image Anda, lokasi cloud yang siap digunakan untuk menyimpan image publik dan/atau pribadi, serta menghilangkan kekhawatiran dalam mengelola server yang menyimpan semua iamge Anda.


### Pengenalan Docker File

Dockerfile adalah file teks biasa yang berisi serangkaian instruksi yang ditentukan pengguna. Ketika Dockerfile dipanggil oleh perintah docker image build, yang akan kita lihat selanjutnya, digunakan untuk merakit image kontainer. Contoh Dockerfile:
```
FROM alpine:latest
LABEL maintainer="adinusa <admin@adinusa.id>"
LABEL description="This example Dockerfile installs NGINX."
RUN apk add --update nginx && \
    rm -rf /var/cache/apk/* && \
    mkdir -p /tmp/nginx/

COPY files/nginx.conf /etc/nginx/nginx.conf
COPY files/default.conf /etc/nginx/conf.d/default.conf
ADD files/html.tar.gz /usr/share/nginx/

EXPOSE 80/tcp

ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
```

### Lab 4.1 Menjelajah Dockerfile
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-004-1` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-004-1
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Praktek nomor 1
#### Duplikat repository untuk latihan
```
git clone https://github.com/spkane/docker-node-hello.git \
    --config core.autocrlf=input latihan01
```

#### Masuk ke Direktori
```
cd latihan01
```

#### Buat image dari repository sebelumnya dan beri nama node-exercise01
```
docker build -t node-latihan01 .
```

#### Jalankan Container dengan image yang baru di buat, dan jalankan di port 8080.
```
docker run -d --rm --name node-latihan01 -p 8080:8080 node-latihan01
```

#### Coba akses Container
```
curl localhost:8080
```

#### Praktek Nomor 2
#### Buat direktori latihan02
```
cd $HOME
mkdir latihan02
cd latihan02
```

#### buat Dockerfile seperti 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
...
```

#### Buat image dari Dockerfile
```
docker build -t docker-whale .
```

#### Lihat image yang sudah di buat
```
docker image ls
```

#### Coba jalankan image
```
docker run docker-whale
```

#### Lihat container
```
docker ps
docker container ls -a
```

#### Verifikasi
* Pastikan image node-latihan01 dan image docker-whale sudah terbuat dan bisa di jalankan

#### Tugas
Jalankan command `nusactl grade do-004-1` untuk menampilkan nilai kalian.
```
nusactl grade do-004-1
```

Lalu jalankan command `nusactl finish do-004-1` untuk membersihkan konfigurasi.
```
nusactl finish do-004-1
```

### Lab 4.2 Menjelajah Dockerfile (Flask Apps)
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-004-2` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-004-2
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Praktek Nomor 3
Jika anda tidak mempunyai docker ID, registarsi di https://hub.docker.com/signup

#### Login dengan Docker ID
```
docker login
```

#### Buat direktori latihan03
```
cd $HOME
mkdir latihan03
cd latihan03
```

#### Buat file flask
```
sudo nano 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')
...
```

#### Buat file requirements.txt
```
sudo nano requirements.txt
...
Flask==0.10.1
Werkzeug==1.0.0
Jinja2==2.8.1
MarkupSafe==1.1.1
itsdangerous==1.1.0
...
```

#### Buat Dockerfile
```
sudo nano 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"]
...
```

#### Buat image dari Dockerfile
```
docker build -t flask-latihan03 .
```

#### Tag image dengan username docker
```
docker tag flask-latihan03 [usernamedocker]/flask-latihan03:latest
```

#### Push image ke dockerhub
```
docker push [usernamedocker]/flask-latihan03:latest
```

#### Jalankan Image
```
docker run -d -p 5000:5000 --name flask03 [usernamedocker]/flask-latihan03
```

#### Test browsing
```
curl localhost:5000
```

#### Verifikasi
* Pastikan semuanya sudah sesuai dengan requested folder
* Pastikan image sudah di tage dengan username docker
* Pastikan container menyala dan outputnya seperti app.py

#### Tugas
Jalankan command `nusactl grade do-004-2` untuk menampilkan nilai kalian.
```
nusactl grade do-004-2
```

Lalu jalankan command `nusactl finish do-004-2` untuk membersihkan konfigurasi.
```
nusactl finish do-004-2
```

### Lab 4.3 Exploring Dockerfile (Quiz)
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-004-3` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-004-3
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Quiz
1. Buat direktori latihan-quiz01, lalu masuk ke direktori
2. Clone repository dari github `https://github.com/rivawahyuda/mywebsite.git`
3. Buat Dockerfile didalam direktori latihan-quiz01 dengan kondisi:
    * Menggunakan image : `registry.adinusa.id/btacademy/nginx:latest`
4. Buat image dengan nama latihan-quiz02-image
5. Jalankan container dengan image latihan-quiz01-image, jalankan di port 80 dan namai quiz01
6. Tes browsing, pastikan tidak membuka default web nginx.


#### Jawaban Quiz
#### 1. Buat direktori Latihan-quiz01 dan masuk kedalamnya
```
mkdir latihan-quiz01
cd latihan-quiz01
```

#### 2. Clone repository
```
git clone https://github.com/rivawahyuda/mywebsite.git
```

#### 3. Buat Dockerfile
```
nano Dockerfile
~~~
# Dockerfile
FROM registry.adinusa.id/btacademy/nginx:latest
COPY ./mywebsite /usr/share/nginx/html
~~~
```

#### 4. Build image Docker
```
docker build -t latihan-quiz01-image .
```

#### 5. Jalankan Container Docker
```
docker run -d -p 80:80 --name quiz01 latihan-quiz01-image
```

#### 6. Test Browsing
```
http://localhost
```

#### Tugas
Jalankan command `nusactl grade do-004-3` untuk menampilkan nilai kalian.
```
nusactl grade do-004-3
```

Lalu jalankan command `nusactl finish do-004-3` untuk membersihkan konfigurasi.
```
nusactl finish do-004-3
```


## 5. Pengenalan Docker Compose
Tujuan yang akan dicapai:
> 1. Memahami konsep dasar Docker Compose sebagai alat untuk mengatur dan menjalankan kontainer Docker pada satu host.
> 2. Mengerti format file docker-compose.yml dan cara menggunakan YAML untuk mendefinisikan aplikasi kontainer.
> 3. Mampu membuat file docker-compose.yml untuk menggambarkan dan menjalankan aplikasi yang terdiri dari lebih dari satu kontainer.
> 4. Memahami penggunaan layanan (services) dalam Docker Compose untuk mendefinisikan setiap komponen aplikasi.
> 5. Mampu mengaitkan volume-volumes dengan layanan-layanan yang dideklarasikan dalam docker-compose.yml.
### Docker Compose
![image](https://hackmd.io/_uploads/SJe_nWm0T.png)


**Docker Compose** adalah alat dari Docker untuk menjalankan dan mengatur kontainer pada satu host Docker. Ini berguna untuk pengembangan, CI, pengujian otomatis, QA, atau demo. File docker-compose.yml menggunakan format YAML untuk mendefinisikan aplikasi kontainer. Secara default, **Docker Compose** mengharapkan file-file ini disebut docker-compose.yml. Isi dari docker-compose.yml dikatakan sebagai cara deklaratif untuk menggambarkan dan menjalankan aplikasi yang di containerisasi yang potensial terdiri dari lebih dari satu kontainer.

Deklaratif: Ini adalah cara di mana kita bisa memecahkan masalah tanpa memerlukan programmer untuk menentukan prosedur yang tepat yang harus diikuti.

"deklaratif" adalah antonim dari "imperatif".

Imperatif: Ini adalah cara di mana kita bisa memecahkan masalah dengan menentukan prosedur yang tepat yang harus diikuti oleh sistem.

### File simple dokcer-compose.yml
* Cloning repositori untuk dokcer compose
```
git clone https://github.com/ammarun11/Docker-For-DevOps.git
cd Docker-For-DevOps/exercise/practice03
```

* Buat file docker-compose.yml
```
cat docker-compose.yml
```

```
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:
 ```
 
 **NOTE:**
 
 * version: Pada baris ini, kita menentukan versi format Docker Compose yang ingin kita gunakan. Pada saat penulisan, ini adalah versi 2.4.
 
 * services: Pada bagian ini, kita menentukan layanan-layanan yang membentuk aplikasi kita dalam blok layanan. Pada contoh kita, kita memiliki dua layanan aplikasi dan kita menyebutnya web dan db:
 
 * web: Layanan web menggunakan image yang disebut palopalepalo/web:1.0, yang, jika belum ada di cache image, dibangun dari Dockerfile yang ditemukan di folder web. Layanan juga mempublikasikan port kontainer 3000 ke port host 80.
 
 * db: Layanan db, di sisi lain, menggunakan nama image palopalepalo/db:1.0, yang merupakan basis data PostgreSQL yang disesuaikan. Sekali lagi, jika image belum ada di cache, dibangun dari Dockerfile yang ditemukan di folder db. Kita mengaitkan volume yang disebut pets-data ke dalam kontainer dari layanan db.
 
 * volumes: Volume-volume yang digunakan oleh salah satu layanan harus dideklarasikan dalam bagian ini. Pada contoh kita, ini adalah bagian terakhir dari file. Ketika aplikasi dijalankan untuk pertama kalinya, sebuah volume bernama pets-data akan dibuat oleh Docker dan kemudian, dalam jalanan-jalanan berikutnya, jika volume masih ada, akan digunakan kembali. 



### Lab 5.1 Menggunakan Docker Compose
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-005-1` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-005-1
```
#### Instruksi
**Eksekusi di node pod-[username]-node01 dan pod-[username]-node02**

#### Download dan Install Compose
```
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
```

#### Cek apakah compose sudah ter install
```
docker-compose --version
```

#### Instruksi
**Eksekusi di node pod-[username]-node01

#### Buat direktori my_wordpress dan masuk ke direktori
```
cd $HOME
mkdir -p latihan/my_wordpress
cd latihan/my_wordpress
```

#### Buat file docker-compose
```
nano docker-compose.yml
```

```
version: '3.2'

services:
   db:
     image: registry.adinusa.id/btacademy/mysql:5.7
     volumes:
       - dbdata:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: [username]
       MYSQL_PASSWORD: [password]

   wordpress:
     depends_on:
       - db
     image: registry.adinusa.id/btacademy/wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: [username]
       WORDPRESS_DB_PASSWORD: [password]
volumes:
    dbdata:
```

Note : jangan lupa mengganti [usermae] dan [password]

#### Jalankan compose
```
docker-compose up -d
```

#### Lihat list container dan tes browsing wordpress yang sudah di buat
```
docker container ls
```

#### Verifikasi
* pastikan docker-compose telah terinstall di seluruh node dan container up (menyala)

#### Tugas
Jalankan command `nusactl grade do-005-1` untuk menampilkan nilai kalian.
```
nusactl grade do-005-1
```

Lalu jalankan command `nusactl finish do-005-1` untuk membersihkan konfigurasi.
```
nusactl finish do-005-1
```

## 6. Docker Continous Integration (CI)
Tujuan yang akan dicapai:
> 1. Memahami konsep Continuous Integration (CI) dan pentingnya dalam pengembangan perangkat lunak modern.
> 2. Mengerti alur kerja CI menggunakan Docker sebagai bagian dari proses pengujian otomatis.
> 3. Mengetahui bagaimana GitHub digunakan sebagai repositori kode sumber dan bagaimana Jenkins berintegrasi dengan GitHub melalui webhook untuk memulai proses CI.
> 4. Memahami peran Docker dalam proses CI, termasuk pembangunan image Docker dan pengujian dalam kontainer Docker.
> 5. Mengetahui cara Docker Hub Automated Build memungkinkan otomatisasi pembangunan image Docker dari repositori kode sumber eksternal.
### CI Menggunakan Docker

CI adalah praktik development yang meminta developer untuk sering mengintegrasikan kode ke repositori bersama. Setiap pengiriman diverifikasi oleh automated build untuk mendeteksi masalah lebih awal. CI/CD menggabungkan developments dengan pengujian, memungkinkan developer membangun dan menguji kode secara otomatis, mempercepat proses development dan menghilangkan bug lebih cepat. Dengan dukungan Docker untuk alat seperti Jenkins dan GitHub, developer dapat mengirimkan dan menguji kode dengan mudah, memicu automated build, dan menyimpan image Docker dengan efisien. Ini mempercepat proses, menghemat waktu, dan memungkinkan developer untuk menjalankan tes secara paralel, menjaga produktivitas mereka. berikut alur dari CI:

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

1. Developer melakukan commit ke GitHub
2. GitHub menggunakan webhook untuk memberi tahu Jenkins tentang pembaruan
3. Jenkins menarik repositori GitHub, termasuk Dockerfile yang menggambarkan image, serta kode aplikasi dan tes.
4. Jenkins membangun sebuah image Docker pada node penjinak Jenkins
5. Jenkins menginisialisasi kontainer Docker pada node penjinak, dan menjalankan tes yang sesuai
6. Jika tes berhasil, image kemudian diunggah ke Dockerhub atau Docker Trusted Registry.

### Docker Hub Automated Build

Docker Hub bisa otomatis membangun image dari kode sumber eksternal dan mendorongnya ke repositori Docker Anda. Saat Anda menyiapkan automated build, Docker Hub membuat image dari cabang dan tag yang Anda tentukan. Ketika Anda mendorong kode ke cabang yang sesuai, pembangunan baru dipicu dan hasilnya diunggah ke Docker Hub. Ini memastikan image dibangun sesuai spesifikasi, Dockerfile dapat diakses oleh siapa pun, dan repositori tetap terupdate otomatis. Sistem ini mendukung repositori publik dan pribadi di GitHub dan Bitbucket.

**Status Build**
* Queued :  dalam antrian untuk building image.
* Building : image sedang dibangun
* Success : Image telah dibangun tanpa masalah
* Error : Ada masalah dengan image anda

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

## 7. Docker swarm & portainer
Tujuan yang akan dicapai:
> 1. Dapat menjelaskan Docker swarm dan portainer
> 2. membangun image kostum container dengan portainer

### Apa itu swarm ?

Swarm adalah klaster dari satu atau lebih komputer yang menjalankan Docker, memungkinkan orkestrasi dan pengelompokan. Fitur-fitur seperti pemeriksaan kesehatan dan penyeimbangan beban disertakan secara langsung. Swarm dan Docker Compose sekarang merupakan bagian bawaan dari Docker, dengan fungsionalitas yang terintegrasi ke dalam mesin Docker. Saat menjalankan kontainer dalam mode layanan, Swarm mengelola siklus hidup layanan dengan mencoba menghidupkan jumlah replika yang diinginkan. Ini mirip dengan Kubernetes.


### Docker Swarm
Docker Swarm adalah sekelompok mesin fisik atau virtual yang menjalankan aplikasi Docker dan telah dikonfigurasi untuk bergabung dalam sebuah klaster. Setelah sekelompok mesin terklaster bersama, Anda masih dapat menjalankan perintah-perintah Docker yang biasa Anda gunakan, tetapi sekarang mereka akan dilaksanakan oleh mesin-mesin dalam kluster Anda. Aktivitas dari klaster dikendalikan oleh seorang manajer swarm, dan mesin-mesin yang telah bergabung dalam klaster disebut sebagai node.

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

### Fitur Docker Swarm
* Cluster management integrated with Docker Engine: Gunakan CLI Docker Engine untuk membuat klaster Docker Engines di mana Anda bisa mendeploy layanan aplikasi tanpa memerlukan perangkat lunak orkestrasi tambahan.

* Decentralized design: Docker Engine menangani spesialisasi pada saat runtime, bukan pada saat penempatan. Anda dapat mendeploy kedua jenis node, manajer dan pekerja, menggunakan Docker Engine. Ini berarti Anda dapat membangun sebuah klaster lengkap dari satu image disk.

* Declarative service model:  Docker Engine menggunakan pendekatan deklaratif untuk memungkinkan Anda menentukan keadaan yang diinginkan dari berbagai layanan dalam tumpukan aplikasi Anda. Sebagai contoh, Anda mungkin menggambarkan sebuah aplikasi yang terdiri dari layanan front end web dengan layanan antrian pesan dan backend database.

* Scalling : Anda dapat mendeklarasikan jumlah tugas yang ingin Anda jalankan untuk setiap layanan. Saat Anda meningkatkan atau menurunkan skala, manajer klaster secara otomatis menyesuaikan dengan menambah atau menghapus tugas untuk mempertahankan keadaan yang diinginkan.

* Desired state reconciliation: Manajer klaster secara terus-menerus memantau dan menyesuaikan keadaan klaster agar sesuai dengan keadaan yang diinginkan. Contohnya, jika ada kegagalan pada mesin pekerja yang meng-host beberapa replika, manajer akan membuat replika baru untuk menggantikannya dan menugaskan ke pekerja yang berjalan.

* Multi-host networking: Anda dapat menentukan jaringan overlay untuk layanan Anda. Manajer klaster secara otomatis menetapkan alamat ke kontainer pada jaringan overlay saat menginisialisasi atau memperbarui aplikasi.

* Service discovery: Node manajer klaster memberikan setiap layanan dalam klaster sebuah nama DNS unik dan menyeimbangkan beban kontainer yang berjalan. Anda dapat mengakses setiap kontainer yang berjalan dalam klaster melalui server DNS yang terintegrasi dalam klaster.

* Load Balancing: Anda dapat mengekspos port untuk layanan ke pengimbang beban eksternal. Secara internal, klaster memungkinkan Anda menentukan cara mendistribusikan kontainer layanan antara node.

* Secure by default: Setiap node dalam klaster menerapkan otentikasi dan enkripsi mutual TLS untuk mengamankan komunikasi antara dirinya dan semua node lain. Anda memiliki opsi untuk menggunakan sertifikat root self-signed atau sertifikat dari custom root CA.

* Rolling updates: Pada saat penyebaran, Anda dapat menerapkan pembaruan layanan ke node secara bertahap. Manajer klaster memungkinkan Anda mengontrol jeda antara penyebaran layanan ke set node yang berbeda. Jika ada yang salah, Anda dapat kembali ke versi sebelumnya dari layanan.

### Portainer
Portainer adalah alat manajemen kontainer universal yang mudah digunakan dan dapat bekerja dengan Docker dan Kubernetes. Dengan antarmuka ringan, Anda dapat mengelola sumber daya Docker Anda, termasuk kontainer, gambar, volume, dan jaringan. Ini cocok untuk pengguna dari berbagai tingkat keterampilan dan dapat diterapkan sebagai kontainer tunggal pada berbagai platform.

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

Portainer terdiri dari 2 versi:
1. Portainer Community Edition (CE) adalah fondasi. Dengan lebih dari setengah juta pengguna reguler, CE adalah set alat sumber terbuka yang kuat yang memungkinkan Anda dengan mudah membangun dan mengelola kontainer dalam Docker, Docker Swarm, Kubernetes, dan Azure ACI.

2. Portainer Business Edition (BE) adalah penawaran komersial. Dengan fitur yang ditujukan untuk bisnis dan organisasi besar seperti Role-Based Access Control, manajemen registri, dan dukungan khusus, Portainer BE adalah set alat yang kuat yang memungkinkan Anda dengan mudah membangun dan mengelola kontainer dalam Docker, Docker Swarm, Kubernetes, dan Azure ACI. 

### Lab 7.1 Membuat swarm
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-007-1` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-007-1
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Instalasi Docker Swarm
```
docker swarm init --advertise-addr 10.7.7.10
```

#### Instruksi
**Eksekusi di node pod-[username]-node02
```
docker swarm join --token [TOKEN] 10.7.7.10:2377
```

#### Instruksi
**Eksekusi di node pod-[username]-node01

#### Cek apakah node02 sudah join
```
docker node ls
```

#### Verifikasi
* Pastikan node02 sudah bergabung di docker swarm
#### Tugas
Jalankan command `nusactl grade do-007-1` untuk menampilkan nilai kalian.
```
nusactl grade do-007-1
```

Lalu jalankan command `nusactl finish do-007-1` untuk membersihkan konfigurasi.
```
nusactl finish do-007-1
```

### Lab 7.2 Deploy service di Swarm
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-007-2` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-007-2
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Buat Service Nginx dengan 2 replica, dan jalankan di port 80
```
docker service create --name web --replicas 2 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
```

#### Cek apakah Nginx sudah berjalan dengan baik di seluruh node
```
docker service ls
```

#### Tes browsing dari node01 dan node02
```
curl http://10.XX.XX.10
curl http://10.XX.XX.20
```
> **Note:** Ganti X sesuai dengan ip node kalian, dan konfigurasi yang benar akan menampilkan default landing page Nginx dari node01 dan node02

#### Cek informasi service
```
docker service inspect --pretty web
```

#### Jika ingin cek dimana service berjalan
```
docker service ps web
```

#### Buat Container dengan limit cpu serta memory
```
docker service create --name [username] --reserve-cpu 1 --limit-cpu 1 \
--reserve-memory  256mb --limit-memory 128mb registry.adinusa.id/btacademy/httpd:latest
```

#### Cek spesifikasi Container
```
docker service inspect --pretty [username]
```

#### Verifikasi
* Pastikan nginx berjalan dengan 2 replica dan dapat diakses di seluruh node
* pastikan service [username] berjalan dengan spesifikasi yang diinginkan

#### Tugas
Jalankan command `nusactl grade do-007-2` untuk menampilkan nilai kalian.
```
nusactl grade do-007-2
```

Lalu jalankan command `nusactl finish do-007-2` untuk membersihkan konfigurasi.
```
nusactl finish do-007-2
```

### Lab 7.3 Updating dan sscalling Docker swarm
#### Persiapan
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-007-3` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-007-3
```
#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Buat service Nginx dengan 3 replica
```
docker service create --name web2 --replicas 3 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
```

#### Kita dapat mengubah replica service
```
docker service scale web2=1
```

#### Cek apakah replica sudah berubah
```
docker service ls
docker service ps web2
```

#### Docker swarm dapat melakukan update secara bergulir
```
docker service update --image sistyo/myweb web2
docker service inspect --pretty web2
```

#### Verifikasi
* Pastikan menggunakan replica 1
* Pastikan updated image adalah sistyo/myweb:latest
* Pastikan update lengkap, dan dapat melihatnya dengan `docker service inspect` dan outputnya `update completed`
* Cek konfigurasi apakah benar dan bila benar akan menampilkan halaman php dari node01

#### Tugas
Jalankan command `nusactl grade do-007-3` untuk menampilkan nilai kalian.
```
nusactl grade do-007-3
```

Lalu jalankan command `nusactl finish do-007-3` untuk membersihkan konfigurasi.
```
nusactl finish do-007-3
```

### Lab 7.4 Install dan konfigurasi Portainer
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-007-4` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-007-4
```

#### Instruksi
**Eksekusi di node pod-[username]-node01**

#### Install Portainer di node01
```
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
```

#### Akses dashbord Portainer
```
Open browser and access 10.10.10.11:9000
```

#### Connect agen portainer node02 ke portainer Dashboard
* Klik menu **Environments** -> **Add Environment**
* Pilih **Docker Swarm** -> **Start Wizard**
* Pilih **Agent** -> Copy command dan jalankan di **node01**

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

#### Kembali ke Dashboard portainer
* Isi kolom nama dengan hostname node02 pod-username-node02
* Isi Environtment URL dengan ip address node02 10.7.7.20:9001
* Clik Connect

#### Untuk memastikan node02 sukses terhubung, kembali ke menu home dan anda akan melihat Environtment lain yang baru saja ditambahkan

#### Verifikasi
* Pastikan Dashboard portainer dapat di akses
* Pastikan node2 terkoneksi dengan portainer dan node2 muncul di dashboard home

#### Tugas
Jalankan command `nusactl grade do-007-4` untuk menampilkan nilai kalian.
```
nusactl grade do-007-4
```

Lalu jalankan command `nusactl finish do-007-4` untuk membersihkan konfigurasi.
```
nusactl finish do-007-4
```

### Lab 7.5 Menjalankan Container dari Portainer
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-007-5` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-007-5
```

#### Akses dashboard portainer lewat tunnel SSH
```
http://10.10.10.11:9000
```

#### Jalankan Container
* Pilih **Home** -> Node02
* Klik **Contaienr** -> Add Container
* Isi kolom nama dengan [usename]-web
* Isi kolom image dengan nginx:latest
* Klik **Publish a new netowkr port** -> isi kolom host dengan 8080 dan kolom container 80
* Node **pod-username-node** 
* Klik **Deploy Container**

#### Akses Container
```
http://10.10.10.12:8080
```

#### Verifikasi
* Pastikan container telah terbuat dan menampilkan container  [username]-web di container menu

#### Tugas
Jalankan command `nusactl grade do-007-5` untuk menampilkan nilai kalian.
```
nusactl grade do-007-5
```

Lalu jalankan command `nusactl finish do-007-5` untuk membersihkan konfigurasi.
```
nusactl finish do-007-5
```

### Lab 7.6 Build & push image dari portainer
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-007-6` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-007-6
```

#### Membuat image dari Dockerfile
* Klik menu **Image** -> + Build a new Image
* Isi kolom nama dengan {username adinusa}/nginx:lab76
* Pilih metode build **Web Editor**
* Buat Dockerfile

```
FROM registry.adinusa.id/btacademy/nginx:latest

ARG USERNAME={username adinusa}

RUN echo "nginx running on image $USERNAME/nginx:lab76" > /usr/share/nginx/html/index.html

EXPOSE 80
```
**Note:** isi username tanpa {} 
* Deploy di pod-username-node01
* Klik **Build image** -> lihat outputnya
* Cek image di menu **Images**

#### Push image ke Docker Hub
* Klik menu **Registries** -> **Add registry**
* di menu **registry provider** -> pilih **DockerHub**
    * Name: repo-{username adinusa}
    * username : {username docker}
    * Password : {password docker}
* klik **Add registry**
* kembali ke **Images**, buka image yang baru dibuat
* Di kolom registry pilih repo-username adinusa
* Di kolom imgae, isi dengan {username docker}/nginx:lab76 -> klik **Tag**
* Pilih **Push to Registry**
* Cek image apakah sudah di **pushed** ke dashbord docker hub / coba pull image

#### Verification
* Pastikan image sudah terbuat dan sudah di push ke docker hub
* pastikan ketika running `docker history {username docker}/nginx:lab76` terdapat `ARG USERNAME=username adinusa`
* Jika 2 point verifikasi telah di konfirmasi benar namun masih salah, coba `docker login` terlebih dahulu, dan jalankan grading


#### Tugas
Jalankan command `nusactl grade do-007-6` untuk menampilkan nilai kalian.
```
nusactl grade do-007-6
```

Lalu jalankan command `nusactl finish do-007-6` untuk membersihkan konfigurasi.
```
nusactl finish do-007-6
```

## 8. Logging Driver
> Dalam materi kali ini, kita akan merujuk ke logging Docker dalam konteks Logging Container, yang berarti log yang dihasilkan Container. Log ini khusus untuk Docker dan disimpan di host docker.

Docker Memiliki berbagai mekanisme logging yang disebut sebagai **logging drivers**. Secara default, Docker menggunakan logging driver json-file untuk menyimpan cache log Container sebagai JSON. Meskipun tidak ada rotasi log secara default, disarankan untuk menggunakan logging driver "local" yang melakukan rotasi log secara otomatis dan menggunakan format file yang lebih efisien. Hal ini mencegah kehabisan ruang storage (disk). Meskipun Docker tetap menggunakan logging driver json-file sebagai default untuk kompabilitas mundur dengan versi Docker yang lebih lama dan untuk penggunaan Docker sebagai runtuime Kubernetes, Logging driver "local" direkomendasikan untuk situasi lainnya.

### Lab 8.1 Konfigurasi Logging Driver
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-008-1` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-008-1
```

#### Instruksi
**Jalankan di pod-[username]-node01**

#### Buat file daemon.json
```
sudo touch /etc/docker/daemon.json
sudo nano /etc/docker/daemon.json
...
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "100"
  }
}
...
```

#### Restart Daemon dan Docker
```
sudo systemctl daemon-reload
sudo systemctl restart docker
```

#### Jalankan Container
```
docker run --log-driver json-file --log-opt max-size=10m registry.adinusa.id/btacademy/alpine echo hello world   
```

#### Cek apakah logs ada di direktori docker
```
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 .
```

ATAU

```
sudo cat /var/lib/docker/containers/CONTAINER/xxx-json.log
```
> Note: ID dapat dilihat dengan command `docker ps -a`

#### Verifikasi
* Pastikan log telah terbuat dan direktori telah di mention


#### Tugas
Jalankan command `nusactl grade do-008-1` untuk menampilkan nilai kalian.
```
nusactl grade do-008-1
```

Lalu jalankan command `nusactl finish do-008-1` untuk membersihkan konfigurasi.
```
nusactl finish do-008-1
```

## 9. Health Check
Instruksi Healthcheck dalam docker memiliki dua bentuk:
1. Menggunakan perintah CMD di dalam Container untuk memeriksa kesehatan Container
2. Menggunakan HEALTCHCHECK NONE untuk menonaktifkan healthcheck yang diwarisi dari image dasar

Healthcheck digunakan untuk memastikan Container masih berfungsi dengan baik. Status kesehatan Container berubah dari starting menjadi healthy setelah pemeriksaan berhasil dan menjadi unhealthy setelah sejumlah kegagalan berturut-turut. Opsi seperti interval, timeout dan retries dapat dikonfigurasi. Hanya satu HEALTHCHECK yang boleh ada dalam Dockefile, dan hanya perintah shell atau exec array yang bisa digunakan setelah kata kunci CMD. Status exit perintah menunjukkan status kesehatain Container. Output perintah akan disimpan untuk membantu debug

### Lab 9.1 Health check 
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-009-1` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-009-1
```

#### Instruksi
**Jalankan di pod-[username]-node01**

#### Praktek Healtch check 01

#### Buat working direktori
```
cd $HOME
mkdir hc-latihan01
cd hc-latihan01
```

#### Buat Dockerfile
```
nano Dockerfile
...
FROM registry.adinusa.id/btacademy/docker-http-server:health
HEALTHCHECK --interval=1s --retries=3 \
    CMD curl --fail http://localhost:80/ || exit 1
...
```

#### Buat image dari dockerfile
```
docker build -t http-healthcheck .
```

#### Jalankan Image
```
docker run -d -p 80:80 --name http-healthcheck http-healthcheck
```

#### Cek image
```
docker ps
# check the status section
```

#### Cek dengan curl
```
curl http://localhost/
# then accessible
```

#### Cek untuk unhealthy
```
curl http://localhost/unhealthy
```

#### Cek status container docker
```
docker container ls
```

#### Cek dengan curl
```
curl http://localhost/
```

#### Praktek Health check 02
#### Buat direktori baru
```
cd $HOME
mkdir hc-latihan02
cd hc-latihan02
```

#### Buat file server.js
```
nano server.js
...
"use strict";
const http = require('http');

function createServer () {
    return http.createServer(function (req, res) {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('OK\n');
    }).listen(8080);
}

let server = createServer();

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    if (server) {
        server.close();
        server = null;
        res.end('Shutting down...\n');
    } else {
        server = createServer();
        res.end('Starting up...\n');
    }
}).listen(8081);
...
```

#### Buat Dockerfile
```
nano Dockerfile
...
FROM registry.adinusa.id/btacademy/node
COPY server.js /
EXPOSE 8080 8081
HEALTHCHECK --interval=5s --timeout=10s --retries=3 CMD curl -sS 127.0.0.1:8080 || exit 1
CMD ["node","server.js"]
...
```

#### Buat image dari Dockerfile
```
docker build -t node-server .
```

#### Jalankan Image
```
docker run -d --name nodeserver -p 8080:8080 -p 8081:8081 node-server
```

#### Cek container
```
curl 127.0.0.1:8080
docker ps 
docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
```

#### Cek Container
```
curl 127.0.0.1:8080
docker ps 
docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
```

#### Cek Container
```
curl 127.0.0.1:8081
docker ps
docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
```

#### Verifikasi
* Container http-healthcheck dalam unhealthy state
* Container node-server healthy

#### Tugas
Jalankan command `nusactl grade do-009-1` untuk menampilkan nilai kalian.
```
nusactl grade do-009-1
```

Lalu jalankan command `nusactl finish do-009-1` untuk membersihkan konfigurasi.
```
nusactl finish do-009-1
```

## 10. Security
Tujuan yang akan dicapai:
> 1. Memahami prinsip-prinsip dasar keamanan Docker, termasuk penggunaan kernel namespaces, cgroups, dan kemampuan kernel untuk mengisolasi dan membatasi sumber daya.
> 2. Mengetahui potensi serangan terhadap Docker daemon dan cara mengurangi serangan dengan mengelola akses dan mengawasi berbagi direktori antara host dan Container.
> 3. Memahami pentingnya verifikasi tanda tangan konten Docker Trust untuk memastikan keamanan image yang dijalankan.
> 4. Mengetahui tentang fitur keamanan kernel lain yang dapat digunakan bersama dengan Docker, seperti AppArmor, SELinux, atau GRSEC, untuk meningkatkan keamanan host Docker.
> 5. Memahami kebutuhan untuk memeriksa dan mengikuti CIS Docker Benchmark untuk memvalidasi konfigurasi Docker dan menerapkan praktik keamanan yang disarankan.
> 6. Memahami konsep rahasia dalam Docker Swarm dan bagaimana Docker mengelola rahasia dengan aman untuk menyimpan dan mengakses data sensitif seperti kata sandi dan kunci SSH.

### Docker Security
1. Kernel namespaces : Container menggunakan namespaces kernel untuk isolasi proses. Masing-masing Container memiliki tumpukan jaringan dan ruang nama yang berbeda, mencegah proses di satu Contaienr melihat atau memengaruhi Container lain atau sistem host.

2. Control Groups (cgroups): Cgroups mengimplementasikan akuntansi dan pembatasan sumber daya (resource) untuk menghindari satu Container menghambiskan semua resource dan mengganggu yang lain. Mereka penting untuk menjaga ketersediaan dan kinerja di platform.

3. Docker daemon attack surface: Daemon Docker membutuhkan akses root, dan hanya pengguna yang di percaya untuk mengontrolnya. Docker memungkinkan berbagi direktori antara host dan Container tanpa batasan, yang bisa dimanfaatkan oleh pengguna jahat jika tidak diawasi dengan baik.

4. Kernel Capabilities: Docker secara default memulai Container dengan seperangkat kemampuan yang terbatas, mengurangi resiko eksalasi ke hak istimewa. Ini berarti jika Container diretas menjadi root, kerusakan serius ke sistem atau eskalasi ke host lebih sulit dilakukan.

5. Docker Content Trust Signature Verification: Docker engine dapat dikonfigurasi hanya untuk menjalankan image yang di ditandatangani (terverifikasi). Fitur ini memungkinkan untuk menjalankan image yang dikenali dan memberikan penggunaan yang lebih aman.

6. Other kernel security features: Selain kemampuan kernel, Docker dapat  dikonfigurasi untuk memanfaatkan sistem keamaan lain seperti AppArmor, SELinux, atau GRSEC untuk meningkatkan keamanan host Docker.

Dengan menjaga dan mengelola aspek ini, keamanan Docker dapat ditingkatkan dan Container dapat dijalnkan secara aman dalam lingkungan produksi

### CIS Docker Benchmark
Center for Internet Security (CIS) menciptakan praktik terbaik keamanan cyber. CIS Benchmark untuk docker membantu organisasi memvalidasi konfigurasi Docker mereka. Ada alat open-source dan komersial yang memeriksa Docker anda terhadap rekomendasi CIS. Namun, perlu melampaui pemeriksaan CIS dan menerapkan praktik terbaik seperti menetapkan batasan resource dan memastikan image berjalan dalam mode read-only. Benchmark terbaru (CIS Docker Benchmark v1.4.0) mencakup konfigurasi host, daemon, file, image, runtime, operasi, dan konfigurasi swarm.

### Secret
Secret (rahasia) adalah data sensitif yang tidak boleh disimpan tidak terenkripsi atau ditransmisikan melalui jaringan. DOcker Swarm memungkikan penggunaan secret untuk menyimpan informasi sensitif seperti kata sandi dan kunci SSH, dengan memberikannya secara aman hanya kepada Container yang membutuhkannya. Docker mengelola rahasia dengan enkripsi selama transit dan saat istirahat, serta memberikan akses hanya kepada layanan yang diberi izin. Rahasia disimpan dalam log Raft yang dienkripsi dan di-mount ke dalam Container dalam sistem file memori. Anda dapat memperbarui atau mencabut akses secret kapan sja, tetapi tidak bisa menghapus secret yang digunakan oleh layanan yang sedang berjalan

## 11. Storage Driver
Tujuan yang akan dicapai:
> 1. Mengetahui berbagai jenis storage driver yang tersedia dalam Docker
> 2. Memahami bahwa pemilihan storage driver bergantung pada kebutuhan, ketersediaan kernel, dan distribusi Linux yang digunakan.
> 3. Memahami dukungan storage driver berdasarkan distribusi Linux yang digunakan, baik untuk Docker Engine - Community maupun Docker Desktop untuk Mac dan Windows.
> 4. Mengetahui cara memeriksa storage driver yang sedang digunakan menggunakan perintah docker info.
### Docker Storage Drivers
Docker memiliki beberapa storage driver yang berbeda, seperti overlay2, aufs, devicemapper, btrfs, zfs, dan vfs. Pemilihan driver tergantung pada kebutuhan dan ketersediaan kernel serta distribusi linux. Overlay2 adalah pilihan yang disarankan untuk kebanyakan distro Linux, sementara aufs digunakan untuk versi Docker yang lebih lama. Beberapa driver memerlukan konfigurasi tambahan atau sistem file tertentu. Pemilihan driver didasarkan pada kinerja, stabilitas dan kebutuhan khusus beban kerja. Selain itu, perlu mempertimbangkan kompatibilitas dengan sistem operasi dan distribusi yang digunakan.

### Supported Storage driver per Linux Distribution
Secara umum, pemilihan storage driver yang dapat Anda gunakan sebagian ditentukan oleh edisi Docker yang Anda gunakan.

Selain itu, Docker tidak merekomendasikan konfigurasi yang memerlukan Anda untuk menonaktifkan fitur keamanan dari sistem operasi Anda, seperti perlunya menonaktifkan selinux jika Anda menggunakan driver overlay atau overlay2 pada CentOS.

#### Docker Engine - Community
Untuk Docker Engine - Community, hanya beberapa konfigurasi yang diuji, dan kernel sistem operasi Anda mungkin tidak mendukung setiap storage driver. Secara umum, konfigurasi berikut berfungsi pada versi terbaru dari distribusi Linux:
![image](https://hackmd.io/_uploads/Hk7TlCBRa.png)

#### Docker Desktop for Mac and for Windows
Docker Desktop untuk Mac dan Docker Desktop untuk Windows ditujukan untuk pengembangan, bukan produksi. Modifikasi storage driver pada platform-platform ini tidak memungkinkan.

#### Supported backing filesystem
Terkait dengan Docker, backing filesystem adalah sistem file di mana `/var/lib/docker/` berada. Beberapa storage driver hanya berfungsi dengan backing filesystem tertentu.
![image](https://hackmd.io/_uploads/rJuMWRHRT.png)

#### Cek current storage driver
Untuk melihat storage driver yang sedang digunakan, gunakan docker info dan liat line Storage driver
```
$ docker info

Containers: 0
Images: 0
Storage Driver: overlay2
 Backing Filesystem: xfs
<...>
```

### Lab 11.1 Konfigurasi Storage Driver
sebelum memulai, jalankan `nusactl login` dan login akun Adinusa kalian.
```
student@pod-username-node01:~$ nusactl login
```
Setelah login, jalankan command  `nusactl start do-011-1` . Command ini akan menjalankan script dan *pre-configures* VM kalian.
```
student@pod-username-node01:~$ nusactl start do-011-1
```

#### Instruksi
**Jalankan di pod-[username]-node01**

#### Edit file daemon.json
```
sudo nano /etc/docker/daemon.json
...
{
  "storage-driver": "vfs"
}
...
```

#### Restart service docker.
```
sudo service docker restart
```

#### Cek docker info
```
docker info
```

#### Cek dengan docker pull
```
docker pull registry.adinusa.id/btacademy/ubuntu
```

#### Cek direktory docker
```
sudo ls -al /var/lib/docker/vfs/dir/
sudo du -sh /var/lib/docker/vfs/dir/
```

#### Verifikasi
* Pastikan storage-driver telah berubah sesuai dengan kondisi

#### Tugas
Jalankan command `nusactl grade do-011-1` untuk menampilkan nilai kalian.
```
nusactl grade do-011-1
```

Lalu jalankan command `nusactl finish do-011-1` untuk membersihkan konfigurasi.
```
nusactl finish do-011-1
```

## 12. Logging and Error Handling
Tujuan yang akan dicapai:
> 1. Memahami cara kerja perintah docker logs dalam menampilkan output dari container Docker.
> 2. Mengetahui langkah-langkah yang dapat dilakukan untuk memeriksa histori image, melihat perubahan filesystem dalam sebuah container, dan menampilkan log dari container Docker.

Secara default, docker logs menampilkan output perintah yang akan muncul jika perintah tersebut dijalnkan secara interaktif di terminal. Namun, dalam beberapa kasus, informasi yang ditampilkan mungkin tidak berguna, terutama jika Anda menggunakan logging driver eksternal atau jika image docker menjalankan proses non-interaktif seperti webserver atau databse. Dalam kasus ini, langkah tambahan diperlukan. Misalnya, image resmi nginx membuat tautan simbolis dari file log ke perangkat khsus untuk mengirimkan log ke STDOUT dan STDERR. Demikian pula, gambar resmi Apache httpd mengubah konfigurasi aplikasinya untuk menulis output STDOUT dan STDERR.
Contoh logs:
![image](https://hackmd.io/_uploads/r1m0zCr0a.png)

### Log Check
#### Cek History image
```
docker history registry.adinusa.id/btacademy/nginx:latest
```

#### Jalankan Nginx.
```
docker run -dit -p 80:80 --name nginx1 registry.adinusa.id/btacademy/nginx
```

#### Cek filestystem di nginx
```
docker diff nginx1
```

#### Cek log
```
docker logs --details nginx1
docker logs --timestamps nginx1
docker logs nginx1
```