# **Modul 1: Introduction of Container**
## 1. Container
Docker Container dibutuhkan untuk mengatasi permasalahan kompabilitas di dalam suatu server yang memiliki beberapa aplikasi yang berjalan sekaligus. Biasanya setiap aplikasi membutuhkan dependesi eksternal, permasalahaan muncul disaat dua aplikasi membutuhkan dependesi yang sama tapi beda versi atau ketika ada aplikasi yang akan diupdate. Solusi dari masalah tersebut adalah menggunakan **Container** yang berfungsi sebagai virtual machine ringan yang berisi aplikasi, frameworks, dan libraries.
Container sangat berguna karena lebih aman dibandingkan dengan aplikasi yang tidak menggunakan container, karena container menggunakan Linux kernel namespaces untuk sandbox aplikasi yang berbeda di komputer yang sama. Selain itu kita dapat dengan mudah mensimulasikan production-like environment. Yang terakhir container berguna untuk penyediaan infrastruktur dan menjalankan serta memantau aplikasi dalam produksi.
berikut adalah contoh Containerized Technology:
* Docker
* Podman
* LXC
* LXD
## **2. Host, Virtual Machine and Container**

Bisa dilihat, yang membedakan dedicated machine dan virtual machine adalah dedicated machine menajalankan aplikasi dalam satu software stack, sedangkan virtual machine menjalankan tiga aplikasi dalam dua software stack yang berbeda.

Diagram ini menjelaskan bahwa docker dapat menghilangkan kebutuhan untuk menggunakan beberapa OS.
# **Modul 2: Introduction to Docker**
## **1. Lab 2.1: Instalasi Docker**
1. Lakukan instalasi pada kedua node. Jalankan perintah berikut
```
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
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
```
2. Setelah melakukan instalasi tambahkan user ke docker group.
```
groupadd docker
sudo usermod -aG docker $USER
sudo chmod 666 /var/run/docker.sock
```
3. Tes instalasi docker dengan:
```
docker run registry.adinusa.id/btacademy/hello-world
docker image ls
```

Untuk menampilkan container
```
docker container ls -a
```

## **2. Lab 2.2: Docker Run - Part 1**
### **2.1. Practice 01**
1. Cari image redis dari dockerhub & harbor
```
# From DockerHub
docker search redis
# From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/redis
```
2. Jalankan image redis
```
docker run registry.adinusa.id/btacademy/redis
docker run -d registry.adinusa.id/btacademy/redis
docker run -d --name redis1 registry.adinusa.id/btacademy/redis
```

3. Tampilkan docker yang sedang dijalankan
```
docker ps -a
docker container ls -a
```

4. Untuk menampilkan status-status container dapat menggunakan
```
# docker inspect CONTAINER_NAME/CONTAINER_ID
docker inspect redis1
# docker logs CONTAINER_NAME/CONTAINER_ID
docker logs redis1
# docker stats CONTAINER_NAME/CONTAINER_ID
docker stats redis1
# docker top CONTAINER_NAME/CONTAINER_ID
docker top redis1
```
5. Matikan container
```
# docker stop CONTAINER_NAME/CONTAINER_ID
docker stop redis1
```

### **2.2. Practice 02**
1. Cari image nginx di dockerhub dan harbor
```
# From DockerHub
docker search nginx
# From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/nginx
```

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

2. Untuk menampilkan deskripsi nginx container dapat menggunakan:
```
docker inspect nginx1
```
4. Menjalankan image nginx dan deklarasi container port
```
docker run -d --name nginx2 -p 80 registry.adinusa.id/btacademy/nginx:latest
```

5. Test browsing
```
curl localhost:$(docker port nginx2 80 | cut -d : -f 2)
```

6. Menampilkan container (activate/exit) dan image docker
```
# Container
docker ps -a
docker container ls -a
# Image docker
docker images
```
## **3. Lab 2.3: Docker Run - Part 2**
### **3.1. Practice 03**
1. Cari image nginx di dockerhub dan harbor
```
# From DockerHub
docker search nginx
# From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/nginx
```

