---
Judul: ' DOCKER FUNDAMENTAL '
disqus: hackmd
---
{%hackmd @themes/dracula %}
# DOCKER FUNDAMENTAL REVIEW
# NETDEV 2024
Oleh Muhammad Alfian Alfarizi
# MODUL 1
##### KOMPONEN YANG DIBAHAS :
* [Container](/null)
* [Mengapa Kontainer penting?](/null)
* [Implementasi Container](/null)
* [Host, Virtual Machine, dan Kontainer](/null)
# Container
Dunia telah membawa kita kepada perkembangan teknologi di segala bidang. Teknologi dalam bidang pengembangan aplikasi merupakan salah satu teknologi yang membawa banyak perubahan seiring berjalannya waktu. Metodologi yang digunakan pun bermacam macam. Di masa lalu ketika pengembang akan mengembangkan aplikasi baru, setelah aplikasi tersebut selesai dikembangkan mereka akan menyerahkan aplikasi tersebut ke teknisi operasi, yang kemudian harus menginstalnya di server produksi dan menjalankannya.
**Problemnya** adalah ketika sebuah perusahaan yang terdapat banyak tim pengembang yang membuat jenis aplikasi yang sangat berbeda, namun semuanya harus dipasang di server produksi yang sama dan terus berjalan di sana.Menginstal versi baru dari aplikasi tertentu sekarang menjadi proyek yang rumit, dan sering kali membutuhkan perencanaan dan pengujian selama berbulan-bulan.
**Solusi pertama** yang diusulkan adalah dengan menggunakan mesin virtual (VM). Namun, vm ini dirasa cukup berat karena semuanya berisi sistem operasi lengkap dan semua itu hanya untuk satu aplikasi.
Solusi utama adalah bagaimana kita menyediakan sesuatu yang jauh lebih ringan daripada VM, tetapi juga mampu menampung dependency yang diperlukan. Pengembang menggunakan inovasi kontainer Docker untuk mengemas aplikasi, kerangka kerja, dan pustaka mereka ke dalamnya, dan kemudian mereka mengirimkan kontainer tersebut ke bagian pengujian. Secara garis besar kontainer docker ini adalah sebuah kontainer yang sudah distandarisasi. Dengan demikian, kontainer Docker adalah sarana untuk mengemas aplikasi dan ketergantungannya dengan cara yang terstandardisasi. Docker kemudian menciptakan frasa Bangun, kirim, dan jalankan di mana saja.
# Mengapa Container Penting?

* Developer mampu membuat, menguji, dan mengembangkan aplikasi secara terisolasi dalam sebuah environment
* Memudahkan developer dalam mengembangkan aplikasi dan konfigurasi pada level operating system
* Cenderung lebih hemat sumber daya dan environment yang stabil
* Cenderung lebih mudah dalam konfigurasi
* Mempersingkat pengembangan aplikasi karena docker mampu menjalankan banyak resources dengan waktu yang singkat
# Implementasi Container
Teknologi Container banyak diimplementasikan pada beberapa layanan, sebagai berikut :
## Docker

Docker adalah suatu platform layanan cloud berbasis container yang memiliki kemampuan menjalankan suatu aplikasi dalam lingkungan yang terisolasi. Docker digunakan untuk mengembangkan, mengirim, dan menjalankan aplikasi. Docker memungkinkan untuk memisahkan aplikasi dari infrastruktur sehingga Anda dapat mengirimkan perangkat lunak dengan cepat. Dengan Docker, Anda dapat mengelola infrastruktur dengan cara yang sama seperti mengelola aplikasi.
#### Deploy Aplikasi ada umumnya

#### Deploy Aplikasi menggunakan Docker

* Mengembangkan aplikasi dan komponen pendukungnya menggunakan kontainer.
* Kontainer memiliki peran untuk mendistribusikan dan menguji aplikasi.
* Penerapannya memiliki spesifikasi yang sama pada arsitektur penerapan aplikasi pada umumnya.
## Podman

Podman adalah sebuah platform yang berbasis container. Sederhananya podman merupakan alternatif platform yang memiliki kompatibilitas yang sama dengan docker. Simplenya apabila di docker kontainer yang berjalan dikelola oleh sebuah unsur yang bernama daemon. Namun, pada podman tidak ada unsur tersebut dan semua kontainer yang berjalan pada podman bisa berjalan tanpa adanya daemon. Jadi, terdapat istilah rootless pada podman karena tidak terdapat root access untuk daemon seperti pada docker sehingga user tanpa root access pun bisa menjalankan container.
## Linux Container/LXC

Linux Container adalah teknologi virtualisasi ringan yang dijalankan menggunakan sistem operasi linux dan dicapai menggunakan isolasi linux kernel yang memungkinkan seseorang untuk menjalankan container dalam host yang sama dan pada saat yang bersamaan
#### Arsitektur Linux Container

## LXD

LXD merupakan ekstensi manajemen dari kontainer yang sama dengan LXC yaitu menggunakan sistem operasi linux. LXD menyediakan fleksibilitas dan skalabilitas untuk berbagai kasus penggunaan, dengan dukungan untuk berbagai backend penyimpanan dan jenis jaringan serta opsi untuk menginstal pada perangkat keras mulai dari laptop individual atau instance cloud hingga rak server penuh.
# HOST, VM, KONTAINER
#### Perbedaan VM dan Arsitektur Baru (Docker)

#### Integrasi dengan Docker

Skema diatas menyajikan manfaat utama terbesar dari Docker, yaitu tidak perlu sistem operasi pada setiap aplikasi yang dijalankan. Karena hampir semua versi Linux menggunakan model kernel standar, Docker mengandalkan penggunaan kernel Linux sistem operasi host untuk sistem operasi yang dibangun di atasnya, seperti Red Hat, CentOS, dan Ubuntu. Karena alasan ini, kita dapat memiliki hampir semua sistem operasi Linux sebagai sistem operasi host
# LAB PREPARATION 1.1
## Konfigurasi Jaringan pada VM 1
**1. Set up Account**
```bash!
server login : student
password : Adinusa2023
```
**2. Konfigurasi dengan akun Adinusa**
```
student@servera:~$ nusactl login
(-) login to ADINUSA
Username : alfian5
Password : *******
(+) Succesfully Login
student@servera :~$
```
**3. Edit /etc/netplan/50-cloud-init.yaml**
```bash!
student@servera :~$ sudo nano /etc/netplan/50-cloud-init.yaml
```

**4. Gunakan command sudo netplan apply untuk menerapkan konfigurasi jaringan yang baru**
```bash!
student@servera :~$ sudo netplan apply
```

**4. Ubah nama hostname**
```bash!
student@servera :~$ sudo hostnamectl set-hostname pod-alfian5-node1
```
**5. Ubah nama hostname**
```bash!
student@servera :~$ sudo hostnamectl set-hostname pod-alfian5-node1
```
```bash!
student@servera :~$ sudo hostnamectl set-hostname pod-alfian6-node2
```
**6. Konfigurasikan host**
```bash!
student@servera :~$ sudo nano /etc/hosts
```


**7. Membuat SSH Keygen**
```bash!
student@pod-alfian5-node01 :~$ ssh-keygen -t rsa
```
**8. Menyalin public key ke semua nodes**
## VM 1
```bash!
student@pod-alfian5-node01 :~$ ssh-copy-id student@pod-alfian5-node01
student@pod-alfian5-node01 :~$ ssh-copy-id student@pod-alfian6-node02
```


## VM2
```bash!
student@pod-alfian6-node02:~$ ssh-copy-id student@pod-alfian5-node01
student@pod-alfian6-node02:~$ ssh-copy-id student@pod-alfian6-node02
```


**9. Recheck**
## VM 1
```bash!
student@pod-alfian5-node01:~$ ssh student@pod-alfian5-node01 "whoami; hostname"
student@pod-alfian5-node01:~$ ssh student@pod-alfian6-node02 "whoami; hostname"
```


