---
# System prepended metadata

title: Docker Fundamental

---

---
title: HackMD Dark Theme
tags: theme
description: Use `{%hackmd theme-dark %}` syntax to include this theme.
---

<style>

html, body, .ui-content {
    background-color: #333;
    color: #ddd;
}

.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
    color: #ddd;
}

.markdown-body h1,
.markdown-body h2 {
    border-bottom-color: #ffffff69;
}

.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
    color: #fff;
}

.markdown-body img {
    background-color: transparent;
}

.ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a {
    color: white;
    border-left: 2px solid white;
}

.expand-toggle:hover, 
.expand-toggle:focus, 
.back-to-top:hover, 
.back-to-top:focus, 
.go-to-bottom:hover, 
.go-to-bottom:focus {
    color: white;
}


.ui-toc-dropdown {
    background-color: #333;
}

.ui-toc-label.btn {
    background-color: #191919;
    color: white;
}

.ui-toc-dropdown .nav>li>a:focus, 
.ui-toc-dropdown .nav>li>a:hover {
    color: white;
    border-left: 1px solid white;
}

.markdown-body blockquote {
    color: #bcbcbc;
}

.markdown-body table tr {
    background-color: #5f5f5f;
}

.markdown-body table tr:nth-child(2n) {
    background-color: #4f4f4f;
}

.markdown-body code,
.markdown-body tt {
    color: #eee;
    background-color: rgba(230, 230, 230, 0.36);
}

a,
.open-files-container li.selected a {
    color: #5EB7E0;
}

</style>
**©NICHOLAI DANDY NAINGGOLAN**
# Docker Fundamental
Tujuan untuk mempelajari Docker Fundamental;
- Mengerti dan memahami teknologi kontainer, dikarenakan saat ini teknologi kontainer sangat berguna untuk developer ataupun CC dan Devops. 

# 1. Pengenalan Kontainer
**A Guided Learning for Net Development 2024 under Adaptive Network Laboratory Telkom University**

# Apa itu Kontainer?
Kontainer adalah wadah standar yang memungkinkan pengemasan aplikasi beserta dependensinya, memfasilitasi pengiriman dan pengelolaan aplikasi dengan lebih mudah dan terstandarisasi. Kontainer memisahkan aplikasi dari infrastruktur, memungkinkan pengelolaan yang serupa dengan mengelola aplikasi, dan memberikan lingkungan terisolasi untuk menjalankan aplikasi

# Kenapa Kontainer itu penting?
Kontainer Docker telah menjadi bagian integral dari rantai pasokan perangkat lunak modern, membawa sejumlah manfaat yang sangat penting bagi pengembang, pengujian, dan operator infrastruktur. Berikut adalah beberapa alasan mengapa kontainer menjadi penting:

1. Keamanan: Kontainer memberikan lingkungan terisolasi untuk menjalankan aplikasi, menggunakan primitif keamanan Linux seperti namespace dan grup kontrol (cgroups). Ini mengurangi risiko serangan siber, membatasi dampak dari aplikasi berbahaya, dan memungkinkan pengguna untuk memantau dan mengelola keamanan aplikasi dengan lebih efektif.