2. Menjalankan nginx engine dengan nama nginx1 dan ekspos port 8080
```
docker run -d --name nginx1 -p 8080:80 registry.adinusa.id/btacademy/nginx:latest
```

3. Untuk menampilkan deskripsi nginx container dapat menggunakan:
```
docker inspect nginx1
```
4. Menjalankan nginx engine dengan nama nginx2 dan ekspos port 8081
```
docker run -d --name nginx2 -p 8081:80 registry.adinusa.id/btacademy/nginx:latest
```

5. Menampilkan container (activate/exit)
```
docker ps -a
docker container ls -a
```

6. Menampilkan nginx yang ada di container
```
curl localhost:8080
curl localhost:8081
```

7. Mengakses container dan update & install editor
```
# Mengakses container
docker exec -it nginx2 /bin/bash
# Update dan install editor
apt-get update -y && apt-get install nano -y
```

8. Mengubah index.html
```
nano index.html /usr/share/nginx/html/index.html
```

9. restart nginx dan jalankan ulang containernya
```
# Restart nginx
service nginx restart
# Jalankan container
docker start nginx2
```
10. Menampilkan nginx output di container
```
curl localhost:8080
curl localhost:8081
```

11. Menampilkan status-status nginx yang ada di container
```
# Deskripsi container
docker inspect nginx1
docker inspect nginx2
# Log content
docker logs nginx1
docker logs nginx2
# Resource yang digunakan
docker stats nginx1
docker stats nginx2
# Running process
docker top nginx1
docker top nginx2
```
### **3.2. Practice 04**
1. Cari image ubuntu dari DockerHub & Harbor
```
# From DockerHub
docker search ubuntu
# From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/ubuntu
```

2. Pull image dari harbor
```
docker pull registry.adinusa.id/btacademy/ubuntu
```
3. Menajalankan ubuntu dan akses console
```
docker run -it --name ubuntu1 registry.adinusa.id/btacademy/ubuntu
Exit the container with Ctrl+D or exit
docker ps -a
```

4. Jalankan container ubuntu dan hapus jika ingin 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
```
## **4. Lab 2.4: Docker Run - Part 3**
### **4.1. Practice 05**
1. Menjalankan 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
```

2. Pull image phpmyadmin dari harbor.
```
docker pull registry.adinusa.id/btacademy/phpmyadmin:latest
```

3. Menjalankan phpmyadmin container dan sambungkan ke mysql container.
```
docker run --name my-phpmyadmin -d --link my-mysql:db -p 8090:80 \
registry.adinusa.id/btacademy/phpmyadmin
```
4. Tes browsing
```
Buka http://10.10.10.11:8090/
lalu login dengan user: `root` dan password: `RAHASIA`
```

### **4.2. Practice 06**
1. Jalankan container ubuntu dengan nama ubuntu1 & ubuntu2 lalu lihat list container
```
docker run -dit --name ubuntu1 registry.adinusa.id/btacademy/ubuntu
docker run -dit --name ubuntu2 registry.adinusa.id/btacademy/ubuntu
docker ps
```

2. Pause container ubuntu, lalu bandingkan dengan list container yang sebelumnya
```
docker pause ubuntu1
docker pause ubuntu2
docker ps
```