## VM 2
```bash!
student@pod-alfian6-node02:~$ ssh student@pod-alfian5-node01 "whoami; hostname"
student@pod-alfian6-node02:~$ ssh student@pod-alfian6-node02 "whoami; hostname"
```


**10. Konfigurasi Nusactl melalui vm pada node01**
```bash!
student@pod-alfian5-node01:~$ vim /home/student/.nusactl/hosts.yaml
```

**11. Ekseskusi SSH**
```bash!
student@pod-alfian5-node01:~$ sudo apt install -y keychain && echo "eval $(keychain -q --eval id_rsa)" >> ~/.bashrc && source ~/.bashrc
```

**12. Ekseskusi Penilaian**
```bash!
student@pod-alfian5-node01:~$ nusactl grade do-001-1
```


# MODUL 2
##### KOMPONEN YANG DIBAHAS :
* [Docker](/null)
* [Produk Docker](/null)
* [Membership docker](/null)
# Docker

Docker, Inc. adalah perusahaan yang dibentuk untuk mengembangkan Docker CE dan Docker EE yang menyediakan layanan dukungan berbasis SLA untuk Docker EE. Pada akhirnya mereka menawarkan layanan konsultasi kepada perusahaan yang ingin mengambil aplikasi yang sudah ada dan mengkontainerisasikannya sebagai bagian dari program Modernisasi Aplikasi Tradisional menggunakan Docker.
# Produk Docker
Saat ini docker terbagi menjadi 2 versi yaitu Community Edition (CE), yang bersifat close source namun sepenuhnya gratis, dan ada Enterprise Edition (EE) yang juga close source dan perlu dilisensikan setiap tahun. Docker memberikan dukungan 24/7 untuk bug fixes.
### Berikut perbedaan Docker CE dan EE

# Membership Docker

# LAB 2.1 : Installing Docker
**1. Login**
```bash!
student@pod-alfian5-node01:~$ nusactl login
```
**2. Mengeksekusi Lab 2.1 dengan memulai command start (Sesuai perintah)**
```bash!
student@pod-alfian5-node01:~$ nusactl start do-002-1
```
**3. Memulai tahapan instalasi docker**
```bash!
student@pod-alfian5-node01:~$ sudo apt update
```
```bash!
student@pod-alfian5-node01:~$ sudo sudo apt-get install ca-certificates curl gnupg lsb-release -y
```
```bash!
student@pod-alfian5-node01:~$ sudo mkdir -m 0755 -p /etc/apt/keyrings
```
```bash!
student@pod-alfian5-node01:~$ 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
```
```bash!
student@pod-alfian5-node01:~$ sudo apt-get update
```
```bash!
student@pod-alfian5-node01:~$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
```
**4.Melihat versi docker**
```bash!
student@pod-alfian5-node01:~$ docker version
```

**5.Menambah user pada grup docker**
```bash!
student@pod-alfian5-node01:~$ groupadd docker
```
```bash!
student@pod-alfian5-node01:~$ sudo usermod -aG docker $USER
```
```bash!
student@pod-alfian5-node01:~$ sudo chmod 666 /var/run/docker.sock
```
**6.Tes Docker**
```bash!
student@pod-alfian5-node01:~$ docker run registry.adinusa.id/btacademy/hello-world
```

**7.Menampilkan Docker Image**
```bash!
student@pod-alfian5-node01:~$ docker image ls
```

**8.Menampilkan semua kontainer**
```bash!
student@pod-alfian5-node01:~$ docker container ls -a
```

**Penyelesaian LAB 2.1**

# LAB 2.2
**1.Mencari image redis dari dockerhub dan harbor**
```bash!
student@pod-alfian5-node01:~$ docker search redis
```

```bash!
student@pod-alfian5-node01:~$ skopeo list-tags docker://registry.adinusa.id/btacademy/redis
```

**2.Menjalankan image redis dari dockerhub**
```bash!
student@pod-alfian5-node01:~$ docker run registry.adinusa.id/btacademy/redis
```

```bash!
student@pod-alfian5-node01:~$ docker run -d registry.adinusa.id/btacademy/redis
```

```bash!
student@pod-alfian5-node01:~$ docker run -d --name redis1 registry.adinusa.id/btacademy/redis # Giving the container a name
```

**3.Menampilkan kontainer yang sedang berjalan**
```bash!
student@pod-alfian5-node01:~$ docker ps
```

```bash!
student@pod-alfian5-node01:~$ docker container ls
```

**4.Menampilkan semua kontainer docker**
```bash!
student@pod-alfian5-node01:~$ docker ps -a
```

```bash!
student@pod-alfian5-node01:~$ docker container ls -a
```

**5.Menampilkan deskripsi kontainer docker**
```bash!
student@pod-alfian5-node01:~$ docker inspect redis1
```
**6.Menampilkan konten logs pada kontainer**
```bash!
student@pod-alfian5-node01:~$ docker logs redis1
```

**7.Menampilkan running process pada kontainer**
```bash!
student@pod-alfian5-node01:~$ docker top redis1
```

**8.Mematikan kontainer**
```bash!
student@pod-alfian5-node01:~$ docker stop redis1
```
## Practice 02
**1.Mencari image redis dari dockerhub dan harbor**
```bash!
student@pod-alfian5-node01:~$ docker search nginx
```

```bash!
student@pod-alfian5-node01:~$ skopeo list-tags docker://registry.adinusa.id/btacademy/nginx
```

**2.Menjalankan image nginx dan di export kepada port host**
```bash!
student@pod-alfian5-node01:~$ docker run -d --name nginx1 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
```

**3.Menampilkan deskripsi nginx container**
```bash!
student@pod-alfian5-node01:~$ docker inspect nginx1
```
**4.Menjalankan nginx container dan deklarasikan port container**
```bash!
student@pod-alfian5-node01:~$ docker run -d --name nginx2 -p 80 registry.adinusa.id/btacademy/nginx:latest
```

**5.Test Browsing**
```bash!
student@pod-alfian5-node01:~$ curl localhost:$(docker port nginx2 80 | cut -d : -f 2)
```

**6.Menampilkan image docker**
```bash!
student@pod-alfian5-node01:~$ docker images
```
**Penyelesaian LAB 2.2**

# LAB 2.3
**1.Mencari image redis dari dockerhub dan harbor**
```bash!
student@pod-alfian5-node01:~$ docker search redis
```

```bash!
student@pod-alfian5-node01:~$ skopeo list-tags docker://registry.adinusa.id/btacademy/redis
```

**2.Menjalankan nginx dengan nama nginx1 dan menggunakan port 8080**
```bash!
student@pod-alfian5-node01:~$ docker run -d --name nginx1 -p 8080:80 registry.adinusa.id/btacademy/nginx:latest
```
**3.Menampilkan deskripsi kontainer nginx1**
```bash!
student@pod-alfian5-node01:~$ docker inspect nginx1
```
**4.Menjalankan nginx dengan nama nginx2 dengan port 8081**
```bash!
student@pod-alfian5-node01:~$ docker run -d --name nginx2 -p 8081:80 registry.adinusa.id/btacademy/nginx:latest
```
**5.Menampilkan container (aktifkan/keluar)**
```bash!
student@pod-alfian5-node01:~$ docker ps -a
```
```bash!
student@pod-alfian5-node01:~$ docker container ls -a
```
**6.Check nginx pada container**
```bash!
student@pod-alfian5-node01:~$ curl localhost:8080
```
```bash!
student@pod-alfian5-node01:~$ curl localhost:8081
```
**7.Akses Kontainer**
```bash!
student@pod-alfian5-node01:~$ docker exec -it nginx2 /bin/bash
```
**8.Update dan Install editor pada kontainer**
```bash!
student@pod-alfian5-node01:~$ apt-get update -y && apt-get install nano -y
```
**9.Edit index.html and move index.html ke default direktoriy nginx**
```bash!
student@pod-alfian5-node01:~$ nano index.html -> hello, alfian5.
```
**10.Restart Server pada nginx**
```bash!
student@pod-alfian5-node01:~$ service nginx restart
```
**11.Run ulang kontainer**
```bash!
student@pod-alfian5-node01:~$ docker start nginx2
```
**12.Tampilkan kontainer**
```bash!
student@pod-alfian5-node01:~$ docker ps
```
```bash!
student@pod-alfian5-node01:~$ docker container ls
```
**13.Cek output nginx pada kontainer**
```bash!
student@pod-alfian5-node01:~$ curl localhost:8080
```
```bash!
student@pod-alfian5-node01:~$ curl localhost:8081
```
**14.Menampilkan deskripsi pada kontainer**
```bash!
student@pod-alfian5-node01:~$ docker inspect nginx1
```
```bash!
student@pod-alfian5-node01:~$ docker inspect nginx2
```
**15.Menampilkan log konten pada kontainer**
```bash!
student@pod-alfian5-node01:~$ docker logs nginx1
```
```bash!
student@pod-alfian5-node01:~$ docker logs nginx2
```
**16.Menampilkan live resources pada kontainer**
```bash!
student@pod-alfian5-node01:~$ docker stats nginx1
```
```bash!
student@pod-alfian5-node01:~$ docker stats nginx2
```
**17.Menampilkan running process pada kontainer**
```bash!
student@pod-alfian5-node01:~$ docker top nginx1
```
```bash!
student@pod-alfian5-node01:~$ docker top nginx2
```
## Practice 04
**1.Mencari image redis dari dockerhub dan harbor**
```bash!
student@pod-alfian5-node01:~$ docker search redis
```

