Docker #2: Command-Command Esensial Part 2

Docker #2: Command-Command Esensial Part 2

Container Port

Secara default, saat kita membuat container menggunakan docker create atau docker run kita tidak akan bisa mengakses container tersebut dari internet. Untuk membuat sebuah container dapat diakses dari internet. Kita perlu menambahkan --publish atau -p . Berikut adalah contoh command nya :

Syntax:

docker create -p publishPort:containerPort --name containerName imageName:tag

publishPort: port yang diatur agar bisa diakes dari internet

containerPort: port yang dihasilkan oleh container

studi kasus: Saya akan mencoba membuat container menggunakan image nginx. Secara default, nginx akan menghasilkan port 80 untuk diakses. Dan agar nginx bisa diakes dari internet, saya akan mempublish nginx ini ke port 3222. Jadi jika dirunutkan adalah sebagai berikut:

  • image: nginx:latest

  • containerPort: 80

  • publishPort: 3222

Command:

docker run -d --publish 3222:80 --name nginx-2 nginx:latest

Hasil:

Container Environment Variable

Selanjutnya adalah Environment Variable. Untuk mengatur Env Variable saat membuat sebuah container menggunakan docker create atau docker run kita bisa menambahkan --env KEY="value" . Sebagai contoh praktik saya akan menggunakan image mongo. Pada image mongo, kita bisa mengatur user dan password yang nanti digunakan sebagai auth ketika ingin menggunakan db nya. Detail nya adalah sebagai berikut:

  • image: mongo:latest

  • user ENV: MONGO_INITDB_ROOT_USERNAME

  • pw ENV: MONGO_INITDB_ROOT_PASSWORD

  • publishPort: 3113

  • containerPort: 27017 (default)

Command:

docker run -d --name mongodb-2 -p 3113:27017 \
--env MONGO_INITDB_ROOT_USERNAME=hifni \
--env MONGO_INITDB_ROOT_PASSWORD=hifni \
mongo:latest

Hasil:

Test koneksi menggunakan MongoDB Compass:

Container Resource Limit

Ketika kita membuat sebuah container. Maka container bisa memakai seluruh resource (CPU, RAM, dsb) yang kita miliki. Jika terjadi sebuah accident yang membuat aplikasi didalam container yang kita miliki maka akan ber-impact terhadap container yang lainnya dan berdampak terhadap server/host dari container. Contoh kita memiliki 4 container aktif yang tidak kita limit reource nya. Kemudian ada 1 container yang error dan menyebabkan ia jadi menggunakan 100% dari kapasitas CPU. Maka container lainnya pun akan terdampak. Untuk menghindari kejadian seperti itu, maka salah satu langkahnya adalah dengan menetapkan "Resource Limit".

Untuk membatasi penggunaan maksimal dari CPU saya akan menggunakan opsi --cpus=<value> . Misal saya memiliki CPU dengan 4 core dan saya ingin container hanya boleh menggunakan maksmal 2 core maka begini cara nya --cpus=2 atau container hanya boleh menggunakan 1/2 core. Maka seperti ini format nya--cpus=0.5 .

Setelah itu, untuk mengatur limit dari penggunaan RAM saya akan menggunakan opsi --memory=<value> dan suffix yang tersedia adalah sebagai berikut:

  • b = bytes

  • k = kilobytes

  • m = megabytes

  • g = gigabytes

Jadi jika saya ingin membatasi container hanya boleh menggunakan maksimal 2gb dari keseluruhan ram yang saya miliki format penulisannya adalah seperti ini --memory=2g atau --memory=2000m

Contoh penggunaan lengkap nya adalah sebagai berikut:

  • image: nginx:latest

  • containerName: nginx-with-limit

  • publishPort: 3114

  • CPU limit: 1 core

  • memory/RAM limit: 1.5gb

Command:

docker run -d --name nginx-with-limit -p 3114:80 \
--cpus=1 --memory=1500m nginx:latest

Hasil:

*note: untuk CPU memang tidak terlihat inforasi limit nya berapa ketika kita monitor menggunakan command docker stats , hanya memory yang ditampilkan informasi limit nya.