3. Untuk melihat penggunaan resource terhadap ubuntu yang dipause dapat menggunakan:
```
docker stats ubuntu1
docker stats ubuntu2
```
4. Unpause container ubuntu1.
```
docker unpause ubuntu1
```
### **4.3. Practice 07**
1. Menjalankan container database dengan spesifikasi yang dibatasi
```
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. Membuat container wordpress dan sambungkan ke database container
```
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. Cek log, process, 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
```



4. Tes Browsing
```
Buka website http://10.10.10.11
```

# **Modul 3: Managing Docker Container**
## **1. Managing the Life Cycle of Containers**


### **1.1. Membuat container**

Docker akan menjalankan command run untuk membuat container baru dari image dan menjalankan proses didalam container. Jika tidak ada container image maka akan secara otomatis mendownload imagenya

Setiap kali container dibuat, docker akan membuat **Container ID** secara acak dan unik dan **Name** yang dibuat secara manual. Untuk memberi nama pada container dapat menggunakan --name untuk mendefinisikan nama
### **1.2. Menjalankan Perintah di Container**

Untuk menjalankan perintah di dalam container dapat menggunakan perintah **exec** diikuti dengan nama container atau container ID. Setelah menjalankan perintah exec, kita dapat menjalankan perintah di dalam container.
## **2. Registry**
Registry adalah image storage yang terpusat. Di dalam Registry akan ada banyak image seperti hub.docker.com. Docker Registry diatur oleh Docker Repositories, dimana repository menyimpan semua versi di dalam suatu image. Registry memungkinkan user untuk mengambil image secara lokal serta push image ke dalam registry. Docker private registry sama seperti Docker Registry tapi kita bisa menentukan siapa yang dapat mengakses registry
## **3. Docker Volume**
Volume adalah mekanisme untuk menyimpan data oleh Docker container dan digunakan oleh Docker container. Volume memiliki lebih banyak keuntungan dibandingkan Bind Mounts salah satunya adalah Volume lebih mudah untuk back up atau migrasi, Volume lebih aman untuk di bagi ke beberapa container, dan memiliki performa lebih tinggi.
## **4. Docker Network**
### **4.1. Network drivers**
Ada beberapa drivers untuk memenuhi kebutuhan networking:
* **bridge**
* **host**
* **overlay**, menyambungkan beberapa Docker daemon dan digunakan untuk melakukan komunikasi swarm service dan container
* **macvlan**, untuk memberi container MAC address
* **none**, untuk mematikan semua networking disebuah container
* **Network plugins**, untuk install plugin third-party
### **4.2. Bridge Networks**
Bridge network digunakan untuk memungkinkan container melakukan komunikasi sekaligus menyediakan isolasi dar container yang tidak tersambung ke bridge network

### **4.3. Overlay Networks**
Overlay network driver membuat network terdistribusi di beberapa Docker daemon hosts. Network yang dibuat berada di atas host-specific networks, memungkinkan container untuk menyambungkan ke network.

### **4.3. Host Networking**
Jika host network dibuat di sebuah container, network stack container tersebut tidak terisolasi dari Docker host dan containernya tidak mempunyai ip address
## **5. Lab 3.1: Mount Volume**
1. Membuat direktori
```
cd $HOME
mkdir -p latihan/latihan01-volume
cd latihan/latihan01-volume
```
2. Membuat file dan container untuk data 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
```

3. Mount volume ke container
```
docker run --volumes-from my-volume registry.adinusa.id/btacademy/ubuntu ls /my-volume
```

## **6. Lab 3.2: Mount Volume with NFS Server**
1. Membuat direktori dan membuat NFS Server dengan docker (di node 01)
```
sudo mkdir -p /data/nfs-storage01/
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
```

2. Install package, mount volume di NFS client dan buat file untuk cek volume (di node 02)
```
ssh 10.7.7.20
sudo apt install nfs-client -y
sudo mount -v -o vers=4,loud 10.7.7.10:/ /mnt
sudo touch /mnt/file1.txt
sudo touch /mnt/file2.txt
exit
```

3. Lakukan verifikasi di node 01
```
ls /data/nfs-storage01/
```

## **7. Lab 3.3: Mount Volume with Read-only mode**
1. Membuat docker volume, lihat listnya, dan lihat docker volume detail
```
docker volume create my-vol
docker volume ls
docker volume inspect my-vol
```


2. Menjalankan container dengan volume read dan write access
```
docker run -d --name=nginx-rwvol -v my-vol:/usr/share/nginx/html -p 4005:80 registry.adinusa.id/btacademy/nginx:latest
```

3. Menampilkan ip address dari kontainer
```
docker inspect nginx-rwvol | jq -r '.[].NetworkSettings.IPAddress'
```

4. Membuat index.html dan pindahkan ke direktori source volume lalu tes browsing
```
sudo echo "This is from my-vol source directory" > index.html
sudo mv index.html /var/lib/docker/volumes/my-vol/_data
curl http://172.17.0.2
```