```bash!
student@pod-alfian5-node01:~$ skopeo list-tags docker://registry.adinusa.id/btacademy/redis
```
**2.Tarik gambar ubuntu**
```bash!
student@pod-alfian5-node01:~$ docker pull registry.adinusa.id/btacademy/ubuntu
```

**3.Menjalankan kontainer ubuntu dan akses ke konsol**
```bash!
student@pod-alfian5-node01:~$ docker run -it --name ubuntu1 registry.adinusa.id/btacademy/ubuntu
```

**4.Jalankan kontainer ubuntu dan hapus saat keluar dari kontainer**
```bash!
student@pod-alfian5-node01:~$ docker run -it --rm --name ubuntu2 registry.adinusa.id/btacademy/ubuntu
```
**Penyelesaian Lab 2.3**

# LAB 2.4
**1.Menjalankan kontainer mysql dengan parameter tambahan**
```bash!
student@pod-alfian5-node01:~$ docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD=RAHASIA -e MYSQL_DATABASE=latihan05 -p 3306:3306 \
registry.adinusa.id/btacademy/mysql
```
**2.Menjalankan kontainer mysql dengan parameter tambahan**
```bash!
student@pod-alfian5-node01:~$ docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD=RAHASIA -e MYSQL_DATABASE=latihan05 -p 3306:3306 \
registry.adinusa.id/btacademy/mysql
```
**3.Tarik gambar phpmyadmin dari harbor**
```bash!
student@pod-alfian5-node01:~$ docker pull registry.adinusa.id/btacademy/phpmyadmin:latest
```
**4.Jalankan kontainer phpmyadmin dan hubungkan dengan kontainer mysql**
```bash!
student@pod-alfian5-node01:~$ docker run --name my-phpmyadmin -d --link my-mysql:db -p 8090:80 \ registry.adinusa.id/btacademy/phpmyadmin
```
**4.Test Browsing**
```bash!
open in browser http://10.10.10.11:8090 login with user: `root` dan password: `RAHASIA`
```
## Practice 06
**1.Jalankan kontainer ubuntu dengan nama ubuntu1 & ubuntu2**
```bash!
student@pod-alfian5-node01:~$ docker run -dit --name ubuntu1 registry.adinusa.id/btacademy/ubuntu
```
```bash!
student@pod-alfian5-node01:~$ docker run -dit --name ubuntu2 registry.adinusa.id/btacademy/ubuntu
```
**2.Tampilkan list container**
```bash!
student@pod-alfian5-node01:~$ docker ps
```
**3.Hentikan sementara container ubuntu**
```bash!
student@pod-alfian5-node01:~$ docker pause ubuntu1
```
```bash!
student@pod-alfian5-node01:~$ docker pause ubuntu2
```
**4.Periksa daftar kontainer saat status kontainer dijeda**
```bash!
student@pod-alfian5-node01:~$ docker ps
```
**5.Periksa penggunaan sumber daya saat kontainer ubuntu dijeda**
```bash!
student@pod-alfian5-node01:~$ docker stats ubuntu1
```
```bash!
student@pod-alfian5-node01:~$ docker stats ubuntu2
```
**6.Jalankan lagi ubuntu1**
```bash!
student@pod-alfian5-node01:~$ docker unpause ubuntu1
```
## Practice 07
**1.Membuat database dengan spesifikasi tertentu**
```bash!
student@pod-alfian5-node01:~$ 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
```
**2.Buat wordpress dan hubungkan ke database**
```bash!
student@pod-alfian5-node01:~$ 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
```
**3.Check logs, proses, dan resource.**
```bash!
docker logs ch6_mariadb
docker logs ch6_wordpress
docker top ch6_mariadb
docker top ch6_wordpress
docker stats ch6_mariadb
docker stats ch6_wordpress
```
**3.Test browsing**
```bash!
Open in browser http://10.10.10.11 then complete the installation
```

# Penyelesaian Lab 2.4

# MODUL 3
##### KOMPONEN YANG DIBAHAS :
* [Pengelolaan Siklus Kontainer](/null)
* [Public Registry & Private Registry](/null)
* [Docker Volume](/null)
* [Docker Network](/null)
# LAB 3.1
**1.Buat direktori baru**
```bash!
student@pod-alfian5-node01:~$ mkdir -p latihan/latihan01-volume
```
**2.Masuk ke direktori tersebut**
```bash!
student@pod-alfian5-node01:~$ cd latihan/latihan01-volume
```
**3.Buat file container untuk data volume dengan nama my-volume**
```bash!
student@pod-alfian5-node01:~$ for i in {1..10};do touch file-$i;done
```

```bash!
student@pod-alfian5-node01:~$ sudo docker create -v /my-volume --name my-volume registry.adinusa.id/btacademy/busybox
```

```bash!
student@pod-alfian5-node01:~$ sudo docker cp . my-volume:/my-volume
```

**4.Ambil volume untuk dipindah ke kontainer**
```bash!
student@pod-alfian5-node01:~$ docker run --volumes-from my-volume registry.adinusa.id/btacademy/ubuntu ls /my-volume
```

**Penyelesaian LAB 3.1**

# LAB 3.2
**1.Buat direktori kerja baru**
```bash!
student@pod-alfian5-node01:~$ sudo mkdir -p /data/nfs-storage01/
```
**2.Membuat server NFS dengan docker**
```bash!
student@pod-alfian5-node01:~$ 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
```

**Jalankan pada node02**
**1. Instal paket yang diperlukan, pasang volume pada klien NFS, lalu buat file untuk memeriksa volume**
```bash!
student@pod-alfian5-node02:~$ ssh 10.7.7.20
```

```bash!
student@pod-alfian5-node02:~$ sudo apt install nfs-client -y
```
```bash!
student@pod-alfian5-node02:~$ sudo mount -v -o vers=4,loud 10.7.7.10:/ /mnt
```

```bash!
student@pod-alfian5-node02:~$ df -h
```

```bash!
student@pod-alfian5-node02:~$ sudo touch /mnt/file1.txt
```

```bash!
student@pod-alfian5-node02:~$ sudo touch /mnt/file2.txt
```

```bash!
student@pod-alfian5-node02:~$ exit
```
**2.Verifikasi**
```bash!
student@pod-alfian5-node01:~$ ls /data/nfs-storage01/
```
**Penyelesaian LAB 3.2**

# LAB 3.3
**1.Buat Docker Volume**
```bash!
student@pod-alfian5-node01:~$ docker volume create my-vol
```