2. Kepatuhan dan Keamanan Konten: Penggunaan kontainer memungkinkan implementasi kepercayaan konten, memastikan keaslian pembuat gambar kontainer dan integritas gambar selama perjalanan. Ini membantu mengurangi risiko serangan MITM dan meningkatkan kepatuhan keseluruhan.
![image](https://hackmd.io/_uploads/H1u9GUsaa.png)

3. Efisiensi Pengembangan dan Pengujian: Kontainer memungkinkan simulasi lingkungan produksi dengan mudah, bahkan di laptop pengembang. Ini memungkinkan pengguna untuk menjalankan aplikasi dan dependensinya, termasuk database relasional, tanpa perlu instalasi yang rumit. Hal ini meningkatkan efisiensi pengembangan dan pengujian, serta mengurangi beban pada infrastruktur pengembangan.

4. Skalabilitas dan Keterjangkauan: Kontainer lebih ringan daripada mesin virtual, memungkinkan banyak kontainer berjalan secara bersamaan tanpa membebani infrastruktur. Ini memungkinkan skalabilitas yang lebih besar dan biaya yang lebih rendah dalam pengelolaan aplikasi.

5. Standarisasi Infrastruktur: Dengan kontainer, operator dapat fokus pada standarisasi infrastruktur, dengan setiap server menjadi host Docker. Ini mengurangi kompleksitas instalasi dan pemeliharaan aplikasi, serta memungkinkan operator untuk fokus pada tugas mereka yang sesungguhnya.

Dengan demikian, kontainer Docker tidak hanya meningkatkan keamanan dan efisiensi dalam rantai pasokan perangkat lunak, tetapi juga memfasilitasi pengembangan, pengujian, dan pengelolaan infrastruktur yang lebih efektif, mengarah pada pengiriman aplikasi yang lebih cepat dan lebih andal.

# Contoh Teknologi Kontainer
1. Docker
![image](https://hackmd.io/_uploads/S1oMZDs6T.png)
Docker adalah platform untuk mengembangkan, mengirim, dan menjalankan aplikasi dengan cepat. Ini memisahkan aplikasi dari infrastruktur, memungkinkan pengelolaan yang serupa dengan mengelola aplikasi. Dengan kontainer, aplikasi diisolasi, ringan, dan mudah dibagikan. Docker menyediakan alat untuk siklus hidup kontainer:

- Mengembangkan aplikasi dengan kontainer.
- Mendistribusikan dan menguji aplikasi dengan kontainer.
- Mendeploy aplikasi ke lingkungan produksi, baik lokal, cloud, atau hibrida.

2. Podman
![image](https://hackmd.io/_uploads/BJX_WLaT6.png)
Podman adalah alat open source tanpa daemon untuk mengelola kontainer. Didesain untuk menemukan, menjalankan, membangun, berbagi, dan mendeploy aplikasi menggunakan Kontainer Inisiatif Terbuka (OCI) dan gambar kontainer. Memiliki antarmuka baris perintah (CLI) yang mirip dengan Docker, dan biasanya dapat di-alias dengan mudah. Podman menggunakan Pelaksana Kontainer OCI seperti runc, crun, atau runv untuk membuat kontainer, sehingga kontainer yang dihasilkan hampir tidak dapat dibedakan dari yang dibuat oleh mesin kontainer lainnya. Kontainer dijalankan oleh Podman dapat berjalan oleh root atau non-privileged user. Mengelola seluruh ekosistem kontainer termasuk pod, kontainer, gambar kontainer, dan volume menggunakan pustaka libpod. Podman menyediakan perintah dan fungsi untuk memelihara dan memodifikasi gambar kontainer OCI, termasuk menarik dan tagging. Ada juga API RESTFul untuk mengelola kontainer, dengan klien Podman yang mendukung Linux, Mac, dan Windows. Namun, layanan RESTFul hanya didukung di Linux.

3. LXC
![image](https://hackmd.io/_uploads/Skp0ZU6pp.png)
LXC adalah cara untuk membuat dan mengelola kontainer di Linux. Ini menggunakan beberapa fitur kernel untuk mengisolasi proses, seperti ruang nama, kebijakan keamanan seperti Apparmor dan SELinux, serta kontrol akses dengan CGroups. Kontainer LXC biasanya dianggap sebagai alternatif antara menggunakan chroot dan mesin virtual. Tujuannya adalah untuk memberikan lingkungan yang mirip dengan instalasi Linux biasa tanpa perlu menginstal kernel yang terpisah.

Beberapa komponen LXC;
- Library Liblxc
- Beberapa bahasa untuk API;
    - Python3
    - lua
    - Go
    - Ruby
    - Haskell
- Standart Tools untuk mengkontrol kontainer-kontainer
- Template kontainer

4. LXD
![image](https://hackmd.io/_uploads/ryATfL6p6.png)
LXD adalah manajer kontainer dan mesin virtual canggih berbasis gambar untuk sistem Linux. Ini menyediakan fleksibilitas untuk berbagai kasus penggunaan dengan dukungan untuk berbagai jenis penyimpanan dan jaringan. Dapat dijalankan pada berbagai perangkat keras mulai dari laptop hingga server. Anda dapat mengelola kontainer dan mesin virtual menggunakan antarmuka baris perintah, REST API, atau alat pihak ketiga. Dikembangkan oleh Canonical Ltd.

# Host, Virtual Machine dan Kontainer
Kontainer adalah abstraksi pada lapisan aplikasi yang mengemas kode dan dependensi bersama. Beberapa kontainer dapat berjalan pada mesin yang sama dan berbagi kernel OS dengan kontainer lain, masing-masing berjalan sebagai proses terisolasi di ruang pengguna. Kontainer memakan ruang yang lebih sedikit dibandingkan dengan mesin virtual (gambar kontainer biasanya berukuran puluhan MB), dan memulai hampir secara instan.

Mesin virtual (VM) adalah abstraksi dari perangkat keras fisik yang mengubah satu server menjadi banyak server. Hipervisor memungkinkan beberapa VM berjalan pada satu mesin. Setiap VM termasuk salinan penuh dari sistem operasi, satu atau lebih aplikasi, biner dan pustaka yang diperlukan - memakan ruang hingga puluhan GB. VM juga dapat lambat dalam proses booting.

Sekarang, mari kita lihat perbedaan antara Kontainer dan lingkungan mesin virtual tipikal. Diagram berikut menunjukkan perbedaan antara server fisik yang didedikasikan dan server yang menjalankan mesin virtual.
![image](https://hackmd.io/_uploads/SJWxY8a66.png)
Seperti yang terlihat, pada mesin yang didedikasikan, terdapat tiga aplikasi yang semuanya menggunakan tumpukan perangkat lunak oranye yang sama. Menjalankan mesin virtual memungkinkan kita menjalankan tiga aplikasi, masing-masing menggunakan dua tumpukan perangkat lunak yang benar-benar berbeda. Diagram berikut menunjukkan aplikasi oranye dan hijau yang sama berjalan dalam kontainer menggunakan Docker.
![image](https://hackmd.io/_uploads/S1ahsLaTT.png)
Diagram ini menjelaskan manfaat utama Docker: tidak perlu sistem operasi lengkap untuk setiap kontainer baru, mengurangi ukuran keseluruhan kontainer. Docker menggunakan kernel Linux dari sistem operasi host, memungkinkan berbagai sistem operasi Linux dijalankan di atasnya. Ini membuat aplikasi percaya bahwa sistem operasi lengkap terpasang, padahal sebenarnya hanya biner yang diperlukan. Misalnya, kita bisa menjalankan Red Hat dan Debian tanpa harus menginstalnya secara fisik di host. Docker juga menghasilkan gambar yang kecil karena tidak menyertakan kernel atau sistem operasi, membuatnya mudah dikirim.

# Lab 1.1 Preparation of Lab Environment
![Screenshot (901)](https://hackmd.io/_uploads/S16iRUTap.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# 2. Introduction to Docker
Apa itu Docker?
Docker adalah proyek open source untuk membangun, mengirim, dan menjalankan program. 

# Docker Products
![image](https://hackmd.io/_uploads/B1o5XPpTp.png)

Docker, Inc. adalah perusahaan yang dibentuk untuk mengembangkan Docker CE dan Docker EE. Mereka juga menyediakan layanan dukungan berbasis SLA untuk Docker EE. Selain itu, mereka menawarkan layanan konsultasi kepada perusahaan yang ingin mengambil aplikasi mereka yang sudah ada dan mengonterainkan mereka sebagai bagian dari program Modernize Traditional Apps (MTA) Docker.

Docker saat ini memisahkan produk-produknya menjadi dua segmen. Ada Community Edition (CE), yang bersifat tertutup namun sepenuhnya gratis, dan ada Enterprise Edition (EE), yang juga bersifat tertutup dan perlu dilisensikan secara tahunan. Produk-produk enterprise ini didukung oleh dukungan 24/7 dan didukung oleh perbaikan bug.

Docker CE
Bagian dari Docker Community Edition adalah produk seperti Docker Toolbox dan Docker for Desktop dengan edisi untuk Mac dan Windows. Semua produk ini terutama ditargetkan pada pengembang.

Docker for Desktop adalah aplikasi desktop yang mudah diinstal yang dapat digunakan untuk membangun, debug, dan menguji aplikasi atau layanan yang telah diconterkan pada mesin macOS atau Windows. Docker untuk macOS dan Docker untuk Windows adalah lingkungan pengembangan lengkap yang terintegrasi secara mendalam dengan kerangka hypervisor, jaringan, dan filesystem mereka masing-masing. Alat-alat ini adalah cara paling cepat dan paling andal untuk menjalankan Docker di Mac atau Windows.
![image](https://hackmd.io/_uploads/B1mnmwpTa.png)

Docker EE
Docker Enterprise Edition terdiri dari Universal Control Plane (UCP) dan Docker Trusted Registry (DTR), keduanya berjalan di atas Docker Swarm. Keduanya adalah aplikasi swarm. Docker EE dibangun di atas komponen-komponen hulu dari proyek Moby dan menambahkan fitur-fitur kelas enterprise seperti kontrol akses berbasis peran (RBAC), multi-tenancy, cluster campuran dari Docker swarm dan Kubernetes, UI berbasis web, dan kepercayaan konten, serta pemindaian gambar di atasnya.

Perbedaan Fitur Antara Docker CE dan Docker EE
![image](https://hackmd.io/_uploads/ry0LXvTTp.png)

# Docker Release Cycle

Mulai September 2018, siklus rilis untuk versi stabil Docker CE akan menjadi setiap dua tahun sekali, yang berarti akan memiliki siklus perawatan selama tujuh bulan. Ini berarti Anda memiliki banyak waktu untuk meninjau dan merencanakan pembaruan apa pun.

Pada saat penulisan, jadwal rilis Docker CE adalah sebagai berikut:
- Docker 18.06 CE: Ini adalah rilis terakhir dari rilis kuartalan Docker CE, dirilis pada 18 Juli 2018.
- Docker 18.09 CE: Rilis ini, yang dijadwalkan pada akhir September/awal Oktober 2018, adalah rilis pertama dari siklus rilis dua tahunan Docker CE.
- Docker 19.03 CE: Docker CE yang didukung pertama tahun 2019 dijadwalkan akan dirilis pada Maret/April 2019.
- Docker 19.09 CE: Rilis yang kedua yang didukung tahun 2019 dijadwalkan akan dirilis pada September/Oktober 2019.
- Docker 20.10 CE: Docker CE yang didukung pertama tahun 2020 dirilis pada 9 Desember 2020 dan akan menerima dukungan keamanan hingga 1 Maret 2023.
- Docker 23.0 CE: Docker CE yang didukung pertama tahun 2023 dirilis pada 2 Februari 2023 dan versi terbarunya saat ini adalah 23.0.1 yang dirilis pada 10 Februari 2023.

# Lab 2.1 Installing Docker
**Execute in all node (node-1 & node02)**
**1. 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
![Screenshot (902)](https://hackmd.io/_uploads/HkPiFK6aa.png)
`Execute in all node (node-1 & node02)`

**2. Display docker version.**
sudo docker version
![Screenshot (905)](https://hackmd.io/_uploads/SJOc3tTaT.png)
`Execute in all node (node-1 & node02)`

**3. Display the docker installation details.
**
sudo docker info
![Screenshot (904)](https://hackmd.io/_uploads/S1qk6KaTp.png)
`Execute in all node (node-1 & node02)`

**4. Add user into docker group.**
groupadd docker
sudo usermod -aG docker $USER
sudo chmod 666 /var/run/docker.sock
![Screenshot (906)](https://hackmd.io/_uploads/Hy06Jqapa.png)
`Execute in all node (node-1 & node02)`

**5. Test the docker installation**
docker run registry.adinusa.id/btacademy/hello-world
![Screenshot (908)](https://hackmd.io/_uploads/BJeXeq6a6.png)
`Execute in all node (node-1 & node02)`

**6. Display the downloaded image.**
docker image ls
![Screenshot (909)](https://hackmd.io/_uploads/r1_ilc6TT.png)
`Execute in all node (node-1 & node02)`

**7. Display all container (active or exit).**
docker container ls -a
![Screenshot (912)](https://hackmd.io/_uploads/HJgClc66T.png)
`Execute in all node (node-1 & node02)`

**8. Run the nusactl grade do-002-1 command to assess the lab results. (Adinusa)**
nusactl grade do-002-1
![Screenshot (916)](https://hackmd.io/_uploads/ryrQZca6a.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Lab 2.2 : Docker Run - Part 1
**Introduction**
Execute in node pod-[username]-node01

**running docker (practice 01)**

**1. Search image redis from dockerhub & harbor**
#From DockerHub
docker search redis
![Screenshot (917)](https://hackmd.io/_uploads/rymUU3a6T.png)

#From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/redis
![Screenshot (918)](https://hackmd.io/_uploads/rk8kDn66a.png)

**2. Running image redis**
docker run registry.adinusa.id/btacademy/redis  # CTRL + c for quit
![Screenshot (919)](https://hackmd.io/_uploads/rkUc_n66a.png)
docker run -d registry.adinusa.id/btacademy/redis  # Running in background (Background)
![Screenshot (920)](https://hackmd.io/_uploads/S1cC_2p6p.png)
docker run -d --name redis1 registry.adinusa.id/btacademy/redis # Giving the container a name
![Screenshot (921)](https://hackmd.io/_uploads/SyBNt3aaa.png)

**3. Display running container.**
docker ps 
![Screenshot (922)](https://hackmd.io/_uploads/rk2_t2TTa.png)
docker container ls
![Screenshot (923)](https://hackmd.io/_uploads/rk43KhT6p.png)

**4. Display all docker container.**
docker ps -a
![image](https://hackmd.io/_uploads/HJobq2Taa.png)
docker container ls -a
![Screenshot (925)](https://hackmd.io/_uploads/rkGEqnpa6.png)

**5. Display container description .**
#docker inspect CONTAINER_NAME/CONTAINER_ID
docker inspect redis1
![Screenshot (926)](https://hackmd.io/_uploads/BJGt5na66.png)

**6. Display content of the logs in container.**
#docker logs CONTAINER_NAME/CONTAINER_ID
docker logs redis1
![Screenshot (927)](https://hackmd.io/_uploads/H1iHs2ppT.png)

**7. Display live stream resource used in container.**
#docker stats CONTAINER_NAME/CONTAINER_ID
docker stats redis1
![Screenshot (928)](https://hackmd.io/_uploads/BJ3ghhp66.png)

**8. Display running process in container.**
#docker top CONTAINER_NAME/CONTAINER_ID
docker top redis1
![Screenshot (929)](https://hackmd.io/_uploads/H1xI3hTTT.png)

**9. Shutdown the container.**
#docker stop CONTAINER_NAME/CONTAINER_ID
docker stop redis1
![Screenshot (930)](https://hackmd.io/_uploads/ByY22hp6p.png)

**running docker (practice 02)**

**1. Search image nginx From DockerHub & Harbor**

#From DockerHub
docker search nginx
![Screenshot (931)](https://hackmd.io/_uploads/BysuThT66.png)
#From Harbor
sudo apt install skopeo
![Screenshot (932)](https://hackmd.io/_uploads/rJW_A2Tpp.png)
skopeo list-tags docker://registry.adinusa.id/btacademy/nginx
![Screenshot (933)](https://hackmd.io/_uploads/B1f9A2apT.png)

**2. Running image nginx and expose to port host.**
docker run -d --name nginx1 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
![Screenshot (935)](https://hackmd.io/_uploads/r1tNka66p.png)

**3. Display a description of the nginx container.**
docker inspect nginx1
![Screenshot (936)](https://hackmd.io/_uploads/r1opkT6Tp.png)

**4. Running image nginx and declare the container port.**
docker run -d --name nginx2 -p 80 registry.adinusa.id/btacademy/nginx:latest
![Screenshot (937)](https://hackmd.io/_uploads/SkrGl66TT.png)

**5. Test browsing.**
curl localhost:$(docker port nginx2 80 | cut -d : -f 2)
![Screenshot (938)](https://hackmd.io/_uploads/r1BDl6aap.png)

**6. Display container (activate/exit).**
docker ps -a 
![Screenshot (939)](https://hackmd.io/_uploads/rJwfbppp6.png)
docker container ls -a
![Screenshot (940)](https://hackmd.io/_uploads/ByPr-6Ta6.png)

**7. Display image docker.**
docker images
![Screenshot (941)](https://hackmd.io/_uploads/HJeK-paaT.png)

**Run the nusactl grade do-002-2 command to assess the lab results.**

nusactl grade do-002-2
Then, run the lab finish do-002-2 command to clean up the lab environment.
nusactl finish do-002-2
![Screenshot (942)](https://hackmd.io/_uploads/rJ0ZP6aTa.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Lab 2.3 : Docker Run - Part 2
Introduction
Execute in pod-[username]-node01

running docker (practice 03)

**1. Search image nginx from DockerHub & Harbor**
#From DockerHub
docker search nginx
![Screenshot (943)](https://hackmd.io/_uploads/Sk9-6Appp.png)
#From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/nginx
![Screenshot (944)](https://hackmd.io/_uploads/ByKzlJRpp.png)

**2. Running an nginx image with the name nginx1 and expose port 8080.**
docker run -d --name nginx1 -p 8080:80 registry.adinusa.id/btacademy/nginx:latest
![Screenshot (945)](https://hackmd.io/_uploads/Hk73gy0TT.png)

**3. Displays a description of the nginx1 container.**
docker inspect nginx1
![Screenshot (946)](https://hackmd.io/_uploads/r1iH-10ap.png)

**4. Running an nginx image with the name nginx2 and expose port 8081.**
docker run -d --name nginx2 -p 8081:80 registry.adinusa.id/btacademy/nginx:latest
![Screenshot (947)](https://hackmd.io/_uploads/SyN1M1066.png)

**5. Display container (activate/exit).**
docker ps -a 
![Screenshot (948)](https://hackmd.io/_uploads/SkvHGJApp.png)
docker container ls -a
![Screenshot (949)](https://hackmd.io/_uploads/HJAvMk0pp.png)

**6. Check nginx output on containers.**
curl localhost:8080
![Screenshot (950)](https://hackmd.io/_uploads/H1osG1CTT.png)
curl localhost:8081
![Screenshot (951)](https://hackmd.io/_uploads/B14RG106a.png)

**7. Accessing the container.**
docker exec -it nginx2 /bin/bash
![Screenshot (952)](https://hackmd.io/_uploads/BJKHXJApa.png)

**8. Update and install editor on the container.**
apt-get update -y && apt-get install nano -y
![Screenshot (953)](https://hackmd.io/_uploads/SkMVEk06p.png)

**9. Edit index.html and move index.html to default directory nginx**
nano index.html
...
hello, username.
...
![Screenshot (954)](https://hackmd.io/_uploads/SJT5EJR6T.png)
mv index.html /usr/share/nginx/html
![Screenshot (955)](https://hackmd.io/_uploads/HJ5krJCTT.png)

**10. Restart service nginx.**
service nginx restart
![Screenshot (956)](https://hackmd.io/_uploads/SJCMHJRa6.png)

**11. Rerun the container.**
docker start nginx2
![Screenshot (957)](https://hackmd.io/_uploads/BkfPrkCaa.png)

**12. Display container.**
docker ps
![Screenshot (958)](https://hackmd.io/_uploads/HyFcH1A6p.png)
docker container ls
![Screenshot (959)](https://hackmd.io/_uploads/BJOTS1R6p.png)

**13. Check nginx output on containers.**
curl localhost:8080
![Screenshot (960)](https://hackmd.io/_uploads/r1HzPyC6a.png)
curl localhost:8081
![Screenshot (961)](https://hackmd.io/_uploads/Sy-vw1C6p.png)

**14. Display a description of the container .**
docker inspect nginx1
![Screenshot (962)](https://hackmd.io/_uploads/H1IpwkA6T.png)
docker inspect nginx2
![Screenshot (964)](https://hackmd.io/_uploads/ry3Gd1R6T.png)

**15. Display the log content in the container.**
docker logs nginx1
![Screenshot (965)](https://hackmd.io/_uploads/SJLv_kRaT.png)
docker logs nginx2
![Screenshot (966)](https://hackmd.io/_uploads/Bk_9dyC66.png)

**16. Displays the live resources used in the container.**
docker stats nginx1
![Screenshot (967)](https://hackmd.io/_uploads/S1IlYyCpp.png)
docker stats nginx2
![Screenshot (968)](https://hackmd.io/_uploads/S1n7KyAT6.png)

**17. Display running process in container.**
docker top nginx1
![Screenshot (969)](https://hackmd.io/_uploads/Sk2EnJ0ap.png)
docker top nginx2
![Screenshot (970)](https://hackmd.io/_uploads/r1Ahn10aa.png)

**docker run (practice 04)**

**1. Search image ubuntu from DockerHub & Harbor**
#From DockerHub
docker search ubuntu
![Screenshot (971)](https://hackmd.io/_uploads/HklOa1A6T.png)
#From Harbor
skopeo list-tags docker://registry.adinusa.id/btacademy/ubuntu
![Screenshot (972)](https://hackmd.io/_uploads/ByVja1R6T.png)

**2. Pull image ubuntu from harbor**
docker pull registry.adinusa.id/btacademy/ubuntu
![Screenshot (973)](https://hackmd.io/_uploads/rkyMAJRpT.png)

**3. Running the ubuntu container and access to the console.**
docker run -it --name ubuntu1 registry.adinusa.id/btacademy/ubuntu
(Exit the container with Ctrl+D or exit)
![Screenshot (974)](https://hackmd.io/_uploads/SkKDNgRa6.png)
docker ps -a
![Screenshot (975)](https://hackmd.io/_uploads/HkbIzgIC6.png)

**4. Run the ubuntu container and delete it when exiting the container.**
docker run -it --rm --name ubuntu2 registry.adinusa.id/btacademy/ubuntu

Exit the container with Ctrl+D or exit
docker ps -a

![Screenshot (1175)](https://hackmd.io/_uploads/SJNAfl8Ra.png)

Run the nusactl grade do-002-3 command to assess the lab results.
nusactl grade do-002-3
![Screenshot (1176)](https://hackmd.io/_uploads/ryMXmlLCa.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Lab 2.4 : Docker Run - Part 3
Introduction
Execute in pod-[username]-node01

docker run (practice 05)

**1. Running mysql container with additional parameters.**
docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD=RAHASIA -e MYSQL_DATABASE=latihan05 -p 3306:3306 \
registry.adinusa.id/btacademy/mysql
![Screenshot (976)](https://hackmd.io/_uploads/rypgKORpa.png)

**2. Pull image phpmyadmin from harbor.**
docker pull registry.adinusa.id/btacademy/phpmyadmin:latest
![Screenshot (977)](https://hackmd.io/_uploads/S1__KORTa.png)

**3. Running phpmyadmin container and connect it with mysql container.**
docker run --name my-phpmyadmin -d --link my-mysql:db -p 8090:80 \
registry.adinusa.id/btacademy/phpmyadmin
![Screenshot (978)](https://hackmd.io/_uploads/rJcm9O0aT.png)

**4. Test browsing.**
open in browser http://10.10.10.11:8090 login with user: `root` dan password: `RAHASIA` 
![Screenshot (979)](https://hackmd.io/_uploads/ByI0cdRp6.png)

docker run (practice 06)

**1. Run ubuntu containers with names ubuntu1 & ubuntu2.**
docker run -dit --name ubuntu1 registry.adinusa.id/btacademy/ubuntu
![Screenshot (980)](https://hackmd.io/_uploads/Bk6b2FATT.png)
docker run -dit --name ubuntu2 registry.adinusa.id/btacademy/ubuntu
![Screenshot (981)](https://hackmd.io/_uploads/Hykj3KCp6.png)

**2. Display list container.**
docker ps
![Screenshot (982)](https://hackmd.io/_uploads/SyfAnY0TT.png)

**3. Pause container ubuntu.**
docker pause ubuntu1
docker pause ubuntu2
![Screenshot (983)](https://hackmd.io/_uploads/r1xX0KCa6.png)

**4. Check in list container if the container status is paused.**
docker ps
![Screenshot (984)](https://hackmd.io/_uploads/BkWI0tCTp.png)

**5. Check resource usage when the ubuntu container is paused.**
docker stats ubuntu1
![Screenshot (985)](https://hackmd.io/_uploads/rJVK0KC6T.png)
docker stats ubuntu2
![Screenshot (986)](https://hackmd.io/_uploads/S1ZAAF0pp.png)

**6. Unpause container ubuntu1.**
docker unpause ubuntu1
![Screenshot (987)](https://hackmd.io/_uploads/rJZBGcATa.png)

docker run (practice 07)

**1. Create database containers with limited specifications.**
docker container run -d --name ch6_mariadb --memory 256m --cpu-shares 1024 --cap-drop net_raw \
 -e MYSQL_ROOT_PASSWORD=test registry.adinusa.id/btacademy/mariadb:5.5
![Screenshot (988)](https://hackmd.io/_uploads/B1T_z5RpT.png)

**2. Create a wordpress container and connect it to the 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
![Screenshot (989)](https://hackmd.io/_uploads/SkoC79Rpp.png)

**3. Check logs, running process, and resource.**
docker logs ch6_mariadb
![Screenshot (991)](https://hackmd.io/_uploads/S1T6U90ap.png)
docker logs ch6_wordpress
![Screenshot (993)](https://hackmd.io/_uploads/BJUGpcA6p.png)
docker top ch6_mariadb
docker top ch6_wordpress
![Screenshot (994)](https://hackmd.io/_uploads/r1UP6cAaT.png)
docker stats ch6_mariadb
![Screenshot (995)](https://hackmd.io/_uploads/rJQkR9Ap6.png)
docker stats ch6_wordpress
![Screenshot (996)](https://hackmd.io/_uploads/HJtGA5R6a.png)

**4. Test browsing.**
Open in browser http://10.10.10.11 then complete the installation
![Screenshot (997)](https://hackmd.io/_uploads/BJbsR9Ap6.png)

# 3. Managing Docker Container
Managing the Life Cycle of Containers - Part 1

Docker Client Verbs
Docker memiliki sejumlah perintah yang bisa digunakan untuk membuat dan mengatur kontainer. Berikut adalah ringkasan perintah-perintah yang paling sering digunakan untuk mengubah status kontainer.
![image](https://hackmd.io/_uploads/H158FiRaa.png)

Selain itu, Docker juga menyediakan sejumlah perintah untuk mendapatkan informasi tentang kontainer yang sedang berjalan dan yang sudah berhenti. Berikut adalah ringkasan perintah-perintah yang paling sering digunakan untuk mengambil informasi terkait kontainer Docker.
![image](https://hackmd.io/_uploads/ByJdKiC6T.png)

Managing the Life Cycle of Containers - Part 2

Mengelola Kontainer
Docker menyediakan perintah-perintah berikut untuk mengelola kontainer:
**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 gambar, tetapi sebenarnya tidak terkait.
**IMAGE** Gambar 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 Network 
Pendahuluan Jaringan
Salah satu alasan kekuatan kontainer dan layanan Docker adalah kemampuannya untuk saling terhubung atau terhubung dengan beban kerja non-Docker. Kontainer dan layanan Docker tidak perlu tahu bahwa mereka dijalankan di Docker atau apakah rekan mereka juga menggunakan Docker. Baik host Docker Anda berjalan di Linux, Windows, atau keduanya, Anda bisa mengelolanya secara platform-agnostik dengan Docker.

Dalam pembahasan ini, akan didefinisikan beberapa konsep dasar tentang jaringan Docker untuk mempersiapkan Anda merancang dan men-deploy aplikasi agar bisa memanfaatkan kemampuan ini sepenuhnya.

- Driver Jaringan
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;
- 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
Introduction
Execute in pod-[username]-node01

**1. Create working directory.**
cd $HOME
mkdir -p latihan/latihan01-volume
cd latihan/latihan01-volume
![Screenshot (1000)](https://hackmd.io/_uploads/ByuZ7y1AT.png)

**2. Create file and container for data volume with name 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 
![Screenshot (1001)](https://hackmd.io/_uploads/B1Sdm1kAa.png)

**3. Mount the volume into the container.**
docker run --volumes-from my-volume registry.adinusa.id/btacademy/ubuntu ls /my-volume
![Screenshot (1002)](https://hackmd.io/_uploads/BJp6QJJCT.png)

**Run the nusactl grade do-003-1 command to assess the lab results.**
nusactl grade do-003-1
![Screenshot (1003)](https://hackmd.io/_uploads/H1T-EyJCT.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Lab 3.2: Mount Volume with NFS Server
Introduction
Execute in pod-[username]-node01

**1. Create working directory**
sudo mkdir -p /data/nfs-storage01/
![Screenshot (1004)](https://hackmd.io/_uploads/SJOANJkAT.png)

**2. Create the NFS Server with 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
![Screenshot (1005)](https://hackmd.io/_uploads/SkYfSyJRT.png)

Execute in pod-[username]-node02

**3. Install the necessary packages, mount the volume on the NFS client and then create a file to check out the volume.**
ssh 10.7.7.20
![Screenshot (1006)](https://hackmd.io/_uploads/Sy__SkyR6.png)
sudo apt install nfs-client -y
![Screenshot (1007)](https://hackmd.io/_uploads/SkR9r1kRp.png)
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
![Screenshot (1009)](https://hackmd.io/_uploads/r1Ry8kJRp.png)

sudo touch /mnt/file1.txt
sudo touch /mnt/file2.txt
exit
![Screenshot (1010)](https://hackmd.io/_uploads/ByUmIkJRT.png)

Execute in pod-[username]-node01
**4. Verification.**
ls /data/nfs-storage01/

Run the nusactl grade do-003-2 command to assess the lab results.
nusactl grade do-003-2
![Screenshot (1012)](https://hackmd.io/_uploads/B1MDIy1Ra.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Lab 3.3: Mount Volume with Read-only Mode
Execute in pod-[username]-node01

**1. Create docker volume**
docker volume create my-vol
![Screenshot (1013)](https://hackmd.io/_uploads/H115vJkCT.png)

**2. Display list docker volume.**
docker volume ls
![Screenshot (1014)](https://hackmd.io/_uploads/HJ1Qd1yRT.png)

**3. Display docker volume details.**
docker volume inspect my-vol
![Screenshot (1015)](https://hackmd.io/_uploads/SkABdJJR6.png)

**4. Running the container with volume read and write access.**
docker run -d --name=nginx-rwvol -v my-vol:/usr/share/nginx/html -p 4005:80 registry.adinusa.id/btacademy/nginx:latest
![Screenshot (1016)](https://hackmd.io/_uploads/ryQFOyJ0a.png)

**5. Display the IP Address of the container.**
docker inspect nginx-rwvol | jq -r '.[].NetworkSettings.IPAddress'
![Screenshot (1017)](https://hackmd.io/_uploads/Hk7XF11Ra.png)

**6. Test browsing to IP Address of the container.**
curl http://172.17.X.X
![Screenshot (1018)](https://hackmd.io/_uploads/H17vtyJR6.png)

**7. Create index.html file and move it to the source volume directory.**
sudo echo "This is from my-vol source directory" > index.html
sudo mv index.html /var/lib/docker/volumes/my-vol/_data
![Screenshot (1019)](https://hackmd.io/_uploads/BJj5FJy0T.png)

**8. Test browsing to IP Address of the container.**
curl http://172.17.X.X
![Screenshot (1020)](https://hackmd.io/_uploads/S1Wg5y1A6.png)

**9. Running container with volume read-only access.**
docker run -d --name=nginx-rovol -v my-vol:/usr/share/nginx/html:ro registry.adinusa.id/btacademy/nginx:latest
![Screenshot (1021)](https://hackmd.io/_uploads/S1i8511C6.png)

**10. View the nginx-rovol container details and pay attention to the Mode in Mounts section.**
docker inspect nginx-rovol | jq '.[].Mounts'
![Screenshot (1022)](https://hackmd.io/_uploads/S1FY5JJCp.png)

Run the nusactl grade do-003-3 command to assess the lab results.
nusactl grade do-003-3
![Screenshot (1023)](https://hackmd.io/_uploads/r1t05y1Rp.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Lab 3.4: Volume Driver
Introduction
Execute in pod-[username]-node02

**1. Create directory /share and Create index.html.**
sudo mkdir /share
sudo chmod 777 /share
echo "Hello Adinusa!" > /share/index.html
![Screenshot (1024)](https://hackmd.io/_uploads/r1_KiJJA6.png)

Execute in pod-[username]-node01

**2. Instal plugin sshfs and set plugin sshfs.**
docker plugin install --grant-all-permissions vieux/sshfs
![Screenshot (1025)](https://hackmd.io/_uploads/SyHCjkkAp.png)
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
![Screenshot (1026)](https://hackmd.io/_uploads/r1yd3kJAa.png)

**3. Creating docker volume with driver sshfs**
docker volume create --driver vieux/sshfs -o sshcmd=student@10.7.7.20:/share  -o allow_other sshvolume
![Screenshot (1027)](https://hackmd.io/_uploads/rkG63J1R6.png)

**4. Test running container with the volume.**
docker run -d --name=nginxtest-sshfs -p 8090:80 -v sshvolume:/usr/share/nginx/html registry.adinusa.id/btacademy/nginx:latest
![Screenshot (1028)](https://hackmd.io/_uploads/r1mG61yC6.png)

**5. Test browsing.**
docker ps
curl http://localhost:8090
![Screenshot (1029)](https://hackmd.io/_uploads/r10_6kk0p.png)

Run the nusactl grade do-003-4 command to assess the lab results.
nusactl grade do-003-4
![Screenshot (1030)](https://hackmd.io/_uploads/HJKcTykRp.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

**Lab 3.5: Default Bridge Network**
Execute in pod-[username]-node01

**1. Display a list of networks on the current docker network.**
sudo docker network ls
![Screenshot (1031)](https://hackmd.io/_uploads/rJvfAkkAa.png)

**2. Run 2 alpine container running 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
![Screenshot (1032)](https://hackmd.io/_uploads/H1G8011Ap.png)

**3. Create a new docker network and attach it to the alpine1 container.**
docker network create --driver bridge bridge1
docker network connect bridge1 alpine1
![Screenshot (1033)](https://hackmd.io/_uploads/HkGsCJ10T.png)

**4. Check the IP address of the alpine2 container.**
docker inspect alpine2  | jq -r '.[].NetworkSettings.IPAddress'
![Screenshot (1034)](https://hackmd.io/_uploads/BywRC1106.png)

5. Access to alpine1 container.
docker exec -it alpine1 sh
![Screenshot (1035)](https://hackmd.io/_uploads/SykMkeJ0p.png)

6. Display the IP address of container alpine1.
ip add
![Screenshot (1036)](https://hackmd.io/_uploads/B1_V1ekCp.png)

7. Ping test to the internet on container alpine1 (Success).
ping -c 3 8.8.8.8
![Screenshot (1038)](https://hackmd.io/_uploads/SJ5p1g1C6.png)

8. Ping test to IP Address of alpine2 container (Success).
ping -c 3 172.17.X.X
![Screenshot (1037)](https://hackmd.io/_uploads/SkScJxyC6.png)


9. Ping test to name of alpine2 container (failed).
ping -c 3 alpine2
![Screenshot (1039)](https://hackmd.io/_uploads/ryxQxeJRp.png)

10. Exit from container alpine1 without closing the shell Press Ctrl+P, Ctrl+Q.

Run the nusactl grade do-003-5 command to assess the lab results.
nusactl grade do-003-5
![Screenshot (1040)](https://hackmd.io/_uploads/rJPdglkC6.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

**Lab 3.6: Host Network**
Introduction
Execute in pod-[username]-node01

**1. Run the container from the nginx image with the network host.**
docker run -itd --network host --name my_nginx registry.adinusa.id/btacademy/nginx
![Screenshot (1041)](https://hackmd.io/_uploads/r1uZ-lkCp.png)

**2. Test browsing to localhost.**
curl http://localhost
![Screenshot (1042)](https://hackmd.io/_uploads/BkXdbe1Ap.png)

**3. Verification IP Address and bound port 80.**
ip add
sudo netstat -tulpn | grep :80
![Screenshot (1043)](https://hackmd.io/_uploads/Sk9ibg1CT.png)

Run the nusactl grade do-003-6 command to assess the lab results.
nusactl grade do-003-6
![Screenshot (1044)](https://hackmd.io/_uploads/rkA0ZekRa.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Creating Custom Docker Container Image
Docker images
What is Docker Images?
Gambar Docker adalah seperti "template" yang digunakan untuk membuat kontainer. Di sistem Linux, segala sesuatu dianggap sebagai berkas, termasuk sistem operasi itu sendiri. Jadi, gambar Docker pada dasarnya adalah seperti "paket" besar yang berisi semua yang diperlukan untuk menjalankan sebuah aplikasi dalam kontainer. Ini seperti memiliki "arsip" besar yang berisi semua komponen yang diperlukan, seperti berkas dan folder, yang saling "bertumpuk" untuk membentuk gambar lengkap.

The layered filesystem
Sistem berkas yang berlapis-lapis pada gambar kontainer adalah seperti memiliki beberapa "lapisan" yang saling "bertumpuk". Gambar Docker, yang merupakan template untuk kontainer, terdiri dari beberapa lapisan yang saling terkait. Lapisan pertama, yang juga disebut sebagai lapisan dasar, merupakan dasar dari gambar tersebut. Ini mirip dengan menyusun beberapa "puzzle" yang membentuk gambar keseluruhan.
![image](https://hackmd.io/_uploads/HynH7xy0p.png)
Gambar sebagai tumpukan lapisan Setiap lapisan individual berisi berkas dan folder. Setiap lapisan hanya berisi perubahan pada sistem berkas terhadap lapisan yang mendasarinya. Sebuah driver penyimpanan menangani detail terkait cara lapisan-lapisan ini berinteraksi satu sama lain. Berbagai driver penyimpanan tersedia yang memiliki kelebihan dan kekurangan dalam situasi yang berbeda.

Lapisan-lapisan dari sebuah gambar kontainer semuanya tidak dapat diubah. Tidak dapat diubah berarti bahwa setelah dibuat, lapisan tersebut tidak pernah bisa diubah. Satu-satunya operasi yang memengaruhi lapisan adalah penghapusan fisiknya. Kekakuan dari lapisan-lapisan ini penting karena membuka banyak peluang, seperti yang akan kita lihat.
Pada gambar berikut, kita dapat melihat bagaimana sebuah gambar kustom untuk aplikasi web, menggunakan Nginx sebagai server web, bisa terlihat.
![image](https://hackmd.io/_uploads/S1Yqmey06.png)
Sebuah contoh gambar kustom berbasis Alpine dan Nginx
Lapisan dasar kita di sini terdiri dari distribusi Alpine Linux. Kemudian, di atasnya, kita memiliki lapisan Add Nginx di mana Nginx ditambahkan di atas Alpine. Akhirnya, lapisan ketiga berisi semua berkas yang membentuk aplikasi web, seperti berkas HTML, CSS, dan JavaScript.
Seperti yang telah disebut sebelumnya, setiap gambar dimulai dengan gambar dasar. Biasanya, gambar dasar ini adalah salah satu gambar resmi yang ditemukan di Docker Hub, seperti distro Linux, Alpine, Ubuntu, atau CentOS. Namun, juga memungkinkan untuk membuat gambar dari awal.

**Docker Hub adalah registri publik untuk gambar kontainer. Ini adalah pusat utama yang sangat cocok untuk berbagi gambar kontainer publik.**

Setiap lapisan hanya berisi delta perubahan terhadap set lapisan sebelumnya. Isi dari setiap lapisan dipetakan ke folder khusus pada sistem host, yang biasanya merupakan subfolder dari /var/lib/docker/.
Karena lapisan tidak dapat diubah, mereka dapat dicache tanpa pernah menjadi usang. Ini adalah keuntungan besar, seperti yang akan kita lihat.

The writable container layer
Seperti yang telah kita diskusikan, sebuah gambar kontainer terdiri dari tumpukan lapisan yang tidak dapat diubah atau hanya bisa dibaca. Ketika Docker Engine membuat sebuah kontainer dari gambar tersebut, ia menambahkan sebuah lapisan kontainer yang dapat ditulis di atas tumpukan lapisan yang tidak dapat diubah ini. Sekarang tumpukan kita terlihat seperti berikut:
![image](https://hackmd.io/_uploads/HJ7YVlkAT.png)
Lapisan Kontainer ditandai sebagai baca/tulis. Keuntungan lain dari ketidakbisaan berubahnya lapisan gambar adalah bahwa mereka dapat dibagikan di antara banyak kontainer yang dibuat dari gambar ini. Yang dibutuhkan hanyalah sebuah lapisan kontainer yang tipis dan dapat ditulis untuk setiap kontainer, seperti yang ditunjukkan dalam tangkapan layar berikut:
![image](https://hackmd.io/_uploads/SyY6NlkA6.png)
Teknik ini, tentu saja, menghasilkan pengurangan yang sangat besar dalam sumber daya yang digunakan. Selain itu, ini membantu mengurangi waktu pemuatan sebuah kontainer karena hanya perlu membuat sebuah lapisan kontainer yang tipis setelah lapisan gambar telah dimuat ke dalam memori, yang hanya terjadi untuk kontainer pertama.

**Docker Registry**
An overview of Docker Registry
Pada bagian ini, kita akan membahas tentang Docker Registry. Docker Registry adalah sebuah aplikasi yang bisa kamu jalankan di mana saja dan digunakan untuk menyimpan gambar Dockermu. Kita akan membandingkan antara Docker Registry dan Docker Hub, dan membahas bagaimana cara memilih di antara keduanya. Di akhir bagian ini, kamu akan belajar bagaimana cara menjalankan Docker Registry sendiri dan menentukan apakah itu sesuai untukmu.
![image](https://hackmd.io/_uploads/ByF8BeyR6.png)
**source : thecustomizewindows.com**
Docker Registry adalah aplikasi sumber terbuka yang bisa kamu gunakan untuk menyimpan gambar Docker di platform pilihanmu. Ini memungkinkan kamu untuk menyimpan gambar-gambar tersebut secara pribadi atau membagikannya sesuai kebutuhan.

Docker Registry cocok digunakan jika kamu ingin memiliki registry sendiri tanpa harus membayar fitur-fitur pribadi Docker Hub. Sekarang, mari kita bandingkan Docker Hub dan Docker Registry untuk membantu kamu memilih platform yang sesuai untuk menyimpan gambar-gambarmu.

Fitur Docker Registry:
- Kamu bisa mengelola registry sendiri dari mana kamu bisa menyajikan semua repositori sebagai pribadi, publik, atau campuran dari keduanya.
- Kamu bisa menyesuaikan skala registry sesuai kebutuhan, berdasarkan jumlah gambar yang kamu hosting atau jumlah permintaan pull yang kamu layani.
- Semuanya bisa dijalankan melalui baris perintah.

Docker Hub memberikan:
- Antarmuka berbasis GUI yang mudah dipakai untuk mengelola gambar-gambar kamu.
- Tempat di cloud yang sudah disiapkan untuk menangani gambar-gambar publik dan/atau pribadi.
- Kamu tidak perlu repot mengelola server yang meng-host semua gambar-gambarmu.

Docker Hub
Docker Hub adalah cara termudah untuk membuat, mengelola, dan mengirimkan aplikasi kontainer timmu.
Repositori Docker Hub memungkinkan kamu berbagi gambar kontainer dengan tim, pelanggan, atau komunitas Docker secara luas.
Gambar Docker dapat diunggah ke Docker Hub melalui perintah docker push. Setiap repositori Docker Hub dapat menyimpan banyak gambar Docker.

# Lab 4.1: Exploring Dockerfile
Introduction
Execute in pod-[username]-node01

Dockerfile (practice 01)

**1. Clone repository for training.**
git clone https://github.com/spkane/docker-node-hello.git \
    --config core.autocrlf=input latihan01
![Screenshot (1045)](https://hackmd.io/_uploads/Hk4s8lJAp.png)
**2. Enter the directory.**
cd latihan01
![Screenshot (1046)](https://hackmd.io/_uploads/HkQCUlkAp.png)
**3. Create an image of the previous repository and name it node-exercise01.**
docker build -t node-latihan01 .
![Screenshot (1047)](https://hackmd.io/_uploads/HJYbPekA6.png)
**4. Run the container with the previously created image and expose the port to 8080.**
docker run -d --rm --name node-latihan01 -p 8080:8080 node-latihan01
![Screenshot (1048)](https://hackmd.io/_uploads/r1L6_gyCT.png)
**5. Try access container.**
curl localhost:8080
![Screenshot (1049)](https://hackmd.io/_uploads/Hy21Fe1Ra.png)

Dockerfile (practice 02)

1. Create latihan02 directory.
cd $HOME
mkdir latihan02
cd latihan02
![Screenshot (1050)](https://hackmd.io/_uploads/SyYFtl10a.png)
2. Create Dockerfile as below.
vim Dockerfile
...
#Use whalesay image as a base image
FROM registry.adinusa.id/btacademy/whalesay:latest

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

#Execute command
CMD /usr/games/fortune -a | cowsay
...
![Screenshot (1055)](https://hackmd.io/_uploads/B1C1TgyRT.png)
3. Create image From Dockerfile.
docker build -t docker-whale .
![Screenshot (1054)](https://hackmd.io/_uploads/HkhH3eJ06.png)
4. Display the image that has been created.
docker image ls
![Screenshot (1056)](https://hackmd.io/_uploads/ByJrpxJRp.png)
5. Test run the image.
docker run docker-whale
![Screenshot (1057)](https://hackmd.io/_uploads/H1IdTxkA6.png)
6. Display the container.
docker ps
docker container ls -a
![Screenshot (1058)](https://hackmd.io/_uploads/rkQo6ly0a.png)

Run the nusactl grade do-004-1 command to assess the lab results.
nusactl grade do-004-1
![Screenshot (1059)](https://hackmd.io/_uploads/Bk47kbk06.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Lab 4.2: Exploring Dockerfile (Flask Apps)
Introduction
Execute in pod-[username]-node01

Dockerfile (practice 03)
**1. If you don't have a Docker ID, register at https://hub.docker.com/signup.**

**2. Login with Docker ID**
docker login

**3. Create directory latihan03.**
cd $HOME
mkdir latihan03
cd latihan03
![Screenshot (1060)](https://hackmd.io/_uploads/Ska3bWkA6.png)

**4. Create file flask.**
vim app.py
...
from flask import Flask
app = Flask(__name__)

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


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')
...
![Screenshot (1061)](https://hackmd.io/_uploads/SJ_czZkC6.png)

**5. Create file requirements.txt.**
vi requirements.txt
...
Flask==0.10.1
Werkzeug==1.0.0
Jinja2==2.8.1
MarkupSafe==1.1.1
itsdangerous==1.1.0
...
![Screenshot (1062)](https://hackmd.io/_uploads/S1YJVbJR6.png)

**6. Creating Dockerfile.**
vim Dockerfile
...
FROM registry.adinusa.id/btacademy/ubuntu:16.04
RUN mkdir /app
RUN apt-get update -y && \
        apt-get install python-pip python-dev -y

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

WORKDIR /app
RUN pip install -r requirements.txt

ENTRYPOINT ["python"]
CMD ["app.py"]
... 
![Screenshot (1063)](https://hackmd.io/_uploads/SyZrNbk0a.png)

**7. Create image from Dockerfile.**
docker build -t flask-latihan03 .
![Screenshot (1064)](https://hackmd.io/_uploads/BkadN-JR6.png)

**8. Tag image with docker username**.
docker tag flask-latihan03 [usernamedocker]/flask-latihan03:latest
![Screenshot (1065)](https://hackmd.io/_uploads/BJ71LW1Ap.png)

**9. Push image to dockerhub.**
docker push [usernamedocker]/flask-latihan03:latest
![Screenshot (1066)](https://hackmd.io/_uploads/HJEmIZk0a.png)

**10. Running the image .**
docker run -d -p 5000:5000 --name flask03 [usernamedocker]/flask-latihan03
![Screenshot (1067)](https://hackmd.io/_uploads/r1RlFW1CT.png)

**11. Test browsing.**
curl localhost:5000
![Screenshot (1068)](https://hackmd.io/_uploads/B1yHtbkAa.png)

Run the nusactl grade do-004-2 command to assess the lab results.
nusactl grade do-004-2
![Screenshot (1069)](https://hackmd.io/_uploads/BkYFFWJRp.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Docker Compose
Introducing Docker Compose
![image](https://hackmd.io/_uploads/By_yvEkA6.png)
Docker Compose adalah alat yang disediakan oleh Docker untuk menjalankan dan mengatur kontainer di satu host Docker. Ini digunakan untuk pengembangan, integrasi berkelanjutan, pengujian otomatis, dan lain-lain.

File konfigurasi Docker Compose menggunakan format YAML dan biasanya disebut docker-compose.yml. File ini digunakan untuk menjelaskan dan menjalankan aplikasi yang dikontainerisasi, mungkin dengan beberapa kontainer.

Pendekatan deklaratif berarti kita menyatakan apa yang kita inginkan dari aplikasi tanpa perlu menentukan langkah-langkah tertentu. Ini berbeda dengan pendekatan imperatif, yang memerintahkan sistem langkah demi langkah.

Docker merekomendasikan pendekatan deklaratif karena memberikan kemudahan dalam mengelola aplikasi yang dikontainerisasi. Docker Compose mengikuti pendekatan ini dalam konfigurasinya.

**Lab 5.1: Using Docker Compose**
Execute in pod-[username]-node01 & pod-[username]-node02

Install Compose

**1. Download & Install Compose.**
![Screenshot (1108)](https://hackmd.io/_uploads/HJb5u5-RT.png)
sudo chmod 755 $DESTINATION

**2. Test installation Compose.**
docker-compose --version
![Screenshot (1072)](https://hackmd.io/_uploads/Hy_61BkAa.png)
![Screenshot (1071)](https://hackmd.io/_uploads/HydpyHJRp.png)

Execute in pod-[username]-node01

**3. Create a directory my_wordpress and go to the directory**
cd $HOME
mkdir -p latihan/my_wordpress
cd latihan/my_wordpress
![Screenshot (1073)](https://hackmd.io/_uploads/BJOW7H1C6.png)

**4. create docker-compose file.**
vim 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:
![Screenshot (1074)](https://hackmd.io/_uploads/SyiUXrJ06.png)

**5. Run compose.**
docker-compose up -d
![Screenshot (1075)](https://hackmd.io/_uploads/Ske9XrkRT.png)

**6. Display the list of containers and test browsing to the wordpress page that has been created**
docker container ls

# Docker Continous Integration (CI)

**CI Using Docker**
Continuous Integration (CI) adalah praktik dimana para pengembang secara rutin menggabungkan kode mereka ke dalam satu tempat, dan kemudian kode tersebut secara otomatis diperiksa untuk mendeteksi masalah. CI membantu dalam menemukan bug lebih cepat dan mempermudah untuk memperbaikinya.

CI/CD menggabungkan proses pengembangan dengan pengujian, memungkinkan pengembang untuk bekerja sama dalam membangun dan menguji kode mereka. Docker, yang dapat berintegrasi dengan alat-alat seperti Jenkins dan GitHub, memungkinkan pengembang untuk mengirimkan dan menguji kode mereka secara otomatis. Ini membantu menyederhanakan proses pengembangan dan menghemat waktu, sambil memungkinkan pengembang untuk tetap produktif pada proyek-proyek lain.
![image](https://hackmd.io/_uploads/rk_FNBJAp.png)
1. Pengembang mengirimkan sebuah commit ke GitHub. 
2. GitHub menggunakan webhook untuk memberi tahu Jenkins tentang pembaruan tersebut. 
3. Jenkins menarik repositori GitHub, termasuk Dockerfile yang menjelaskan gambar, serta kode aplikasi dan pengujian. 
4. Jenkins membangun sebuah gambar Docker pada node slave Jenkins. 
5. Jenkins menginstansiasi kontainer Docker pada node slave, dan menjalankan pengujian yang sesuai. 6.Jika pengujian berhasil, gambar tersebut kemudian diunggah ke Dockerhub atau Docker Trusted Registry.
Reference : https://collabnix.com/5-minutes-to-continuous-integration-pipeline-using-docker-jenkins-github-on-play-with-docker-platform/

# Docker Hub Automated Build
Docker Hub dapat secara otomatis membangun gambar dari kode sumber dalam repositori eksternal dan secara otomatis mendorong gambar yang dibangun ke repositori Docker.

Ketika Anda mengatur pembangunan otomatis (autobuilds), Anda membuat daftar cabang dan tag yang ingin Anda jadikan gambar Docker. Setiap kali Anda mengirimkan kode ke salah satu cabang tersebut di repositori sumber (seperti di GitHub) yang sesuai dengan salah satu tag gambar yang terdaftar, sebuah pembangunan baru akan dipicu menggunakan webhook. Pembangunan baru ini akan menghasilkan sebuah gambar Docker yang kemudian akan didorong ke registry Docker Hub.

Pembangunan otomatis ini memungkinkan Anda untuk membuat gambar secara otomatis dari konteks pembangunan yang disimpan di dalam repositori. Konteks pembangunan ini biasanya terdiri dari Dockerfile dan file-file lain yang diperlukan. Ini memiliki keuntungan, antara lain:

1. Gambar dibangun sesuai dengan spesifikasi yang telah Anda tentukan.
2. Dockerfile tersedia untuk semua orang yang memiliki akses ke repositori Docker Hub Anda.
3. Repositori Anda akan selalu terbaru dengan perubahan kode yang otomatis.

Pembangunan otomatis ini mendukung baik repositori publik maupun pribadi di GitHub dan Bitbucket.

Build Statuses
**Queued**: Sedang menunggu gambar dibangun.

**Building**: Proses pembangunan gambar sedang berlangsung.

**Success**: Gambar telah berhasil dibangun tanpa masalah.

**Error**: Terjadi masalah dengan gambar Anda.
![image](https://hackmd.io/_uploads/HyDGUSk0p.png)

# Docker Swarm & Portainer

**What is Swarm?**
Swarm adalah kumpulan komputer yang menjalankan Docker, baik itu satu atau lebih mesin. Dengan mode swarm, Docker mendapat kemampuan orkestrasi dan pengelompokan bawaan. Fitur-fitur seperti penyeimbangan beban dan pengelolaan siklus hidup layanan termasuk di dalamnya. Mode swarm tidak aktif secara default saat menjalankan kontainer dengan perintah Docker, tetapi jika diaktifkan, Anda dapat mengelola layanan daripada kontainer secara langsung.

**About Docker Swarm**
Docker Swarm adalah sekelompok mesin fisik atau virtual yang menjalankan aplikasi Docker dan telah dikonfigurasi untuk bergabung bersama dalam sebuah klaster. Setelah sekelompok mesin dikelompokkan bersama, Anda masih dapat menjalankan perintah Docker seperti biasa, tetapi sekarang perintah tersebut akan dilaksanakan oleh mesin-mesin dalam klaster Anda. Aktivitas klaster dikontrol oleh pengelola swarm, dan mesin yang telah bergabung dalam klaster disebut sebagai node.
![image](https://hackmd.io/_uploads/SkyvPByCp.png)
Feature Docker Swarm:
* Manajemen klaster terintegrasi dengan Docker Engine: Gunakan CLI Docker Engine untuk membuat klaster dari Docker Engines di mana Anda dapat mendeploy layanan aplikasi tanpa perlu perangkat lunak orkestrasi tambahan.

* Desain terdesentralisasi: Docker Engine menangani spesialisasi pada waktu runtime, memungkinkan Anda mendeploy kedua jenis node (manajer dan pekerja) dari gambar disk tunggal.

* Model layanan deklaratif: Docker Engine menggunakan pendekatan deklaratif untuk mendefinisikan keadaan layanan dalam tumpukan aplikasi Anda.

* Penskalaan: Anda dapat mendeklarasikan jumlah tugas untuk setiap layanan dan swarm manager secara otomatis menyesuaikan jumlah tugas sesuai kebutuhan.

* Rekonsiliasi keadaan yang diinginkan: Swarm manager memantau keadaan klaster dan menyelesaikan perbedaan antara keadaan aktual dan diinginkan.

* Jaringan multi-host: Anda dapat menentukan jaringan overlay untuk layanan Anda dan swarm manager secara otomatis menetapkan alamat ke kontainer.

* Penemuan layanan: Setiap layanan dalam swarm diberi nama DNS unik dan dipilihkan beban kontainer yang berjalan.

* Penyeimbangan beban: Anda dapat mengekspos port layanan ke penyeimbang beban eksternal dan menentukan cara mendistribusikan kontainer layanan antara node secara internal.

* Keamanan secara default: Setiap node menerapkan otentikasi mutual TLS dan enkripsi untuk mengamankan komunikasi antar node.

* Pembaruan bertahap: Anda dapat menerapkan pembaruan layanan ke node secara bertahap dengan mengontrol penundaan antara penyebaran layanan ke setiap set node.

# Portainer for Docker

**About Portainer**
Portainer adalah alat manajemen kontainer yang populer dengan banyak pengguna dan dukungan GitHub yang luas. Ini memungkinkan Anda mengelola kontainer Docker dan klaster Swarm dengan antarmuka yang ringan dan sederhana. Portainer dapat berjalan di berbagai platform dan memudahkan manajemen sumber daya Docker Anda seperti kontainer, gambar, dan jaringan. Dengan antarmuka yang mudah dipahami, Portainer cocok untuk administrator dan pengembang dengan berbagai tingkat keahlian.
![image](https://hackmd.io/_uploads/rJqwFSJAp.png)

**Portainer Is Available In Two Editions:**
* **Portainer Community Edition (CE)** adalah fondasi kami. Dengan lebih dari setengah juta pengguna reguler, CE adalah seperangkat alat sumber terbuka yang kuat yang memungkinkan Anda dengan mudah membangun dan mengelola kontainer dalam Docker, Docker Swarm, Kubernetes, dan Azure ACI.

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

**Why Portainer?**
Portainer menyediakan antarmuka yang mudah dipahami dan praktik terbaik yang terkode untuk membantu organisasi mengadopsi kontainer dengan cepat dan efisien.

Fitur-fitur:
* Mengurangi kompleksitas operasional dengan manajemen multi-klaster yang mudah.

* Membantu mengisi kesenjangan keterampilan dengan antarmuka pengguna yang intuitif.

* Memastikan penerapan praktik terbaik cloud-native dengan template desain dan konfigurasi default.

* Menyediakan manajemen akses, izin, dan pencatatan aktivitas secara sentral.

Mendukung Docker, Swarm, Nomad, dan Kubernetes di berbagai lingkungan seperti Data Center, Cloud, Edge Network, atau Perangkat IIoT.

# Lab 7.1 - Create Swarm
Introduction
Execute in pod-[username]-node01

Note: If there is a [username], change it to your username. If there is [X] replace with ip address of 2nd octet.

**1. Initialization Docker Swarm**
docker swarm init --advertise-addr 10.7.7.10
![Screenshot (1076)](https://hackmd.io/_uploads/B1zgoryCT.png)

Execute in pod-[username]-node02

**2. Copy command docker join**
docker swarm join --token [TOKEN] 10.7.7.10:2377
![Screenshot (1077)](https://hackmd.io/_uploads/HJQsoHJA6.png)

execute in pod-[username]-node01

**3. Check if node02 already join**
docker node ls
![Screenshot (1078)](https://hackmd.io/_uploads/SJsG2SkAa.png)

Run the nusactl grade do-007-1 command to assess the lab results.
nusactl grade do-007-1
![Screenshot (1079)](https://hackmd.io/_uploads/ryNHhHyCa.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Lab 7.2 - Deploy Service to Swarm
Introduction
Execute in node pod-[username]-node01

Note: If there is a [username], change it to your username. If there is [X] replace with ip address of 2nd octet.

**1. Create Service Nginx with 2 replica and expose port to 80**
docker service create --name web --replicas 2 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
![Screenshot (1080)](https://hackmd.io/_uploads/SkDs2S1Rp.png)

**2. Check Service Running Correctly in all node**
docker service ls
![Screenshot (1081)](https://hackmd.io/_uploads/r1Zv6SkAa.png)

**3. Test Browsing From node01 and node02**
curl http://10.XX.XX.10
curl http://10.XX.XX.20
Note: If the configuration is correct there will show nginx default page from node01 and node02
![Screenshot (1082)](https://hackmd.io/_uploads/S1m9pH1RT.png)
![Screenshot (1083)](https://hackmd.io/_uploads/Hyr6aHJCp.png)

**4. To check information about the service**
docker service inspect --pretty web
![Screenshot (1084)](https://hackmd.io/_uploads/HJezCSk0p.png)

**5. if we want to check where the service is running**
docker service ps web
![Screenshot (1085)](https://hackmd.io/_uploads/rycUCHyCa.png)

**6. Create container with limit cpu and limit Memory**
docker service create --name [username] --reserve-cpu 1 --limit-cpu 1 \
![Screenshot (1086)](https://hackmd.io/_uploads/Hy4pABkAa.png)

**7. Check the container Spesification**
docker service inspect --pretty [username]
![Screenshot (1087)](https://hackmd.io/_uploads/r1yMyI106.png)

Run the nusactl grade do-007-2 command to assess the lab results.
nusactl grade do-007-2
![Screenshot (1088)](https://hackmd.io/_uploads/ByyryI1Ra.png)

**Lab 7.3 - Docker swarm Scale & Update**

Introduction
Execute in node pod-[username]-node01

**1. Create Service Nginx with 3 replica**
docker service create --name web2 --replicas 3 -p 80:80 registry.adinusa.id/btacademy/nginx:latest
![Screenshot (1089)](https://hackmd.io/_uploads/rya2yL106.png)

**2. We can change the replica of the service**
docker service scale web2=1
![Screenshot (1090)](https://hackmd.io/_uploads/BkMgx81A6.png)

**3. check if replica already change**
docker service ls
docker service ps web2
![Screenshot (1091)](https://hackmd.io/_uploads/B1MXl8JRT.png)

**4. Docker swarm can rolling update the service**
docker service update --image sistyo/myweb web2
docker service inspect --pretty web2
![Screenshot (1093)](https://hackmd.io/_uploads/SJRWGIJCT.png)

Run the nusactl grade do-007-3 command to assess the lab results.
nusactl grade do-007-3
![Screenshot (1094)](https://hackmd.io/_uploads/S11LMIkRp.png)

# Lab 7.4 - Install Portainer and configuration

Introduction
Execute in node pod-[username]-node01

**1. Install Portainer In 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
![Screenshot (1096)](https://hackmd.io/_uploads/H1mGmL1RT.png)

**2. Access Portainer Dashboard**
Open browser and access 10.10.10.11:9000
![Screenshot (1097)](https://hackmd.io/_uploads/BJV8YLyR6.png)

Run the nusactl grade do-007-4 command to assess the lab results.
nusactl grade do-007-4
![Screenshot (1098)](https://hackmd.io/_uploads/HydtK8kR6.png)

# Lab 7.5 - Running Container from Portainer

Introduction

**1. Access Portainer dashboard trough SSH tunnel**
http://10.10.10.11:9000
**2. Running Container**

* Select Home -> node02
* Click Containers -> + Add Container
* Fill the name Column with [username]-web
* Fill the Image Coloumn with nginx:latest
* Click Publish a new network port -> Fill host coloumn 8080 and container coloumn 80
* Node pod-username-node02
* Click Deploy the Container

**3. There will be a notification on the top right side after deploying the container, the results can be seen from the Containers menu.**

**4. We can check the logs from container, Inspect container, Stats Container, Access Console Container From Quick Actions Menu**

**5. Access the container**
http://10.10.10.12:8080

# Logging Driver

Driver logging adalah fitur dalam Docker yang membantu Anda melihat informasi dari kontainer yang berjalan. Setiap Docker memiliki driver logging default. Secara otomatis, Docker menggunakan driver logging json-file, yang menyimpan log kontainer dalam format JSON. Anda juga dapat menggunakan plugin driver logging untuk opsi lainnya.

| Tip: Gunakan driver logging "local" untuk mencegah kehabisan ruang disk.

| Secara default, Docker tidak melakukan rotasi log, yang dapat menyebabkan file log json-file memakan banyak ruang disk jika kontainer menghasilkan banyak output. 

| Docker masih menggunakan json-file sebagai default untuk mempertahankan kompatibilitas dengan versi lama dan saat digunakan dengan Kubernetes. 

| Untuk penggunaan lain, disarankan menggunakan driver logging "local" karena melakukan rotasi log secara default dan menggunakan format file yang lebih efisien.

# Lab 8.1: Configuring Logging Driver
Introduction
Execute in pod-[username]-node01

**1. Create daemon.json file.**
sudo vim /etc/docker/daemon.json
...
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "100"
  }
}
...
![Screenshot (1101)](https://hackmd.io/_uploads/Bkf-0IZR6.png)

**2. Restart Daemon dan Docker.**
sudo systemctl daemon-reload
sudo systemctl restart docker
![Screenshot (1102)](https://hackmd.io/_uploads/HkWQRL-Aa.png)

**3. Run container.**
docker run --log-driver json-file --log-opt max-size=10m registry.adinusa.id/btacademy/alpine echo hello world
![Screenshot (1103)](https://hackmd.io/_uploads/S1evJwZ0a.png)

**4. Check the logs in the docker directory.**
![Screenshot (1107)](https://hackmd.io/_uploads/HkH_P9-AT.png)
OR
sudo cat /var/lib/docker/containers/CONTAINER/xxx-json.log
![Screenshot (1104)](https://hackmd.io/_uploads/HyYcy9-Ra.png)

Run the nusactl grade do-008-1 command to assess the lab results.
nusactl grade do-008-1
![Screenshot (1105)](https://hackmd.io/_uploads/H1M3ycZCT.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Health Check
Instruksi HEALTHCHECK dalam Docker memberitahu Docker cara memeriksa apakah kontainer masih berfungsi dengan baik. Misalnya, dapat mendeteksi jika server web terjebak dalam loop tak berujung. Ketika kontainer memiliki pemeriksaan kesehatan, ia memiliki status kesehatan tambahan. Statusnya bisa 'mulai', 'sehat', atau 'tidak sehat'.

Anda dapat menentukan opsi seperti berapa sering pemeriksaan dilakukan, berapa lama pemeriksaan diizinkan berjalan, dan berapa kali kontainer diberi kesempatan sebelum dianggap 'tidak sehat'.

Satu-satunya instruksi HEALTHCHECK di Dockerfile Anda harus menjadi yang terakhir. Ini bisa berisi perintah yang akan dijalankan di dalam kontainer untuk memeriksa kesehatannya. Hasil dari perintah ini akan menentukan status kesehatan kontainer: 'sukses' jika sehat dan 'tidak sehat' jika tidak.

Jadi, dengan menggunakan instruksi HEALTHCHECK, Anda dapat mengawasi kesehatan kontainer Docker dengan lebih baik, memastikan bahwa aplikasi di dalamnya berjalan dengan baik.

# Lab 9.1: Health Check
Introduction
Execute in node pod-[username]-node01

Health Check practice 01

**1. Create working direktori.**
cd $HOME
mkdir hc-latihan01
cd hc-latihan01
![Screenshot (1129)](https://hackmd.io/_uploads/H1_LUFECT.png)

**2. Create Dockerfile.**
vim Dockerfile
...
FROM registry.adinusa.id/btacademy/docker-http-server:health
HEALTHCHECK --interval=1s --retries=3 \
    CMD curl --fail http://localhost:80/ || exit 1
...
![Screenshot (1130)](https://hackmd.io/_uploads/B1eFPY4Ap.png)

**3. Create image from dockerfile.**
docker build -t http-healthcheck .
![Screenshot (1131)](https://hackmd.io/_uploads/H1DMuKVCT.png)

**4. Run image.**
docker run -d -p 80:80 --name http-healthcheck http-healthcheck
![Screenshot (1132)](https://hackmd.io/_uploads/HkVIuYVC6.png)

**5. Check image.**
docker ps
#check the status section
![Screenshot (1133)](https://hackmd.io/_uploads/Byzj_tECp.png)

**6. Check with curl.**
curl http://localhost/
#then accessible
![Screenshot (1134)](https://hackmd.io/_uploads/ByYltK4C6.png)

**7. Check for unhealthy.**
curl http://localhost/unhealthy
![Screenshot (1135)](https://hackmd.io/_uploads/S1_HtYN0p.png)

**8. Check the docker container status.**
docker container ls
![Screenshot (1136)](https://hackmd.io/_uploads/rkokqtNAp.png)

**9. Check with curl.**
curl http://localhost/
![Screenshot (1137)](https://hackmd.io/_uploads/Hk089F4Aa.png)

Health Check practice 02

**1. Create a new directory.**
cd $HOME
mkdir hc-latihan02
cd hc-latihan02
![Screenshot (1146)](https://hackmd.io/_uploads/Bk8XyiNAp.png)

**2. Create server.js file.**
vim 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);
...
![Screenshot (1148)](https://hackmd.io/_uploads/SkaqyoV0T.png)

**3. Create Dockerfile.**
vim 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"]
...
![Screenshot (1149)](https://hackmd.io/_uploads/r1l01oN0T.png)

**4. Create image from dockerfile.**
docker build -t node-server .
![Screenshot (1150)](https://hackmd.io/_uploads/rkOges4C6.png)

**5. Run image.**
docker run -d --name nodeserver -p 8080:8080 -p 8081:8081 node-server
![Screenshot (1152)](https://hackmd.io/_uploads/B1Owmo40a.png)

**6. Check container.**
curl 127.0.0.1:8080
docker ps 
docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
![Screenshot (1151)](https://hackmd.io/_uploads/rkcamiE0a.png)

**7. Check container.**
curl 127.0.0.1:8081
docker ps 
docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
![Screenshot (1153)](https://hackmd.io/_uploads/HyzeNj4Ra.png)

**8. Check Container.**
curl 127.0.0.1:8081
docker ps
docker inspect --format "{{ json .State.Health }}" nodeserver | jq .
![Screenshot (1154)](https://hackmd.io/_uploads/BJDX4j40T.png)

Run the nusactl grade do-009-1 command to assess the lab results.
nusactl grade do-009-1
![Screenshot (1155)](https://hackmd.io/_uploads/rJjruiNCa.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Security
Ada empat area utama yang perlu dipertimbangkan saat meninjau keamanan Docker:

* Keamanan intrinsik dari kernel dan dukungannya terhadap namespaces dan cgroups.
* Permukaan serangan dari daemon Docker itu sendiri.
* Celah dalam profil konfigurasi kontainer, baik secara default maupun saat disesuaikan oleh pengguna.
* Fitur keamanan "pengerasan" dari kernel dan bagaimana interaksinya dengan kontainer.

**Docker Security**
Docker memiliki beberapa area penting yang perlu dipertimbangkan untuk keamanan:

Kernel Linux dan Penggunaan Namespaces serta Cgroups: Saat Anda menjalankan kontainer Docker, Docker menggunakan fitur kernel seperti namespaces dan cgroups untuk memberikan isolasi dan pengaturan sumber daya. Ini memastikan bahwa proses dalam kontainer tidak bisa melihat atau mempengaruhi proses di kontainer lain atau di host.

Keamanan Daemon Docker: Daemon Docker adalah komponen utama yang menjalankan kontainer. Penting untuk memastikan bahwa daemon hanya diakses oleh pengguna yang dipercayai, karena daemon memerlukan hak akses root.

Profil Konfigurasi Kontainer: Docker memiliki pengaturan default untuk mengontrol apa yang bisa dilakukan kontainer. Ini termasuk pengaturan untuk hak akses root dalam kontainer dan penggunaan kemampuan sistem.

Pengerasan Kernel dan Interaksinya dengan Kontainer: Kernel Linux memiliki banyak fitur keamanan seperti AppArmor, SELinux, dan GRSEC yang bisa digunakan bersama Docker untuk menambahkan lapisan keamanan tambahan.

Dengan memahami dan mengelola aspek-aspek ini, Anda dapat meningkatkan keamanan lingkungan Docker Anda. Selalu ada opsi untuk mengaktifkan fitur keamanan tambahan seperti AppArmor atau SELinux, dan pastikan untuk menjalankan Docker dengan konfigurasi yang aman.

**CIS Docker Benchmark**

CIS membuat aturan terbaik untuk melindungi dari serangan siber. Mereka menggunakan pendapat banyak orang untuk menentukan aturan keamanan. Salah satu alat populer mereka adalah CIS Benchmarks.

Anda bisa gunakan CIS Benchmark untuk Docker untuk pastikan kontainer dan runtime Docker Anda diatur dengan aman. Ada alat gratis dan berbayar yang bisa cek otomatis Docker Anda terhadap aturan CIS untuk temukan konfigurasi yang berpotensi berbahaya.

Meski CIS Benchmark untuk Docker memberi banyak cek berguna, Anda sebaiknya lihat itu sebagai titik awal. Anda perlu tambahkan langkah-langkah keamanan tambahan, seperti batasan sumber daya dan memastikan kontainer berjalan dalam mode baca saja.

Benchmark terbaru untuk Docker (CIS Docker Benchmark v1.4.0) mencakup:

* Konfigurasi host
* Konfigurasi daemon Docker
* File konfigurasi daemon Docker
* Gambar kontainer dan file build
* Runtime kontainer
* Operasi
* Konfigurasi Swarm

**Secure Computing mode** 
Mode Komputasi Aman (seccomp) adalah fitur dalam kernel Linux yang membatasi tindakan yang dapat dilakukan dalam kontainer. Dapat digunakan untuk membatasi akses aplikasi Anda. 

Fitur ini hanya tersedia jika Docker telah dibangun dengan seccomp dan kernel dikonfigurasi dengan CONFIG_SECCOMP aktif. Untuk memeriksa apakah kernel mendukung seccomp:
| $ grep CONFIG_SECCOMP= /boot/config-$(uname -r)
CONFIG_SECCOMP=y

**Pass a profile for a container**
Memberikan profil untuk sebuah kontainer dengan seccomp adalah cara untuk membatasi akses yang diberikan ke pemanggilan sistem di dalam kontainer Docker. Profil seccomp default memberikan pengaturan yang aman dan mematikan sekitar 44 pemanggilan sistem yang mungkin berisiko. Ini memberikan perlindungan yang cukup tanpa mengganggu kompatibilitas aplikasi. Dengan profil ini, pemanggilan sistem secara default ditolak, namun beberapa yang aman diperbolehkan. Penting untuk menjalankan kontainer Docker dengan seccomp untuk memastikan keamanan, tetapi tidak disarankan untuk mengubah profil default.


Ketika Anda menjalankan sebuah kontainer, kontainer tersebut akan menggunakan profil default kecuali jika Anda menggantinya dengan opsi --security-opt. Sebagai contoh, berikut adalah cara untuk secara eksplisit menentukan kebijakan:
| $ docker run --rm \
             -it \
             --security-opt seccomp=/path/to/seccomp/profile.json \
             hello-world

**Secret**
Sebuah rahasia adalah sekelompok data sensitif seperti;
kata sandi, kunci SSH, atau nama server internal yang sebaiknya tidak dikirimkan melalui jaringan atau disimpan dalam kode sumber aplikasi tanpa dienkripsi.

Docker menyediakan cara untuk mengelola rahasia ini secara aman dalam lingkungan Docker Swarm. Rahasia-rasahia ini dienkripsi saat dikirim dan disimpan dalam sistem Docker Swarm. Hanya layanan-layanan tertentu yang diberikan akses ke rahasia ini, dan hanya ketika layanan-layanan tersebut sedang berjalan.

Anda dapat menggunakan rahasia ini untuk mengatur akses ke data sensitif antara kontainer-kontainer dalam lingkungan pengembangan, pengujian, dan produksi Anda. Docker secara otomatis mengelola penyimpanan dan pembagian rahasia-rasahia ini di antara kontainer-kontainer.

Jika diperlukan, Anda dapat menambah, memeriksa, atau menghapus rahasia-rasahia ini kapan pun diperlukan. Selain itu, Anda dapat mengatur pembaruan atau pengembalian rahasia dengan menambahkan nomor versi atau tanggal ke nama rahasia. Ini memudahkan pengelolaan dan pembaruan rahasia-rasahia dalam lingkungan Docker Anda.

**Secret in Compose**
![image](https://hackmd.io/_uploads/Hkww0VSCp.png)

# Storage Driver
Untuk menggunakan driver penyimpanan dengan efektif, penting untuk memahami bagaimana Docker membuat dan menyimpan gambar, serta bagaimana gambar-gambar tersebut digunakan oleh kontainer. Dengan pengetahuan ini, Anda dapat membuat pilihan yang tepat untuk menyimpan data aplikasi Anda dan menghindari masalah kinerja.

Driver penyimpanan memungkinkan Anda menyimpan data di dalam kontainer, tetapi data tersebut tidak akan tetap ada setelah kontainer dihapus. Kecepatan membaca dan menulis data dalam kontainer ini lebih lambat daripada sistem file asli.

| Catatan: bahwa operasi yang membutuhkan banyak penulisan data, seperti penyimpanan basis data, bisa bermasalah, terutama jika data yang sudah ada disimpan dalam lapisan hanya-baca. Detail lebih lanjut dapat ditemukan dalam dokumen ini.

# Docker Storage Driver
Untuk menggunakan driver penyimpanan dengan efektif, penting untuk memahami bagaimana Docker membuat dan menyimpan gambar, serta bagaimana gambar-gambar tersebut digunakan oleh kontainer. Dengan pengetahuan ini, Anda dapat membuat pilihan yang tepat untuk menyimpan data aplikasi Anda dan menghindari masalah kinerja.

Driver penyimpanan memungkinkan Anda menyimpan data di dalam kontainer, tetapi data tersebut tidak akan tetap ada setelah kontainer dihapus. Kecepatan membaca dan menulis data dalam kontainer ini lebih lambat daripada sistem file asli.

| Catatan bahwa operasi yang membutuhkan banyak penulisan data, seperti penyimpanan basis data, bisa bermasalah, terutama jika data yang sudah ada disimpan dalam lapisan hanya-baca. Detail lebih lanjut dapat ditemukan dalam dokumen ini.

Docker mendukung berbagai driver penyimpanan yang berbeda untuk mengelola bagaimana gambar dan kontainer disimpan di host Docker Anda. Dalam memilih driver penyimpanan yang tepat, pertimbangkan faktor-faktor berikut:

* Docker memiliki daftar prioritas driver penyimpanan jika tidak ada yang dikonfigurasi secara eksplisit.
* Pilih driver dengan kinerja dan stabilitas terbaik.
* Docker mendukung driver overlay2, aufs, fuse-overlayfs, devicemapper, btrfs, zfs, dan vfs, masing-masing dengan kelebihan dan kekurangannya.
* Pastikan driver yang Anda pilih sesuai dengan sistem file pendukung Anda.
* Setelah mempersempit pilihan, pertimbangkan karakteristik beban kerja Anda untuk membuat keputusan akhir.

# Supported storage drivers per Linux distribution
Secara umum, driver penyimpanan yang dapat Anda gunakan sebagian ditentukan oleh edisi Docker yang Anda gunakan.
Selain itu, Docker tidak merekomendasikan konfigurasi yang memerlukan Anda menonaktifkan fitur keamanan dari sistem operasi Anda, seperti kebutuhan untuk 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 driver penyimpanan. Secara umum, konfigurasi berikut berfungsi pada versi terbaru distribusi Linux:
![image](https://hackmd.io/_uploads/rJAHT6HCT.png)

**Docker Desktop for Mac and Docker Desktop for Windows**
Docker Desktop untuk Mac dan Docker Desktop untuk Windows ditujukan untuk pengembangan, bukan untuk produksi. Memodifikasi driver penyimpanan pada platform-platform ini tidak memungkinkan.

**Check your current storage driver**
Dokumentasi lengkap untuk setiap driver penyimpanan memberikan semua langkah yang diperlukan untuk mengatur dan menggunakan driver penyimpanan tertentu.

Untuk mengetahui driver penyimpanan yang digunakan oleh Docker saat ini, gunakan perintah docker info dan perhatikan baris yang bertuliskan "Storage Driver".
$ docker info

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

# Lab 11.1: Configuring Storage Driver
Introduction
Execute in node pod-[username]-node01

**1. Edit file daemon.json.**
sudo vim /etc/docker/daemon.json
...
{
  "storage-driver": "vfs"
}
...
![Screenshot (1169)](https://hackmd.io/_uploads/BkYe4RBCp.png)

**2. Restart service docker.**
sudo service docker restart
![Screenshot (1162)](https://hackmd.io/_uploads/HJp3f0HRT.png)

**3. Check the docker info.**
docker info
![Screenshot (1163)](https://hackmd.io/_uploads/HJNCzArC6.png)

**4. Check with docker pull.**
docker pull registry.adinusa.id/btacademy/ubuntu
![Screenshot (1166)](https://hackmd.io/_uploads/r1R8m0S0p.png)

**5. Check the docker directory.**
sudo ls -al /var/lib/docker/vfs/dir/
sudo du -sh /var/lib/docker/vfs/dir/
![Screenshot (1167)](https://hackmd.io/_uploads/rJ_5QRSR6.png)

Run the nusactl grade do-011-1 command to assess the lab results.
nusactl grade do-011-1
![Screenshot (1168)](https://hackmd.io/_uploads/ByshmABRp.png)
"This is task from Adinusa, Join the course of Docker Fundamental in Adinusa for free"

# Logging and Error Handling
Perintah docker logs menampilkan informasi yang dicatat oleh kontainer yang sedang berjalan. Perintah docker service logs menampilkan informasi yang dicatat oleh semua kontainer yang berpartisipasi dalam sebuah layanan. Informasi yang dicatat dan format log tersebut hampir sepenuhnya bergantung pada perintah akhir kontainer.


Secara default, perintah docker logs menampilkan keluaran perintah sebagaimana di terminal. Namun, dalam beberapa kasus, informasi yang ditampilkan mungkin tidak berguna. Misalnya, jika Anda menggunakan driver logging yang mengirimkan log ke tempat lain atau jika aplikasi dalam kontainer tidak mengirimkan keluaran ke STDOUT dan STDERR. Dalam kasus seperti itu, Anda perlu mengambil langkah tambahan.

Salah satu solusi yang umum digunakan adalah dengan membuat tautan simbolis dari file log ke STDOUT dan STDERR. Hal ini dapat dilakukan dengan mengubah konfigurasi aplikasi dalam gambar Docker. Misalnya, gambar resmi nginx membuat tautan simbolis dari file log ke perangkat khusus yang sesuai.

Namun, penting untuk diingat bahwa docker logs hanya menampilkan apa yang dikirimkan ke STDOUT dan STDERR. Jika ada pengaturan lain untuk logging, mungkin perlu cara yang berbeda untuk melihat log.

Example logs :
![image](https://hackmd.io/_uploads/SyK-3ArRa.png)

**Log Check**
Introduction

**1. Check history image.**
docker history registry.adinusa.id/btacademy/nginx:latest

**2. Run nginx.**
docker run -dit -p 80:80 --name nginx1 registry.adinusa.id/btacademy/nginx

**3. Check the filesystem on nginx.**
docker diff nginx1

**4. Cek Log.**
docker logs --details nginx1
docker logs --timestamps nginx1
docker logs nginx1

# Lab Challange
**Challenge 1 - Haproxy With Docker**
Introduction
Note: Execute in node01

**1. Create a challenge1 directory, and go into that directory**
![Screenshot (1171)](https://hackmd.io/_uploads/HklPA0S06.png)

**2. Create 2 container with name web1 using image registry.adinusa.id/btacademy/nginx:latest and web2 using image registry.adinusa.id/btacademy/httpd:latest and use container port 80**
![Screenshot (1170)](https://hackmd.io/_uploads/HkttRCSCa.png)
![Screenshot (1172)](https://hackmd.io/_uploads/r1Wg1180T.png)

3. Save the haproxy configuration file inside the challenge1 folder with the name haproxy.cfg

4. Create 1 container haproxy with name username-haproxy using image registry.adinusa.id/btacademy/haproxy-alpine:2.4
![Screenshot (1173)](https://hackmd.io/_uploads/H1Kyg18Ra.png)

5. Configure the haproxy so that it can access all web server container via haproxy container with domain web1.username.id and web2.username.id

Clue

Do not point the container IP to /etc/hosts
Pointing all domains to IP Node01
Create a docker volume to save configuration haproxy
This is not a loadbalancer

**Challenge 2 - Deploy Laravel with Docker (Hard)**
Introduction
Note: Execute in node02

**1. Make Directory challenge2, change to directory challenge2**

**2. Clone repository from https://github.com/academynusa/perpus-laravel.git**

**3. Create Image img-perpus-username with Dockerfile**

**4. Run the container with image img-perpus-username, expose port 8000, and name it perpus-username**

Clue

Use PHP 7.2
Run Command composer update (in directory perpus)
Copy .env.example cp .env.example .env
Run Command php artisan key:generate to generate APP_KEY in .env
Make sure you have database perpusku_gc
Setting database configuration in .env
Run Commandphp artisan migrate
Also Run Command php artisan db:seed
Make sure no manual steps are executed. to overcome that you can create a bash script which will be run when the container runs.
**Note:** Make sure you can access Dashboard.
![image](https://hackmd.io/_uploads/ryyrUZPRT.png)