5. Menjalankan container dengan volume read-only access dan melihat detil nginx-rovol container
```
docker run -d --name=nginx-rovol -v my-vol:/usr/share/nginx/html:ro registry.adinusa.id/btacademy/nginx:latest
docker inspect nginx-rovol | jq '.[].Mounts'
```

## **8. Lab 3.4: Volume Driver**
1. Buat /share dan index.html di node02
```
sudo mkdir /share
sudo chmod 777 /share
echo "Hello Adinusa!" > /share/index.html
```
2. Instal plugin sshfs dan set plugin sshfs di node 01
```
docker plugin install --grant-all-permissions vieux/sshfs
docker plugin ls
docker plugin disable ffc82daabc2e
docker plugin set vieux/sshfs sshkey.source=/home/student/.ssh/
docker plugin enable ffc82daabc2e
docker plugin ls
```

3. Membuat docker volume dengan driver sshfs lalu test running container dengan volume
```
docker volume create --driver vieux/sshfs -o sshcmd=student@10.7.7.20:/share -o allow_other sshvolume
docker run -d --name=nginxtest-sshfs -p 8090:80 -v sshvolume:/usr/share/nginx/html registry.adinusa.id/btacademy/nginx:latest
```
4. Tes browsing
```
docker ps
curl http://localhost:8090
```

## **9. Lab 3.5: Default Bridge Network**
1. Lihat list network
```
sudo docker network ls
```