**2.Menampilkan list Docker Volume**
```bash!
student@pod-alfian5-node01:~$ docker volume ls
```

**3.Menampilkan detail Docker Volume**
```bash!
student@pod-alfian5-node01:~$ docker volume inspect my-vol
```

**4.Menjalankan kontainer dengan akses baca dan tulis volume.**
```bash!
student@pod-alfian5-node01:~$ docker run -d --name=nginx-rwvol -v my-vol:/usr/share/nginx/html -p 4005:80 registry.adinusa.id/btacademy/nginx:latest
```

**5.Menampilkan IP Address dari container.**
```bash!
student@pod-alfian5-node01:~$ docker inspect nginx-rwvol | jq -r '.[].NetworkSettings.IPAddress'
```

**6.Test browsing IP Address**
```bash!
student@pod-alfian5-node01:~$ curl http://172.17.0.2
```

**7.Buat file index.html dan pindahkan ke direktori volume sumber.**
```bash!
student@pod-alfian5-node01:~$ sudo echo "This is from my-vol source directory" > index.html
```
```bash!
student@pod-alfian5-node01:~$ sudo mv index.html /var/lib/docker/volumes/my-vol/_data
```
**8. Test browsing IP Address**
```bash!
student@pod-alfian5-node01:~$ curl http://172.17.0.2
```
**9.Menjalankan kontainer dengan akses baca volume.**
```bash!
student@pod-alfian5-node01:~$ docker run -d --name=nginx-rovol -v my-vol:/usr/share/nginx/html:ro registry.adinusa.id/btacademy/nginx:latest
```

**10.Lihat detail kontainer nginx-rovol**
```bash!
student@pod-alfian5-node01:~$ docker inspect nginx-rovol | jq '.[].Mounts'
```

**Penyelesaian LAB 3.3**

# LAB 3.4
**Dijalankan pada node02**
**1.Membuat direktori /share and Create index.html**
```bash!
student@pod-alfian5-node02:~$ sudo mkdir /share
```
```bash!
student@pod-alfian5-node02:~$ sudo chmod 777 /share
```
```bash!
student@pod-alfian5-node02:~$ echo "Hello Adinusa!" > /share/index.html
```

**2.Lakukan Instalasi plugin sshfs and set plugin sshfs**
```bash!
student@pod-alfian5-node02:~$ docker plugin install --grant-all-permissions vieux/sshfs
```

```bash!
student@pod-alfian5-node02:~$ docker plugin ls
```

```bash!
student@pod-alfian5-node02:~$ docker plugin disable [PLUGIN ID]
```

```bash!
student@pod-alfian5-node02:~$ docker plugin set vieux/sshfs sshkey.source=/home/student/.ssh/
```

```bash!
student@pod-alfian5-node02:~$ docker plugin enable [PLUGIN ID]
```

```bash!
student@pod-alfian5-node02:~$ docker plugin ls
```

**3.Membuat docker volume dengan driver ssfhs**
```bash!
student@pod-alfian5-node02:~$ docker volume create --driver vieux/sshfs -o sshcmd=student@10.7.7.20:/share -o allow_other sshvolume
```

**4.Jalankan container dengan volume terkait**
```bash!
student@pod-alfian5-node02:~$ docker run -d --name=nginxtest-sshfs -p 8090:80 -v sshvolume:/usr/share/nginx/html registry.adinusa.id/btacademy/nginx:latest
```
**5.Test Browsing**
```bash!
student@pod-alfian5-node02:~$ docker ps
```
```bash!
student@pod-alfian5-node02:~$ curl localhost:8090
```
**Penyelesaian Lab 3.4**

# LAB 3.5
**Dijalankan pada node01**
**1.Menampilkan daftar jaringan pada jaringan docker saat ini**
```bash!
student@pod-alfian5-node01:~$ sudo docker network ls
```

**2.Jalankan alpine container ash shell**
```bash!
student@pod-alfian5-node01:~$ docker run -dit --name alpine1 registry.adinusa.id/btacademy/alpine ash
```

```bash!
student@pod-alfian5-node01:~$ docker run -dit --name alpine2 registry.adinusa.id/btacademy/alpine ash
```

```bash!
student@pod-alfian5-node01:~$ docker container ls
```

**3.Buat jaringan baru pada docker dan arahkan ke container alphine1**
```bash!
student@pod-alfian5-node01:~$ docker network create --driver bridge bridge1
```

```bash!
student@pod-alfian5-node01:~$ docker network connect bridge1 alpine1
```

**4.Cek IP container alphine2**
```bash!
student@pod-alfian5-node01:~$ docker inspect alpine2 | jq -r '.[].NetworkSettings.IPAddress'
```

**5.Akses alphine1 container**
```bash!
student@pod-alfian5-node01:~$ docker exec -it alpine1 sh
```

**6.Tampilkan IP alphine1 container**
```bash!
student@pod-alfian5-node01:~$ ip add
```

**7.Tes PING pada alphine1 container**
```bash!
student@pod-alfian5-node01:~$ ping -c 3 8.8.8.8
```

**8.Tes PING untuk alphine2 container**
```bash!
student@pod-alfian5-node01:~$ ping -c 3 172.17.0.3
```

**9.Tes PING nama untuk alphine2 container (Gagal)**
```bash!
student@pod-alfian5-node01:~$ ping -c 3 alpine2
```
**10.Keluar dari container**
```bash!
student@pod-alfian5-node01:~$ ping -c 3 alpine2
```
**Penyelesaian LAB 3.5**

# LAB 3.6
**Dijalankan pada node01**
**1.Jalankan container dengan image nginx dan dengan network host**
```bash!
student@pod-alfian5-node01:~$ docker run -itd --network host --name my_nginx registry.adinusa.id/btacademy/nginx
```

**2.Test Browsing ke Localhost**
```bash!
student@pod-alfian5-node01:~$ curl http://localhost
```

**3.Buat jaringan baru pada docker dan arahkan ke container alphine1**
```bash!
student@pod-alfian5-node01:~$ ip add
```
```bash!
student@pod-alfian5-node01:~$ sudo netstat -tulpn | grep :80
```

**Penyelesaian LAB 3.6**

# MODUL 4
##### KOMPONEN YANG DIBAHAS :
* [Docker Images](/null)
* [Docker Registry](/null)
* [Memanipulasi Image pada Container](/null)
* [Membangun container khusus dengan Dockerfile](/null)
* [Meninjau secara mendalam tentang Dockerfile](/null)
# Docker Images
Di Linux, semuanya merupakan file. Seluruh sistem operasi pada dasarnya adalah sistem berkas dengan berkas dan folder yang disimpan pada local disk. Ini adalah fakta penting yang perlu diingat ketika melihat apa itu image container. Seperti yang akan kita lihat, image pada dasarnya adalah unsur besar yang berisi sistem berkas. Lebih khusus lagi, image berisi sistem berkas berlapis.
**Layer Images**

Gambar sebagai tumpukan lapisan Setiap lapisan individual berisi file dan folder. Setiap lapisan hanya berisi perubahan pada sistem berkas sehubungan dengan lapisan di bawahnya. Driver penyimpanan menangani detail mengenai bagaimana lapisan ini berinteraksi satu sama lain. Lapisan-lapisan gambar kontainer semuanya tidak dapat diubah. Tidak dapat diubah berarti bahwa setelah dibuat, lapisan tidak dapat diubah. Satu-satunya operasi yang merubah suatu lapisan adalah penghapusan fisiknya.
Pada tangkapan layar berikut ini, kita dapat melihat seperti apa custom images untuk aplikasi web

Contoh citra kustom berdasarkan Alpine dan Nginx
Lapisan dasar kita di sini terdiri dari distribusi Linux Alpine. Kemudian, di atasnya, terdapat lapisan Nginx. Terakhir, lapisan ketiga berisi semua berkas yang membentuk aplikasi web, seperti berkas HTML, CSS, dan JavaScript.
Docker Hub adalah open registry untuk kontainer. Setiap lapisan hanya berisi data perubahan yang memiliki korelasi dengan lapisan sebelumnya. Konten setiap lapisan dipetakan ke folder khusus pada sistem host, yang biasanya berupa subfolder dari /var/lib/docker/.
**Writable Content Layer**