Bind Mounts

Secara default, saat kita membuat sebuah container maka storage dari container itu sendiri akan terisolasi dengan storage host maupun storage container lain. Untuk membuat container dapat mengakses directory tertentu dari host atau sebaliknya maka kita bisa menambahkan opsi --mount ketika membuat container. Berikut parameter yang dibutuhkan.

ParameterDeskripsi
typeJenis mount yang akan dilakukan. Tersedia bind, volume, atautmpfs . Untuk bind mount, gunakan nilai bind.
source atau srcLokasi/path di host sistem file yang akan di-mount ke kontainer.
target atau dstLokasi/path di dalam kontainer tempat file atau direktori host akan di-mount.
readonlyOpsional. Jika diatur ke true, membuat mount menjadi hanya-baca.

Contoh command:

docker run -d \
  -p 3115:80 \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app \
  nginx:latest

Untuk memastikan mount bind nya sudah berhasil, kita bisa mengeceknya menggunakan command docker inspect <containerId/containerName>

Hasil :

Volume

Docker Volume

  • Selain menggunakan Bind Mounts, kita juga bisa menggunakan volumes sebagai "external storage" dari container yang kita buat.

  • Fitur Bind Mounts sudah ada sejak Docker versi awal, di versi terbaru direkomendasikan menggunakan Docker Volume

  • Docker Volume mirip dengan Bind Mounts, bedanya adalah terdapat management Volume, dimana kita bisa membuat Volume, melihat daftar Volume, dan menghapus Volume

  • Volume sendiri bisa dianggap storage yang digunakan untuk menyimpan data, bedanya dengan Bind Mounts, pada bind mounts, data disimpan pada sistem host, sedangkan pada volume, data di manage oleh Docker

List volume

Untuk menampilkan daftar volume bisa menggunakan command berikut:

docker volume ls

Create volume

Untuk membuat volume bisa menggunakan command berikut:

docker volume create <volumeName>

Remove volume

Dan untuk menghapus volume bisa menggunakan command berikut:

docker volume rm <volumeName>

# CATATAN
# sebelum menghapus volume, pastika volume tidak terkonek dengan 
# container tertentu, jika tidak. Maka volume tidak bisa dihapus.

Container Volume

  • Volume yang sudah kita buat, bisa kita gunakan di container

  • Keuntungan menggunakan volume adalah, jika container kita hapus, data akan tetap aman di volume

Untuk menghubungkan container dengan volume contoh command nya adalah sebagai berikut:

#contoh 1
docker run -d \
  -p 3115:80 \
  --name devtest \
  -v volumeName:/app \
  nginx:latest

# contoh 2
docker run -d \
  -p 3115:80 \
  --name devtest \
  --mount type=volume,source=volumeName,target=/app \
  nginx:latest

Contoh Detail

Studi Kasus

Saya sedang mengembangkan aplikasi Node.js yang berjalan di port 3000. Aplikasi ini menyimpan log di dalam folder /usr/src/app/logs di container. Dan saya ingin:

  1. Mengedit kode aplikasi di host dan langsung melihat perubahan di container tanpa harus membangun ulang image.

  2. Menyimpan log aplikasi secara persisten di volume Docker agar tidak hilang saat container dihentikan atau dihapus.

Dengan konfigurasi di atas:

  • Bind mount menghubungkan direktori kode lokal dengan container, sehingga perubahan pada kode di host akan langsung terlihat di container.

  • Volume node_logs akan menyimpan log aplikasi secara persisten.

Command:

# Command 1: Membuat volume
docker volume create node_logs

# Command 2: Menjalankan container sekaligus menghubungkannya 
# dengan storage di host dan volume
docker run -d -p 3000:3000 --name node_app \
-v type=bind,source="$(pwd)"/app,destination=/usr/src/app \
-v type=volume,source=node_logs,destination=/usr/src/app/logs \
node:latest

Penjelasan command diatas:

Penjelasan:

  1. -v type=bind,source="$(pwd)"/app,destination=/usr/src/app:

    • type=bind: Menghubungkan direktori dari host ke container (bind mount).

    • source="$(pwd)/app": Direktori di host (lokal) di mana kode aplikasi Node.js berada.

    • destination=/usr/src/app: Direktori dalam container di mana kode Node.js akan dimuat.

  2. -v type=volume,source=node_logs,destination=/usr/src/app/logs:

    • type=volume: Menggunakan volume Docker untuk menyimpan log yang dihasilkan oleh aplikasi.

    • source=node_logs: Volume bernama node_logs untuk menyimpan log aplikasi.

    • destination=/usr/src/app/logs: Direktori dalam container di mana log aplikasi akan disimpan.

Network

Docker Network

  • Saat kita membuat container di docker, secara default container akan saling terisolasi satu sama lain

  • Docker memiliki fitur Network yang bisa digunakan untuk membuat jaringan di dalam Docker

  • Dengan menggunakan Network, kita bisa mengkoneksikan container dengan container lain dalam satu Network yang sama

  • Jika beberapa container terdapat pada satu Network yang sama, maka secara otomatis container tersebut bisa saling berkomunikasi

Saat kita membuat Network di Docker, kita perlu menentukan driver yang ingin kita gunakan, ada banyak driver yang bisa kita gunakan, tapi kadang ada syarat sebuah driver network bisa kita gunakan. Beberapa network driver di docker:

  • bridge (default), Semua kontainer dalam satu network bridge dapat saling terhubung, mirip seperti perangkat yang terhubung ke router WiFi di rumah.
  • host, yaitu driver yang digunakan untuk membuat network yang sama dengan sistem host tanpa isolasi. Seperti menjalankan aplikasi langsung di komputer tanpa pembungkus kontainer. host hanya jalan di Docker Linux, tidak bisa digunakan di Mac atau Windows.

  • none, yaitu driver untuk membuat network yang tidak bisa berkomunikasi

Contoh penggunaan:

# Command 1: membuat network
docker network create my_network

# Command 2: menjalankan node_app + menghubungkannya dengan my_network
docker run -d --name app --network my_network node_app

# Command 3: menjalankan db + menghubungkannya dengan my_network
docker run -d --name db --network my_network db_image

Dengan cara ini, app dan db bisa saling berkomunikasi.

Network List

Berikut adalah cara melihat daftar dari network yang ada di docker:

docker network ls

Output:

Create Network

Berikut adalah cara untuk membuat network di docker:

# Syntax: docker network create network_name
docker network create demo_app_network

Secara default, ketika kita menggunakan command diatas. Maka akan membuat sebuah network yang menggunakan driver “bridge“.

Output:

Delete Network

Berikut adalah cara untuk menghapus docker network:

# Syntax: docker network rm network_name
docker network rm demo_app_network

Output:

Catatan: network hanya bisa dihapus jika dia tidak terhubung ke container manapun. Jika network terhubung ke container, maka koneksi container dengan network tersebut harus dilepas terlebih dahulu.

Container Network

  • Setelah kita membuat Network, kita bisa menambahkan container ke network

  • Container yang terdapat di dalam network yang sama bisa saling berkomunikasi (tergantung jenis driver network nya)

  • Container bisa mengakses container lain dengan menyebutkan hostname dari container nya, yaitu nama container nya

Berikut adalah contoh penggunaanya:

  • Buat bridge network:

    Jalankan perintah ini untuk membuat jaringan Docker dengan driver bridge:

      docker network create my_bridge_network
    
  • Jalankan container pertama (misalnya container untuk aplikasi Node.js):

      docker run -d --name node_app --network my_bridge_network node:14
    

    Ini akan menjalankan container node_app yang terhubung ke jaringan my_bridge_network.

  • Jalankan container kedua (misalnya container database seperti MongoDB):

      docker run -d --name mongo_db --network my_bridge_network mongo
    

    Container mongo_db juga akan terhubung ke jaringan yang sama, sehingga container node_app dapat berkomunikasi dengan mongo_db.

  • Koneksikan antar container:

    Dalam container node_app, kamu bisa mengakses MongoDB dengan menggunakan nama container mongo_db sebagai hostname.

    Misalnya, dari aplikasi Node.js di dalam container, kamu bisa konek ke MongoDB seperti ini:

      const MongoClient = require('mongodb').MongoClient;
      const url = 'mongodb://mongo_db:27017'; // Gunakan 'mongo_db' sebagai hostname
    

    Karena kedua container berada dalam jaringan my_bridge_network, mereka bisa saling berkomunikasi dengan nama container masing-masing.