2. Jalankan 2 alpine container yang menjalankan 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
```

3. Buat docker network dan sambungkan ke container alpine1 dan cek ip address alpine2
```
docker network create --driver bridge bridge1
docker network connect bridge1 alpine1
docker inspect alpine2 | jq -r '.[].NetworkSettings.IPAddress'
```

4. Akses alpine1 dan tampilkan ip addressnya
```
docker exec -it alpine1 sh
ip add
```

5. Ping ip alpine1, ip alpine2, dan nama alpine2
```
ping -c 3 8.8.8.8
ping -c 3 172.17.0.3
ping -c 3 alpine2
```

## **10. Lab 3.6: Host Network**
1. Jalankan container nginx dengan network host dan tes browsing localhost
```
docker run -itd --network host --name my_nginx registry.adinusa.id/btacademy/nginx
curl http://localhost
```

2. Verifikasi ip address dan bound port 80
```
ip add
sudo netstat -tulpn | grep :80
```

# **Modul 4: Creating Custom Docker Container Image**
## **1. Docker Image**
Image adalah wadah yang menampung layered filesystem. Dalam layered filesystem terdapat base layer yang berada di layer pertama. Di setiap layer terdapat file dan folder yang berisi perubahan pada filesystem sehubungan dengan layer dibawahnya. Layer yang berada di container image adalah immutable yang artinya saat dibuat, layer tersebut tidak bisa diubah hanya bisa dihapus

Saat Docker Engine membuat container dari image, akan ada writable container layer di layer paling atas

## **2. Lab 4.1: Exploring Dockerfile**
### **2.1. Practice 01**
1. Clone repository dan buat image
```
git clone https://github.com/spkane/docker-node-hello.git --config core.autocrlf=input latihan01
cd latihan01
docker build -t node-latihan01 .
```

2. jalankan container dan akses container
```
docker run -d --rm --name node-latihan01 -p 8080:8080 node-latihan01
curl localhost:8080
```

### **2.2. Practice 02**
1. Buat direktori latihan2 dan buat dockerfile
```
cd $HOME
mkdir latihan02
cd latihan02
vim Dockerfile
```

2. buat image dari Docker file dan tampilkan
```
docker build -t docker-whale .
docker image ls
```

## **2. Lab 4.1: Exploring Dockerfile (Flask Apps)**
Login docker terlebih dahulu
1. Buat direktori latihan03 & buat file flask, requirements.txt, Dockerfile
```
cd $HOME
mkdir latihan03
cd latihan03
vim app.py
vi requirements.txt
vim Dockerfile
```



2. Buat image dari Dockerfile dan tag image dengan username docker
```
docker build -t flask-latihan03 .
docker tag flask-latihan03 alvanm/flask-latihan03:latest
```

3. Push image ke dockerhub dan jalankan image
```
docker push alvanm/flask-latihan03:latest
docker run -d -p 5000:5000 --name flask03 alvanm/flask-latihan03
```

4. Tes browsing
```
curl localhost:5000
```

## **3. Lab 4.3: Exploring Dockerfile (Quiz)**
1. Buat direktori latihan-quiz01 lalu git clone, setelah itu buat docker file
```
mkdir latihan-quiz01
cd latihan-quiz01/
git clone https://github.com/rivawahyuda/mywebsite.git
nano Dockerfile
```


2. Buat image latihan-quiz01-image
```
docker build -t latihan-quiz01-image .
```

3. Jalankan container dengan image tersebut, ekspos dengan port 80 dengan nama quiz01
```
docker run -d -p 80:80 --name quiz01 latihan-quiz01-image
```
4. Tes browsing
```
Buka website dengan alamat ip node01 atau http://10.10.10.11
```

# **Modul 5: Docker Compose**
Docker Compose adalah tool yang digunakan untuk menjalankan dan mengatur container yang berjalan di dalam satu docker host. Docker Compose menggunakan file yaml/yml sebagai input yang memiliki sifat deklaratif.
## 1. **Lab 5.1: Using Docker Compose**
1. Download dan install Compose di kedua node lalu lihat versinya
```
sudo curl -L --resolve raw.githubusercontent.com:443:185.199.108.133 https://github.com/docker/compose/releases/download/v2.24.6/docker-compose-linux-x86_64 -o /usr/bin/docker-compose && \
sudo chmod 755 /usr/bin/docker-compose
```

2. Buat direktori my_wordpress dan buat file docker-compose didalamnya
```
cd $HOME
mkdir -p latihan/my_wordpress
cd latihan/my_wordpress
vim docker-compose.yml
```


3. Jalankan container dan lihat list container
```
docker-compose up -d
docker container ls
```


# **Modul 6: Docker Continous Integration (CI)**
## **1. CI Menggunakan Docker**
Continuous Integration (CI) adalah praktik mengintegrasikan kode ke shared repository. Setiap check-in akan diverifikasi oleh automated build, memudahkan tim untuk mencari dan menghilangkan masalah dengan cepat.

Karena Docker bisa integrasi dengan Jenkins dan GitHub, developer bisa submit code ke GitHub, tes kode dan secara otomatis melakukan build pakai Jenkins, dan setelah build, image bisa ditambahkan ke docker registries.
## **2. Docker Hub Automated Build**
Docker Hub bisa secara otomatis membangun image dari source code menggunakan repositori eksternal dan push ke Docker repository
# **Modul 7: Docker Swarm dan Portainer**
## **1. Docker Swarm**
Docker Swarm adalah sekumpulan komputer yang berjalan di Docker. Setelah kumpulan komputer dikelompokan, Docker command yang dijalankan akan berlaku ke semua komputer yang ada di kelompok
## **2. Portainer untuk Docker**
Portainer adalah universal container management tool untuk melakukan deployment dan pengelolaan dari ontainerized applications dan services.
## **3. Lab 7.1 - Create Swarm**
1. Inisialisasi Docker Swarm
```
docker swarm init --advertise-addr 10.7.7.10
```

2. Copy command docker join di node02
```
docker swarm join --token SWMTKN-1-13nlc7oojz2c6lsr3uticm2qfiqbrjwwn67zxy2z0x6t7kg05s-egod0z9otq1p68wx45402ekiv 10.7.7.10:2377
```

3. Cek apakah node02 sudah join
```
docker node ls
```

## **4. Lab 7.2 - Deploy Service to Swarm**
1. Buat service nginx dengan 2 replika dan ekspos ke port 80
```
docker service create --name web --replicas 2 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
```

2. Periksa apakah kodenya berjalan dan tes browsing dari node01 dan node 02
```
docker service ls
curl http://10.7.7.10
curl http://10.7.7.20
```

3. Periksa informasi tentang service
```
docker service inspect --pretty web
```

4. Buat container dengan cpu dan memori yang terbatas
```
docker service create --name alvan --reserve-cpu 1 --limit-cpu 1 \
--reserve-memory 256mb --limit-memory 128mb registry.adinusa.id/btacademy/httpd:latest
```

5. Periksa container yang baru dibuat
```
docker service inspect --pretty alvan
```

## **5. Lab 7.3 - Docker swarm Scale & Update**
1. Buat service nginx dengan 3 replica
```
docker service create --name web2 --replicas 3 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
```

3. Ubah replica service
```
docker service scale web2=1
```

4. Periksa apakah replica sudah diubah
```
docker service ls
docker service ls
```

5. Melakukan update ke service di swarm
```
docker service update --image sistyo/myweb web2
docker service inspect --pretty web2
```

## **6. Lab 7.4 - Install Portainer and configuration**
1. 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
```