Dalam docker dapat menjalankan banyak container dengan layer images yang sama. Teknik ini, tentu saja, menghasilkan pengurangan sumber daya yang luar biasa dalam sumber daya yang dikonsumsi, hal ini juga dapat membantu mengurangi waktu pemuatan container, karena hanya lapisan container tipis yang harus dibuat setelah lapisan gambar dimuat ke dalam memori, yang hanya terjadi pada container pertama.
# Docker Registry
Docker Registry adalah aplikasi open source yang dapat Anda jalankan di mana pun Anda inginkan dan menyimpan Docker. Secara general Docker registry merupakan alternatif fitur dari Docker Hub

Ada beberapa fitur Docker Registry yaitu :
-Mengelola registri Anda sendiri, dan terdapat semua layanan repositori sebagai privat, publik, atau gabungan di antara keduanya
-Skalabilitas registri sesuai kebutuhan, berdasarkan berapa banyak dijadikan host atau berapa banyak permintaan dapat dilayani
-Based on command line
# Docker Hub
Docker Hub adalah salah satu platform yang memudahkan kita membuat, mengelola, dan mengirimkan aplikasi kontainer tim Anda.Repositori Docker Hub memungkinkan kita berbagi kontainer dengan tim, pelanggan, atau komunitas Docker secara luas.
Dengan Docker Hub kita bisa melakukan :
-Mendapatkan antarmuka berbasis GUI yang dapat digunakan untuk mengelola docker.
-Memiliki lokasi yang sudah disiapkan pada cloud yang siap menangani layanan publik dan/atau pribadi.
# Memanipulasi Image pada kontainer
Ada berbagai cara untuk mengelola image container secara devops. Dalam hal ini terdapat 2 contoh cara untuk melakukan hal ini:
1. Menyimpan citra kontainer ke file *.tar.
2. Menerbitkan (push) kontainer ke registri
# Membangun kontainer khusus dengan docker file
Dockerfile adalah berkas teks yang berisi serangkaian instruksi yang ditentukan pengguna. Dockerfile digunakan untuk merakit/membangun kontainer.
**Alphine Linux**
Alpine Linux adalah unsur distribusi Linux non-komersial yang dikembangkan secara independen dan kecil yang dirancang untuk keamanan, efisiensi, dan kemudahan penggunaan. Meskipun kecil (lihat bagian berikut), ia menawarkan fondasi yang kuat untuk image kontainer karena repositori paketnya yang luas, dan juga berkat port tidak resmi grsecurity/PaX, yang ditambal ke dalam kernelnya, ia menawarkan perlindungan proaktif terhadap lusinan potensi serangan zero-day dan kerentanan lainnya.
Alpine Linux, karena ukurannya, dan juga kekuatannya, telah menjadi basis citra default untuk citra kontainer resmi yang disediakan oleh Docker. Karena itu, kita akan menggunakannya di sepanjang buku ini. Untuk memberikan gambaran kepada Anda betapa kecilnya image resmi untuk Alpine Linux, mari kita bandingkan dengan beberapa distribusi lain yang tersedia pada saat buku ini ditulis:

Seperti yang dapat Anda lihat dari keluaran Terminal, Alpine Linux hanya berukuran 4,41 MB, berbeda dengan image terbesar, yaitu Fedora, yang berukuran 253 MB. Instalasi bare-metal dari Alpine Linux berukuran sekitar 130 MB, yang masih hampir setengah dari ukuran image container Fedora.
# Meninjau secara mendalam tentang Dockerfile
# LAB 4.1
**Jalankan pada node01**
**Practice01**
**1.Clone Repository**
```bash!
student@pod-alfian5-node01:~$ git clone https://github.com/spkane/docker-node-hello.git \
--config core.autocrlf=input latihan01
```

**2.Masuk ke repository**
```bash!
student@pod-alfian5-node01:~$ cd latihan01
```

**3.Buat image repositori sebelumnya dan beri nama node-latihan01**
```bash!
student@pod-alfian5-node01:~$ docker build -t node-latihan01 .
```

**4.Jalankan kontainer dengan image yang telah dibuat sebelumnya dan buka port ke 8080**
```bash!
student@pod-alfian5-node01:~$ docker run -d --rm --name node-latihan01 -p 8080:8080 node-latihan01
```

**5.Coba akses kontainer**
```bash!
student@pod-alfian5-node01:~$ curl localhost:8080
```

**Practice02**
**1.Buat direktory latihan02**
```bash!
student@pod-alfian5-node01:~$ cd $HOME
```
```bash!
student@pod-alfian5-node01:~$ mkdir latihan02
```
```bash!
student@pod-alfian5-node01:~$ cd latihan02
```
**2.Buat Dockerfile**
```bash!
student@pod-alfian5-node01:~$ 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
```
**3.Buat image dari Dockerfile**
```bash!
student@pod-alfian5-node01:~$ docker build -t docker-whale .
```
**4.Tampilkan image yang sudah dibuat**
```bash!
student@pod-alfian5-node01:~$ docker image ls
```
**5.Jalankan image yang sudah dibuat**
```bash!
student@pod-alfian5-node01:~$ docker run docker-whale
```
**6.Tampilkan kontainer**
```bash!
student@pod-alfian5-node01:~$ docker ps
```

```bash!
student@pod-alfian5-node01:~$ docker ps
```

**Penyelesaian Lab 4.1

# LAB 4.2
**1.Login dengan Docker**
```bash!
student@pod-alfian5-node01:~$ docker login
```

**2.Buat direktori latihan03**
```bash!
student@pod-alfian5-node01:~$ cd $HOME
```
```bash!
student@pod-alfian5-node01:~$ mkdir latihan03
```
```bash!
student@pod-alfian5-node01:~$ cd latihan03
```

**2.Buat flask file**
```bash!
student@pod-alfian5-node01:~$ vim app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hey, we have Flask in a Docker container!'
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
```
**3.Buat file requirements.txt**
```bash!
student@pod-alfian5-node01:~$ vi requirements.txt
Flask==0.10.1
Werkzeug==1.0.0
Jinja2==2.8.1
MarkupSafe==1.1.1
itsdangerous==1.1.0
```
**4.Buat Dockerfile**
```bash!
student@pod-alfian5-node01:~$ vim Dockerfile
FROM registry.adinusa.id/btacademy/ubuntu:16.04
RUN mkdir /app
RUN apt-get update -y && \
apt-get install python-pip python-dev -y
COPY ./requirements.txt /app
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]
```
**4.Buat image dari Dockerfile**
```bash!
student@pod-alfian5-node01:~$ docker build -t flask-latihan03 .
```

**5.Tandai gambar dengan nama pengguna docker.**
```bash!
student@pod-alfian5-node01:~$ docker tag flask-latihan03 [usernamedocker]/flask-latihan03:latest
```

**6.Arahkan gambar ke dockerhub**
```bash!
student@pod-alfian5-node01:~$ docker push [usernamedocker]/flask-latihan03:latest
```

**7.Jalankan image**
```bash!
student@pod-alfian5-node01:~$ docker run -d -p 5000:5000 --name flask03 [usernamedocker]/flask-latihan03
```

**7.Test Browsing**
```bash!
student@pod-alfian5-node01:~$ curl localhost:5000
```
**Penyelesaian LAB 4.2**

# MODUL 5
##### KOMPONEN YANG DIBAHAS :
* [Pengenalan Docker Compose](/null)
* [Menjalankan Multi Service App](/null)
* [Membuat images dengan docker compose](/null)
* [Menjalankan aplikasi dengan docker compose](/null)
* [Skalabilitas Layanan](/null)
### Pengenalan Docker Compose