Connected Container to Network

Jika containernya sudah terlanjur dibuat, kita juga bisa mengkoneksikan container yang sudah dibuat ke network yang ada. Berikut caranya:

# Syntax: docker network connect network_name container_name
docker network demo_app_network demo_app_1

Disconnected Container from Network

Selain bisa menghubungkan container ke network, kita juga bisa memutuskan koneksinya dari network tersebut. Contoh:

# Syntax: docker network disconnect network_name conainer_name
docker network demo_app_network demo_app_1

Docker Inspect

Docker inspect adalah perintah yang digunakan untuk menampilkan informasi detail tentang objek Docker tertentu, seperti container, image, volume, atau jaringan. Informasi ini meliputi metadata, pengaturan konfigurasi, status, dan detail teknis lainnya terkait objek Docker tersebut.

Pada langkah sebelumnya saya menggunakan docker inspect untuk memastikan mount bind telah berhasil dilakukan.

Command:

docker inspect <containerId/containerName>

Contoh output:

Dengan docker inspect kita bisa melihat banyak hal, diantaranya adalah:

  • Metadata: Informasi metadata tentang objek Docker, termasuk ID, nama, dan label.

  • Konfigurasi: Pengaturan konfigurasi yang digunakan oleh objek Docker, seperti environment variables, command, dan entrypoint.

  • Jaringan: Informasi tentang jaringan yang terhubung dengan objek Docker, termasuk alamat IP, port mapping, dan konfigurasi jaringan lainnya.

  • Volume: Detail volume yang terkait dengan objek Docker, seperti lokasi mount dan konfigurasi volume.

  • Status: Status saat ini dari objek Docker, seperti apakah objek tersebut sedang berjalan atau berhenti.

  • Informasi Teknis: Informasi teknis tambahan, seperti path ke direktori yang terkait dengan objek Docker dan detail internal lainnya.

Docker Prune

Docker prune adalah sebuah perintah yang digunakan untuk membersihkan resource Docker yang tidak digunakan, seperti images, containers, networks, dan build caches yang tidak sedang aktif. Tujuan utamanya adalah untuk menghemat ruang penyimpanan dengan menghapus resource yang tidak diperlukan lagi.

Beberapa contoh penggunaan docker prune:

  1. docker prune: Menghapus semua resource yang tidak digunakan, termasuk images, containers, networks, dan build caches.

  2. docker image prune: Menghapus semua images yang tidak digunakan.

  3. docker container prune: Menghapus semua containers yang berhenti atau dihentikan.

  4. docker network prune: Menghapus semua networks yang tidak digunakan.

  5. docker builder prune: Menghapus semua build caches yang tidak digunakan.

  6. docker system prune: Ini merupakan perintah yang paling komprehensif, yang menghapus semua resource yang tidak digunakan, termasuk images, containers, networks, dan build caches.

Kita bisa menambahkan opsi --force atau -f untuk memaksa penghapusan tanpa konfirmasi, dan --volumes untuk juga menghapus volume yang tidak digunakan.

Sebagai contoh, jika kita ingin menghapus semua images yang tidak digunakan dan memaksa penghapusan tanpa konfirmasi, kita dapat menggunakan perintah berikut:

docker image prune -f

Docker prune sangat berguna untuk membersihkan resource yang tidak dibutuhkan lagi dan menghemat ruang penyimpanan, terutama setelah melakukan banyak percobaan atau eksperimen dengan Docker.


Artikel ini adalah catatan saya dari belajar di Programmer Zaman Now - TUTORIAL DOCKER DASAR (BAHASA INDONESIA)