2. Akses Portainer Dashboard
```
Buka 10.10.10.11:9000 di browser
```
3. Click menu Environments -> Add environmets -> Select Docker Swarm -> Start Wizard -> Select Agent -> Copy command ke node01

```
docker network create \
--driver overlay \
portainer_agent_network
docker service create \
--name portainer_agent \
--network portainer_agent_network \
-p 9001:9001/tcp \
--mode global \
--constraint 'node.platform.os == linux' \
--mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock \
--mount type=bind,src=//var/lib/docker/volumes,dst=/var/lib/docker/volumes \
portainer/agent:2.19.4
```

4. Di portainer board
* isi NAME Column dengan hostname node02 pod-username-node02
* isi Environment URL dengan ip address node02 10.7.7.20:9001
* klik connect

## **7. Lab 7.5 - Running Container from Portainer**
1. Buka Portainer lalu:
* Ke Home -> node02 -> Containers -> + Add Container
* Isi name Column dengan [username]-web
* Isi image dengan nginx:latest
* Klik Publish a new network port -> isi host coloumn 8080 dan container coloumn 80

2. Akses container dengan membuka laman http://10.10.10.12:8080

## **8. Lab 7.6 - Build & Push Image from Portainer**
1. Membuat Image dari Dockerfile

2. Buat registry DockerHub di Portainer

3. Periksa di DockerHub

# **Modul 8: Logging Driver**
Docker menyediakan Logging Driver yang berfungsi untuk membantu melihat informasi dari container dan service yang sedang berjalan. Docker menggunakan json-file logging driver untuk melakukan cache container sebagai JSON
## **1. Lab 8.1: Configuring Logging Driver**
1. Membuat file daemon.json
```
sudo vim /etc/docker/daemon.json
```

2. Restart Daemon dan Docker
```
sudo systemctl daemon-reload
sudo systemctl restart docker
```
3. Jalankan container
```
docker run --log-driver json-file --log-opt max-size=10m registry.adinusa.id/btacademy/alpine echo hello world
```