Docker Compose adalah alat yang disediakan oleh Docker yang terutama digunakan saat Anda perlu menjalankan dan mengatur kontainer yang berjalan pada satu host Docker. Docker Compose menggunakan berkas yang diformat dalam YAML sebagai masukan. Isi dari docker-compose.yml dikatakan sebagai cara deklaratif untuk mendeskripsikan dan menjalankan aplikasi yang terkontainerisasi yang berpotensi terdiri dari lebih dari satu kontainer.
### Menjalankan Multi Service App
Dalam banyak kasus, aplikasi tidak hanya terdiri dari satu blok monolitik, melainkan beberapa layanan aplikasi yang bekerja bersama. Saat menggunakan kontainer Docker, setiap layanan aplikasi berjalan di dalam kontainernya sendiri. Ketika kita ingin menjalankan aplikasi multi-layanan seperti itu, tentu saja semua dapat memulai kontainer yang berpartisipasi dengan perintah run kontainer docker yang terkenal, dan kita telah melakukan ini di bab-bab sebelumnya. Namun, cara ini sangat tidak efisien. Dengan alat bantu Docker Compose, kita diberi cara untuk mendefinisikan aplikasi secara deklaratif dalam berkas yang menggunakan format YAML.
# LAB 5.1
**Eksekusi pada Node01 dan Node02**
**Download dan Install compose**
```bash!
student@pod-alfian5-node01:~$ 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
```

**Lihat Versi Compose (tes)**
```bash!
student@pod-alfian5-node01:~$ docker-compose --version
```

**Buat direktori wordpress dan masuk ke direktorinya**
```bash!
student@pod-alfian5-node01:~$ cd $HOME
```
```bash!
student@pod-alfian5-node01:~$mkdir -p latihan/my_wordpress
```
```bash!
student@pod-alfian5-node01:~$cd latihan/my_wordpress
```

**Buat docker compose file**
```bash!
student@pod-alfian5-node01:~$ vim docker-compose.yml
```
```bash!
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:
```
**Jalankan Compose**
```bash!
student@pod-alfian5-node01:~$ docker-compose up -d
```

**Tampilkan list container**
```bash!
student@pod-alfian5-node01:~$ docker container ls
```

**Penyelesaian LAB 5.1**

# MODUL 6
##### KOMPONEN YANG DIBAHAS :
* [CI menggunakan Docker](/null)
* [Docker Hub Automated Build](/null)
### Integrasi Docker dengan Continous Integration (CI)
Continuous Integration (CI) adalah pengembangan yang mengharuskan pengembang mengintegrasikan kode ke dalam repositori bersama beberapa kali dalam sehari. Setiap check-in kemudian diverifikasi oleh build otomatis. CI tidak menghilangkan bug, tetapi membuatnya lebih mudah ditemukan dan dihapus. CI/CD menggabungkan pengembangan dengan pengujian, memungkinkan pengembang untuk membangun suatu kode secara kolaboratif, mengirimkannya ke cabang, dan memeriksa masalah. Hal ini memungkinkan pengembang untuk tidak hanya membangun kode mereka, tetapi juga menguji kode mereka di semua jenis lingkungan dan sesering mungkin untuk menangkap bug di awal siklus pengembangan aplikasi. Karena Docker dapat berintegrasi dengan alat bantu seperti Jenkins dan GitHub, pengembang dapat mengirimkan kode di GitHub, menguji kode, dan secara otomatis memicu pembangunan menggunakan Jenkins, dan setelah citra selesai, citra dapat ditambahkan ke registri Docker. Hal ini menyederhanakan proses, menghemat waktu dalam proses pembangunan dan penyiapan, sekaligus memungkinkan pengembang menjalankan pengujian secara paralel dan mengotomatiskannya sehingga mereka dapat terus bekerja pada proyek lain saat pengujian dijalankan.

### Docker Hub Automated Build
Docker Hub dapat secara otomatis membangun image dari kode sumber di repositori eksternal dan secara otomatis mendorong image yang telah dibangun ke repositori Docker Anda.
# MODUL 7
##### KOMPONEN YANG DIBAHAS :
* [Docker Swam](/null)
* [Portainer untuk Docker](/null)
### Docker Swarm
Swarm adalah sebuah klaster yang terdiri atas satu atau lebih komputer yang menjalankan Docker. Swarm dapat terdiri atas satu mesin atau lebih, sehingga Anda dapat menggunakan fungsionalitas swarm pada mesin lokal Anda.
Dengan diperkenalkannya mode swarm, Docker menerima kemampuan orkestrasi, pengelompokan, dan penjadwalan bawaan. Fitur untuk menangani banyak mesin, seperti pemeriksaan kesehatan, penyeimbangan beban, dan banyak hal bagus lainnya sekarang disertakan secara out-of-the-box.
Dua layanan yang sebelumnya merupakan tambahan eksternal, yang bekerja di atas mesin Docker telah disertakan secara native - Swarm dan Docker Compose. Namun, keduanya tidak hanya dikemas dengan itu.
Tidak seperti Swarm mandiri yang lama, fungsionalitasnya sekarang dibangun ke dalam mesin Docker itu sendiri. Itu adalah layanan terpisah, bukan bagian dari daemon docker dan berinteraksi dengan API Docker (seperti yang masih dilakukan oleh Kubernetes dan kawan-kawan. Anda dapat membaca lebih lanjut tentang konsep ini di sini dan memulai dengan tutorial ini Dengan mengaktifkan mode swarm dan berkas docker-compose.yml yang ditulis menurut spesifikasi versi 3, Anda dapat mengeluarkan perintah docker stack yang memunculkan tumpukan layanan.
Ketika Anda menjalankan kontainer dengan perintah Docker, mode swarm tidak digunakan secara default. Jika Anda menggunakan mode swarm, Anda berurusan dengan tingkat abstraksi yang lebih tinggi - layanan, bukan kontainer. Anda dapat menangani kedua jenis ini pada mesin yang sama.
Saat kontainer berjalan dalam mode layanan, mode swarm mengambil alih dan mengelola siklus hidup layanan. Mode ini berusaha memunculkan sejumlah replika yang diinginkan, seperti yang ditentukan dalam definisi. Bagian dari fungsi tersebut sangat mirip dengan Kubernetes.
### Portainer untuk Docker
Portainer adalah alat manajemen kontainer universal yang dapat bekerja dengan Docker dan Kubernetes untuk membuat penyebaran dan pengelolaan aplikasi dan layanan dalam kontainer menjadi lebih mudah dan efisien. Portainer memiliki lebih dari 650.000 pengguna dan 21.700 bintang GitHub, sehingga banyak digunakan dan populer.
Portainer adalah UI manajemen yang ringan yang memungkinkan Anda untuk dengan mudah mengelola lingkungan Docker Anda yang berbeda (host Docker atau cluster Swarm). Portainer dimaksudkan agar mudah diterapkan dan digunakan. Portainer terdiri dari satu kontainer yang dapat berjalan pada mesin Docker apa pun (dapat digunakan sebagai kontainer Linux atau kontainer asli Windows, juga mendukung platform lain). Portainer memungkinkan Anda untuk mengelola semua sumber daya Docker Anda (kontainer, image, volume, jaringan, dan lainnya)! Ini kompatibel dengan mesin Docker mandiri dan dengan mode Docker Swarm.
Selama setahun terakhir, Portainer telah menjadi alat andalan saya untuk mengelola penyebaran kontainer. Salah satu alasan utamanya adalah karena Portainer benar-benar membuat bekerja dengan kontainer menjadi mudah dipahami. Bagi saya, hal itu menjadikannya platform manajemen yang jelas bagi admin dan pengembang dari semua tingkat keahlian.
# LAB 7.1
**Eksekusi di node01**
**Inisialisasi Docker Swam**
```bash!
student@pod-alfian5-node01:~$ docker swarm init --advertise-addr 10.7.7.10
```

**Eksekusi di node02**
```bash!
student@pod-alfian5-node02:~$ docker swarm join --token [TOKEN] 10.7.7.10:2377
```
**Eksekusi di node01**
```bash!
student@pod-alfian5-node01:~$ docker node ls
```

**Penyelesaian LAB 7.1**

# LAB 7.2
**Eksekusi pada node01**
**Buat service nginx dengan 2 replika dan arahkan pada port 80**
```bash!
student@pod-alfian5-node01:~$ docker service create --name web --replicas 2 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
```

**Check apakah service sudah berjalan**
```bash!
student@pod-alfian5-node01:~$ docker service ls
```
**Test Browsing dari Node01 ke Node02**
```bash!
student@pod-alfian5-node01:~$ curl http://10.7.7.10
```
```bash!
student@pod-alfian5-node01:~$ curl http://10.7.7.20
```

**Cek informasi tentang service**
```bash!
student@pod-alfian5-node01:~$ docker service inspect --pretty web
```

**Cek dimana letak service berjalan**
```bash!
student@pod-alfian5-node01:~$ docker service ps web
```

**Buat kontainer dengan limit cpu dan memory**
```bash!
student@pod-alfian5-node01:~$ 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 kontainer**
```bash!
student@pod-alfian5-node01:~$ docker service inspect --pretty [username]
```

**Penyelesaian LAB 7.2

# LAB 7.3
**Eksekusi pada node01**
**Buat service nginx dengan 3 replika**
```bash!
student@pod-alfian5-node01:~$ docker service create --name web2 --replicas 3 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
```

**Merubah service dari replika**
```bash!
student@pod-alfian5-node01:~$ docker service scale web2=1
```

**Cek jika replika sudah diubah**
```bash!
student@pod-alfian5-node01:~$ docker service ls
```

```bash!
student@pod-alfian5-node01:~$ docker service ps web2
```

**Docker swarm dapat memperbarui layanan secara bertahap**
```bash!
student@pod-alfian5-node01:~$ docker service update --image sistyo/myweb web2
```

```bash!
student@pod-alfian5-node01:~$ docker service inspect --pretty web2
```
**Penyelesaian Lab 7.3**

# LAB 7.4
**Eksekusi pada node01**
**Install Portainer pada node01**
```bash!
student@pod-alfian5-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 portainer dashboard**

**Hubungkan Portainer Agent Node02 ke Portainer Dashboard (node01)**
- Click menu Environments -> Add environmets
- Select Docker Swarm -> Start Wizard
- Select Agent -> Copy command to run in node01



**Kembali portainer Dashboard**
- Isi kolom NAME dengan pod-username-node02
- Isi Environment URL dengan ip address node02 10.7.7.20:9001
- Klik Connect
**Penyelesaian Lab 7.4**

# LAB 7.5
**Akses Portainer Dashboard**
```bash!
http://10.10.10.11:9000
```

**Jalankan Container**
- Pilih Home -> node02
- Klik Containers -> + Add Container
- Isi kolom nama dengan [username]-web
- Isi kolom image dengan nginx:latest
- Klik Publish a new network port -> Isi kolom host dengan 8080 dan kolom container dengan 80
- Node pod-username-node02
- Klik Deploy the Container




**Akses Container**
```bash!
http://10.10.10.12:8080
```

**Penyelesaian Lab 7.5**

# LAB 7.6
**Buat Image dari Dockerfile**
- Cick Menu Image -> + Build a new Image
- Fill name coloumn with {username adinusa}/nginx:lab76
- Select build method to Web Editor
- Create Dockerfile
- Deployment to pod-username-node01
- Click Build the image -> see the output
- Check the image in menu Images
**Mengarahkan Image ke Docker Hub**
- Click menu Registries -> Add registry
- In menu registry provider -> Select DockerHub
- Name: repo-{username adinusa}
- Username: {username docker}
- Password: {password docker}
- Click Add Registry
- Back to Images, Open the previously created image
- in Registry coloumn select repo-username adinusa
- In Image coloumn fill with {username docker}/nginx:lab76 -> Click Tag
- Select Push to Registry
- Check the image if already pushed in docker hub dashboard / try to pull the image
**Buat Image dari Dockerfile**



**Mengarahkan Image ke Docker Hub**



# MODUL 8
##### KOMPONEN YANG DIBAHAS :
* [logging Driver](/null)
### Logging Driver
Docker menyertakan beberapa mekanisme pencatatan untuk membantu Anda mendapatkan informasi dari kontainer dan layanan yang sedang berjalan. Mekanisme ini disebut dengan logging driver. Setiap daemon Docker memiliki driver pencatatan default, yang digunakan oleh setiap kontainer kecuali jika Anda mengonfigurasinya untuk menggunakan driver pencatatan yang berbeda, atau disingkat "log-driver".
Sebagai default, Docker menggunakan logging driver json-file, yang menyimpan log kontainer sebagai JSON secara internal. Selain menggunakan logging driver yang disertakan dengan Docker, Anda juga dapat mengimplementasikan dan menggunakan plugin logging driver.
# LAB 8.1
**Eksekusi pada node01**
**Buat file daemon.json**
```bash!
student@pod-alfian5-node01:~$ sudo vim /etc/docker/daemon.json
```
```bash!
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "100"
}
}
```
**Restart Daemon dan Docker**
```bash!
student@pod-alfian5-node01:~$ sudo systemctl daemon-reload
```
```bash!
student@pod-alfian5-node01:~$ sudo systemctl restart docker
```

**Jalankan Kontainer**
```bash!
student@pod-alfian5-node01:~$ docker run --log-driver json-file --log-opt max-size=10m registry.adinusa.id/btacademy/alpine echo hello world
```

**Cek Logs pada direktori docker**
```bash!
student@pod-alfian5-node01:~$ 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 .
```

**Penyelesaian LAB 8.1**

# MODUL 9
##### KOMPONEN YANG DIBAHAS :
* [Health Check](/null)
### Health Check
Instruksi HEALTHCHECK memberi tahu Docker cara menguji kontainer untuk memeriksa apakah kontainer tersebut masih berfungsi. Hal ini dapat mendeteksi kasus seperti server web yang terjebak dalam perulangan tak terbatas dan tidak dapat menangani koneksi baru, meskipun proses server masih berjalan.
Ketika sebuah kontainer memiliki pemeriksaan kesehatan yang ditentukan, kontainer tersebut memiliki status kesehatan selain status normalnya. Status ini pada awalnya adalah mulai. Setiap kali pemeriksaan kesehatan berlalu, kontainer akan menjadi sehat (apa pun status sebelumnya). Setelah sejumlah kegagalan berturut-turut, kontainer menjadi tidak sehat.
# LAB 9.1
**Eksekusi di Node01**
### Health Check Practice 01
**Buat working directory**
```bash!
student@pod-alfian5-node01:~$ cd $HOME
```
```bash!
student@pod-alfian5-node01:~$ mkdir hc-latihan01
```
```bash!
student@pod-alfian5-node01:~$ cd hc-latihan01
```

**Buat Dockerfile**
```bash!
student@pod-alfian5-node01:~$ vim Dockerfile
```
```bash!
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**
```bash!
student@pod-alfian5-node01:~$ docker build docker build -t node-server .
```
**Jalankan Image**
```bash!
student@pod-alfian5-node01:~$ docker run -d -p 80:80 --name http-healthcheck http-healthcheck
```

**Cek Image**
```bash!
student@pod-alfian5-node01:~$ docker ps
```

**Cek dengan command CURL**
```bash!
student@pod-alfian5-node01:~$ curl http://localhost/
```

**Cek untuk unhealthy**
```bash!
student@pod-alfian5-node01:~$ curl http://localhost/unhealthy
```
**Cek status kontainer pada docker**
```bash!
student@pod-alfian5-node01:~$ docker container ls
```

**Cek dengan command CURL**
```bash!
student@pod-alfian5-node01:~$ curl http://localhost/
```

### Health Cek Practice02
**Buat direktori baru**
```bash!
student@pod-alfian5-node01:~$ cd $HOME
```
```bash!
student@pod-alfian5-node01:~$ mkdir hc-latihan02
```
```bash!
student@pod-alfian5-node01:~$ cd hc-latihan02
```
**Buat file server.js**
```bash!
student@pod-alfian5-node01:~$ vim server.js
```
```bash!
"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 Docker file**
```bash!
student@pod-alfian5-node01:~$ vim Dockerfile
```
```bash!
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**
```bash!
student@pod-alfian5-node01:~$ docker build -t node-server .
```

**Jalankan Image**
```bash!
student@pod-alfian5-node01:~$ docker run -d --name nodeserver -p 8080:8080 -p 8081:8081 node-server
```

**Cek kontainer**
```bash!
student@pod-alfian5-node01:~$ curl 127.0.0.1:8080
```

```bash!
student@pod-alfian5-node01:~$ docker ps
```

```bash!
student@pod-alfian5-node01:~$docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
```

**Cek kontainer**
```bash!
student@pod-alfian5-node01:~$ curl 127.0.0.1:8081
```

```bash!
student@pod-alfian5-node01:~$ docker ps
```

```bash!
student@pod-alfian5-node01:~$docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
```

**Penyelesaian LAB 9.1**

# MODUL 10
##### KOMPONEN YANG DIBAHAS :
* [Docker Security](/null)
* [CIS Docker Benchmark](/null)
* [Secure Computing Mode](/null)
* [Secret](/null)
### Docker Security
**Kernel Namespaces**
Kontainer Docker sangat mirip dengan kontainer LXC, dan memiliki fitur keamanan yang serupa. Saat memulai kontainer dengan menjalankan docker, di balik layar, Docker menciptakan satu set ruang nama dan grup kontrol untuk kontainer. Ruang nama menyediakan bentuk isolasi pertama dan paling mudah: proses yang berjalan di dalam kontainer tidak dapat melihat, dan bahkan tidak memengaruhi, proses yang berjalan di kontainer lain, atau di sistem host. Setiap kontainer juga mendapatkan tumpukan jaringannya sendiri, yang berarti bahwa sebuah kontainer tidak mendapatkan akses istimewa ke soket atau antarmuka kontainer lain. Tentu saja, jika sistem host diatur dengan benar, kontainer dapat berinteraksi satu sama lain melalui antarmuka jaringan masing-masing - seperti halnya berinteraksi dengan host eksternal. Ketika Anda menentukan port publik untuk kontainer Anda atau menggunakan tautan, maka lalu lintas IP diperbolehkan di antara kontainer. Mereka dapat melakukan ping satu sama lain, mengirim/menerima paket UDP, dan membuat koneksi TCP, tetapi dapat dibatasi jika perlu. Dari sudut pandang arsitektur jaringan, semua kontainer pada suatu host Docker berada pada antarmuka jembatan. Ini berarti bahwa mereka seperti mesin fisik yang terhubung melalui sakelar Ethernet umum; tidak lebih, tidak kurang.
**Control Groups**
Grup Kontrol adalah komponen kunci lain dari Linux Containers. Grup ini menerapkan penghitungan dan pembatasan sumber daya. Grup ini menyediakan banyak metrik yang berguna, tetapi juga membantu memastikan bahwa setiap kontainer mendapatkan bagian yang adil dari memori, CPU, disk I/O; dan, yang lebih penting, bahwa satu kontainer tidak dapat membuat sistem menjadi rusak karena menghabiskan salah satu sumber daya tersebut. Jadi, meskipun mereka tidak berperan dalam mencegah satu kontainer mengakses atau memengaruhi data dan proses kontainer lain, mereka sangat penting untuk menangkis beberapa serangan penolakan layanan. Mereka sangat penting pada platform multi-penyewa, seperti PaaS publik dan privat, untuk menjamin waktu aktif (dan kinerja) yang konsisten bahkan ketika beberapa aplikasi mulai berperilaku buruk.
Kontainer Docker, secara default, cukup aman, terutama jika Anda menjalankan proses Anda sebagai pengguna yang tidak memiliki hak istimewa di dalam kontainer.
**CIS Docker Benchmark**
CIS menciptakan praktik-praktik terbaik untuk keamanan dan pertahanan dunia maya. CIS menggunakan urun daya untuk menentukan rekomendasi keamanannya. Tolok Ukur CIS adalah salah satu alat yang paling populer.
Organisasi dapat menggunakan CIS Benchmark untuk Docker untuk memvalidasi bahwa kontainer Docker dan runtime Docker mereka dikonfigurasikan seaman mungkin. Terdapat alat bantu sumber terbuka dan komersial yang dapat secara otomatis memeriksa lingkungan Docker Anda terhadap rekomendasi yang ditetapkan dalam CIS Benchmark for Docker untuk mengidentifikasi konfigurasi yang tidak aman.
CIS Benchmark untuk Docker menyediakan sejumlah pemeriksaan konfigurasi yang bermanfaat, tetapi organisasi harus menganggapnya sebagai titik awal dan melampaui pemeriksaan CIS untuk memastikan praktik terbaik diterapkan. Menetapkan batasan sumber daya, mengurangi hak istimewa, dan memastikan citra berjalan dalam mode hanya-baca adalah beberapa contoh pemeriksaan tambahan yang perlu Anda jalankan pada berkas kontainer Anda.
**Secure Computing Mode**
Mode komputasi aman (seccomp) adalah fitur kernel Linux. Anda dapat menggunakannya untuk membatasi tindakan yang tersedia di dalam kontainer. Panggilan sistem seccomp() beroperasi pada status seccomp dari proses pemanggilan. Anda dapat menggunakan fitur ini untuk membatasi akses aplikasi Anda.
**Secret**
Rahasia adalah gumpalan data yang tidak boleh dikirim melalui jaringan atau disimpan tanpa dienkripsi di dalam Dockerfile atau di dalam kode sumber aplikasi Anda.
# MODUL 11
##### KOMPONEN YANG DIBAHAS :
* [Docker Storage Driver](/null)
### Docker Storage Driver
Storage driver berperan dalam memberikan akses kepada pengguna ke dalam lapisan container writeable. Storage driver juga berperan pada penyimpadan dan pengelolaan image juga container di host Docker pengguna. Berikut storage driver yang dapat digunakan pada Docker:
Comment
- overlay2: driver untuk semua distribusi Linux dan tidak memerlukan konfigurasi tambahan.
- aufs: driver untuk Docker 18.06 dan yang lebih lama, ketika dijalankan di Ubuntu yang tidak mendukung overlay2.
- fuse-overlayfs: untuk menjalankan Rootless Docker pada host yang tidak menyediakan dukungan untuk rootless overlay2.
- devicemapper:dapat dijalankan tapi memerlukan direct-lvm untuk lingkungan produksi, karena loopback-lvm, meskipun konfigurasi nol, memiliki kinerja yang sangat buruk.
- btrfs dan zfs: penyimpanan digunakan jika ada sistem file pendukung yang memungkinkan opsi lanjutan, seperti membuat “snapshot”.
- vfs: penyimpanan dimaksudkan untuk tujuan pengujian, dan untuk situasi
Berikut merupakan rekomendasi penggunaan driver:
# LAB 11.1
**Eksekusi di node01**
**Edit file daemon.json**
```bash!
student@pod-alfian5-node01:~$ sudo vim /etc/docker/daemon.json
```
```bash!
{
"storage-driver": "vfs"
}
```
**Restart Service Docker**
```bash!
student@pod-alfian5-node01:~$ sudo service docker restart
```
**Cek docker info**
```bash!
student@pod-alfian5-node01:~$ docker info
```

**Check with Dockerpull**
```bash!
student@pod-alfian5-node01:~$ docker pull registry.adinusa.id/btacademy/ubuntu
```

**Check the docker directory**
```bash!
student@pod-alfian5-node01:~$ sudo ls -al /var/lib/docker/vfs/dir/
```

```bash!
student@pod-alfian5-node01:~$ sudo du -sh /var/lib/docker/vfs/dir/
```

**Penyelesaian LAB 11.1**

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