4. Periksa log 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 .
```

# **Modul 9: Health Check**
**Health Check** digunakan untuk menentukan apakah aplikasi sudah siap dan bisa melaksanakan fungsinya. instruksi **HEALTHCHECK** memerintahkan docker untuk memeriksa apakah container masih berjalan dengan benar.
Exit code menandakan health status containernya. Value dari exit code-nya adalah:
* 0: success - the container is healthy and ready for use
* 1: unhealthy - the container is not working correctly
* 2: reserved - do not use this exit code
## **1. Lab 9.1: Health Check**
### **1.1. Practice 01**
1. Buat working direktori
```
cd $HOME
mkdir hc-latihan01
cd hc-latihan01
```
2. Buat image dari Dockerfile
```
vim Dockerfile
```

3. Buat image dan jalankan
```
docker build -t http-healthcheck .
```

4. Cek image dan browser
```
docker ps
curl http://localhost/
# periksa yang unhealthy
curl http://localhost/unhealthy
```



5. Cek status container dan cek dengan curl
```
docker container ls
curl http://localhost/
```

### **1.2. Practice 02**
1. Buat working direktori
```
cd $HOME
mkdir hc-latihan02
cd hc-latihan02
```
2. Buat file server.js
```
vim server.js
```

3. Buat image dari Dockerfile
```
vim Dockerfile
```

4. Buat image dan jalankan
```
docker build -t node-server .
docker run -d --name nodeserver -p 8080:8080 -p 8081:8081 node-server
```

5. Cek container di kedua port
```
# Port 8080
curl 127.0.0.1:8080
docker ps
docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
curl 127.0.0.1:8081
docker ps
docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
```
**Port 8080**


**Port 8081**


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


# **Modul 10: Security**
## **1. Docker Security**
**Kernel namespaces** membuat setiap container terisolasi dari container lain, termasuk network stack yang mencegah serangan cyber. **Control groups** membatasi sumber daya untuk mencegah DDOS. **Docker daemon attack surface** mencegah orang yang tidak berwenang mengendalikan Docker daemon. **Linux kernel capabilities** mencegah processes bertindak menjadi root. **Docker Content Trust Signature Verification** memberikan wawasan terhadap administrator
## **2. CIS Docker Benchmark**
Center for Internet Security (CIS) menjamin bahwa Docker container dan runtime diatur seaman mungkin.
## **3. Secure Computing Mode**
Secure computing mode (seccomp) adalah sebuah fitur linux kernel yang dipakai untuk membatasi tindakan yang tersedia di dalam container.
## **4. Secret**
Secret adalah sekumpulan data yang tidak dikirim atau disimpan di tempat yang unencrypted, biasanya untuk password, SSH keys, dll.
# **Modul 11: Storage Driver**
Storage Drivers memungkinkan pengguna untuk melakukan write pada container layer writable. Berikut adalah storage driver yang didukung oleh docker:
* **overlay2**, tidak membutuhkan konfigurasi tambahan
* **aufs**, untuk docker versi lawas yang tidak memiliki dukungan untuk overlay2
* **fuse-overlayfs**, digunakan hanya untuk menjalankan Rootless Docker
* **devicemapper**, direkomendasikan untuk CentOS and RHEL yang tidak bisa menggunakan overlay2
* **btrfs & zfs**, digunakan jika ada backing filesystem
* **vfs**, untuk melakukan ujicoba
## **1. Lab 11.1: Configuring Storage Driver**
1. Edit file daemon.json
```
sudo vim /etc/docker/daemon.json
```

2. Restart service docker dan cek docker info
```
sudo service docker restart
docker info
```

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

5. Cek docker directory
```
sudo ls -al /var/lib/docker/vfs/dir/
sudo du -sh /var/lib/docker/vfs/dir/
```


# **Modul 12: Logging and Error Handling**
## 1. Log Check
Untuk melakukan cek di filesystem dalam sebuah container dapat menggunakan:
```
docker diff nama-container
```

Untuk membuka log dapat menggunakan:
```
docker logs --details nama-container
docker logs --timestamps nama-container
docker logs nama-container
```
# **Modul 13: Lab Challenge**
## **1. Challenge 1 - Haproxy With Docker**
1. Buat Working Direktori
```
mkdir challenge1
cd challenge1
```
2. Buat 2 container menggunakan image
```
docker run -d --name web1 -p 8081:80 registry.adinusa.id/btacademy/nginx:latest
docker run -d --name web2 -p 8082:80 registry.adinusa.id/btacademy/httpd:latest
```

3. Buat file konfigurasi haproxy.cfg
```
vim haproxy.cfg
```

4. Buat volume untuk menyimpan konfigurasi haproxy.cfg
```
docker volume create haproxy_config
```

5. Jalankan container alpine menggunakan haproxy dengan konfigurasi yang sudah dimount ke volume
```
docker run -d --name alvan-haproxy -p 80:80 -v haproxy-config:/usr/local/etc/haproxy registry.adinusa.id/btacademy/haproxy-alpine:2.4
```

## **2. Challenge 2 - Deploy Laravel with Docker (Hard)**
1. Buat Working Direktori
```
mkdir challenge2
cd challenge2
```
2. Clone repository dan buat docker file
```
git clone https://github.com/academynusa/perpus-laravel.git perpus
vim Dockerfile
```

3. Buat bash script
```
vim setup.sh
```

4. Build dan jalankan dari dockerfile
```
docker build -t img-perpus-username .
docker run -d -p 8000:8000 --name perpus-username img-perpus-username
```