Category Archives: Container

Harbor Container Registry Installation

Harbor เป็น container registry ที่ได้รับความนิยมมากในปัจจุบัน เนื่องจากมีความสามารถที่ช่วยให้เก็บ container image ไว้ภายในองค์กรแล้วยังมีความสามารถอื่นๆ เช่น การทำ proxy ไปยัง container registry ภายนอกเช่น docker hub เพื่อลดจำนวน request ไม่ให้ติดปัญหา request limit ของ docker hub การทำ replication ระหว่าง Harbor ด้วยกันกรณี DC/DR use case และ integrate กับ container scanning เช่น Trivy, Clair และ Notary สำหรับการทำ image signed เพื่อป้องกันการแก้ไขเปลี่ยนแปลง image

ในการติดตั้ง Harbor ต้องการ Docker และ Docker Compose ขั้นตอนการ install docker ขึ้นอยู่กับ OS โดยตัวอย่างนี้ติดตั้งบน Linux Rocky

#!/bin/bash
# Docker Installation Script for Rocky Linux

# 1. Update system packages
sudo dnf update -y

# 2. Install required packages
sudo dnf install -y dnf-utils device-mapper-persistent-data lvm2

# 3. Add Docker's official repository
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 4. Install Docker Engine
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 5. Start and enable Docker service
sudo systemctl start docker
sudo systemctl enable docker

# 6. Add current user to docker group (to run docker without sudo)
sudo usermod -aG docker $USER

# 7. Verify Docker installation
sudo docker --version
sudo docker run hello-world

# 8. Check Docker service status
sudo systemctl status docker

# 9. Optional: Install Docker Compose (if not using plugin version)
# sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# sudo chmod +x /usr/local/bin/docker-compose

echo "Docker installation completed!"
echo "Please log out and log back in for group changes to take effect."
echo "Then you can run 'docker ps' without sudo."

กรณีที่ enable firewall จะต้องทำการ allow service docker ด้วย

# Open Docker ports if firewall is enabled
sudo firewall-cmd --permanent --add-service=docker
sudo firewall-cmd --reload

กรณีนี้ติดตั้งด้วยการใช้ self-signed certificate จำเป็นต้องสร้างไฟล์​ daemon.json และใส่ค่า insecure โดยระบุทั้ง host name, host domain และ IP ถ้าไม่ได้สร้าง record บน DSN server

[nutanix@harbor harbor]$ more /etc/docker/daemon.json
{
    "insecure-registries": ["harbor.local", "10.55.10.75"]
}

ต้อง restart docker หลังจากสร้างไฟล์​ daemon.json เพื่อให้ค่า configuration ถูกนำไปใช้

[nutanix@harbor harbor]$ sudo systemctl restart docker

ทำการ download harbor installation binary และสร้างไฟล์ที่เกี่ยวข้อง

[nutanix@harbor harbor]$ HARBOR_VERSION=$(curl -s https://api.github.com/repos/goharbor/harbor/releases/latest | grep 'tag_name' | cut -d\" -f4)

[nutanix@harbor harbor]$ echo $HARBOR_VERSION
v2.13.1

[nutanix@harbor harbor]$ wget "https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-offline-installer-${HARBOR_VERSION}.tgz"

[nutanix@harbor harbor]$ tar xvf harbor-offline-installer-${HARBOR_VERSION}.tgz

[nutanix@harbor harbor]$ cd harbor
[nutanix@harbor harbor]$ cp harbor.yml.tmpl harbor.yml

[nutanix@harbor harbor]$ mkdir certs
[nutanix@harbor harbor]$ mkdir data
[nutanix@harbor harbor]$ mkdir generate-cert

ทำการ generate certificate สำหรับ Harbor ตัวอย่างนี้จะตั้ง host name เป็น harbor.local โดยเป็น self-signed certificate


# Generate CA Key
[nutanix@harbor harbor]$ cd generate-cert
[nutanix@harbor generate-cert]$ openssl genrsa -out ca.key 4096

# Generate CA certificate
[nutanix@harbor generate-cert]$ openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=TH/ST=TH/L=BK/O=IT/OU=IT/CN=harbor.local" \
-key ca.key \
-out ca.crt

#Generate Server key
[nutanix@harbor generate-cert]$ openssl genrsa -out harbor.local.key 4096

# Generate CSR (Certificate Signing Requests)
[nutanix@harbor generate-cert]$ openssl req -sha512 -new \
-subj "/C=TH/ST=TH/L=BK/O=IT/OU=IT/CN=harbor.local" \
-key harbor.local.key \
-out harbor.local.csr

# Create file v3.ext
[nutanix@harbor generate-cert]$ vi v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.0=harbor.local
IP.0=10.55.10.75 #harbor IP address

# Generate Server Certificate signed with above CA generated
[nutanix@harbor generate-cert]$ openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in harbor.local.csr \
-out harbor.local.crt

# Optional - Convert the certificate to PEM format for docker
[nutanix@harbor generate-cert]$ openssl x509 -inform PEM -in harbor.local.crt -out harbor.local.cert

#copy harbor.local.crt and harbor.local.key for harbor server
[nutanix@harbor generate-cert]$ cp harbor.local.crt ../certs
[nutanix@harbor generate-cert]$ cp harbor.local.key ../certs

แก้ไขไฟล์ harbor.yml โดยมีค่าที่จำเป็นต้องแก้ดังนี้

hostname:
certificate:
private_keys:
data_volume:

hostname เป็น domain name ที่ map ไว้ที่ DNS server แต่ถ้าไม่มี DNS server สามารถใช้ IP แทนได้ดังตัวอย่างนี้

Certificate และ private_keys ได้จากขึ้นตอนสร้าง certificate ข้างต้น

data_volume คือข้อมูลระบบและ docker image ที่จัดเก็บใน harbor จำเป็นในการ backup กรณีระบบมีปัญหา และต้องการ recover

run install command เพื่อติดตั้ง harbor ทั้งนี้สามารถติดตั้ง components อื่นๆ ร่วมด้วยโดยใช้ options –with-trivy –with-notary –with-clair –with-chartmuseum

trivy และ clair สำหรับ vulnerability scanner และ notary สำหรับ container signing และ chartmuseum เพื่อให้ harbor สามารถเก็บ helm chart ได้ ตัวอย่างนี้จะติดตั้งเฉพาะ harbor

[nutanix@harbor harbor]$ sudo ./install.sh

หลังจากติดตั้งเสร็จ ทดสอบ login

[nutanix@harbor harbor]$ docker login 10.55.10.75
Username: admin
Password:

WARNING! Your credentials are stored unencrypted in '/home/nutanix/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

กรณีที่ต้องการทำ registry proxy จะต้องไปสร้าง enpoint ที่ต้องการ connect ก่อน โดยเข้าไปที่เมนู Registries และ click +NEW ENDPOINT

กรณีนี้เลือก Docker Hub จากนั้นกรอกข้อมูล Access ID และ Access Secret เพื่อ connect ไปยัง Docker hub โดยต้องไปสร้าง access token ที่ Docker Hub ก่อน สามารถทำทดสอบการเชื่อมต่อโดย click TEST CONNECTION กด OK เพื่อเพิ่ม Endpoint

สร้าง Projects โดยเข้าไปที่เมนู Projects และ click + NEW PROJECT

กรอกข้อมูล Project name เลือก Access Level เลือก Proxy Cache และเลือก endpoint ที่สร้างในขั้นต้น และ click OK เพื่อสร้าง Project

สร้าง Projects อื่นๆ ตัวอย่างนี้สร้าง Project mirror สำหรับติดตั้ง NKP

กรอกข้อมูล Project

Project ที่สร้างขึ้น

Run Docker without Docker Desktop on macOS

จากที่ Docker Inc ได้ประกาศเรื่อง Docker Desktop ที่จะไม่ free สำหรับหน่วยงานที่มีรายได้มากกว่า 10 ล้านดอลลาร์ แต่ก็คงใช้ได้ฟรีสำหรับหน่วยงานที่มีการใช้งานน้อยกว่า 250 คน และมีรายได้น้อยกว่า 10 ล้านดอลลาร์ ใช้งานส่วนตัว การศึกษา หรืองานที่ไม่แสวงหาผลประโยชน์ เช่น open-source project เป็นต้น โดยจะเริ่มบังคับตั้งแต่ 31 มกราคม 2565 เป็นต้นไป ซึ้งบริษัทใหญ่ๆ ที่เข้าเกณท์ก็ต้องจ่ายต่อการใช้งานที่ 5$ ต่อคน ต่อเดือน และก็มี plan อื่นๆ เช่นจ่ายต่อ Team หรือ ต่อหน่วยงาน บริษัทที่มีรายได้ขนาดนี้ก็ไม่น่ามีปัญหาอะไรในการจ่าย เพราะ Docker Inc เองก็ลงทุนเรื่อง product development ไปพอสมควร รายได้ตรงนี้จะทำให้ product พัฒนาได้อีกมาก

พอเราพูดถึง docker ก็จะมีหลายคำที่เราต้องทำความเข้าใจ ก่อนจะเข้าเนื้อหาการติดตั้ง docker บน macOS

Container เป็นรูปแบบของ software ที่สามารถทำงานได้บนเครื่องที่มีสภาพแวดล้อมแตกต่างกันได้ จากการที่เราได้ pack application และสิ่งที่ application ต้องการใช้ให้อยู่ด้วยกัน (package) เช่น application code, libraries, configuration, runtime/server, operating system เป็นต้น

Docker Inc เป็นบริษัทที่พัฒนา docker software ที่ช่วยให้เรา develop, test และ run application ในแบบ container ได้ง่าย ทั้งที่เป็น open source และไม่ใช่ open source

Docker Engine เป็น open-source software ทำงานบน Linux OS ช่วยทำให้ container ทำงานบน Linux kernel ได้ หน้าที่ของ software ตัวนี้คือจัดการ container life cycle เช่น start, stop, delete และจัดการ resource ของเครื่อง (compute, memory, storage) สำหรับให้ container ทำงานได้แบบแยกจากกัน ป้องกันไม่ให้ process อื่น สามารถเข้าถึง หรือ share resource กันได้ เพื่อจุดประสงค์ด้านความปลอดภัย ทั้งนี้ Docker Engine ทำงานได้เฉพาะใน Linux OS

Docker CLI เป็น command line สำหรับเพื่อติดต่อกับ Docker Engine เพื่อใช้งาน container ประกอบด้วย docker และ docker-compose ซึ้งเป็นเป็น open-source software

Docker Desktop เนื่องจาก Docker Engine ทำงานอยู่บน Linux เท่านั้น ถ้าเครื่องเราเป็น Windows หรือ macOS ก็จะไม่สามารถใช้งาน container ได้ ทั้งนี้เราต้องสร้าง Virtual Machine (VM) ที่เป็น Linux OS สำหรับ docker engine ในเครื่องของเราก่อน ถึงจะสามารถใช้ container ผ่าน VM ที่สร้างขึ้นได้ ตรงนี้จึงเป็นต้นกำเนิดของ Docker Desktop ที่ทำให้เราสามารถใช้ container บน Windows/macOS ได้ โดยจะช่วยเรื่องการจัดการ VM และอื่นๆ ที่เกี่ยวข้องกับการใช้งาน เช่น Networking, Virtualization, สั่งงาน Linux OS เป็นต้น ทั้งนี้ Docker Desktop ถูกออกแบบมาให้ใช้สำหรับเครื่อง Desktop เพื่อ Develop software ไม่ใช่สำหรับ run container บน Production หรือใช้งานจริง

โดยสรุปแล้ว Docker Desktop ไม่ใช่ core technology สำหรับ run container จุดประสงค์คือเป็น Software ที่อำนวยความสะดวกให้เรา Develop software ในแบบ container บน OS ที่เป็น Windows หรือ macOS ได้ง่ายขึ้น ไม่ต้องจัดการอะไรให้ยุ่งยาก ดังนั้น Docker Inc เองก็เลยพยายามที่จะทำรายได้จาก product ตัวนี้กับบริษัทใหญ่ๆ เพราะตัวเองก็ Develop อย่างยากลำบาก รวมถึงค่าใช้จ่ายที่ได้ลงทุนไปนั่นเอง

จากที่อ่านถึงต้องนี้คงตอบคำถามได้แล้วว่า ถ้าเราไม่ใช้ Docker Desktop ได้มั้ย และต้องทำยังไง (อย่าลืมว่า docker, docker-compose, docker engine เป็น open-source) เราต้องมีเครื่องที่เป็น Linux สำหรับ docker engine โดยต้องมี software เพื่อทำ virtualization สำหรับ macOS สามารถใช้ hyperkit หรือ virtualbox ก็ได้ ตัวอย่างนี้ผมใช้ virtualbox โดยทำได้ตามขั้นตอนต่อไปนี้

  1. ทำการ uninstall docker desktop ออกก่อน ด้วยการลบ /Applications/Docker.app สำหรับ macOS แต่จะมี file ค้างอยู่ แนะนำให้ทำตามขึ้นตอนนี้ เพื่อ clean ข้อมูลที่ค้างอยู่ออก หรือ search google ด้วย “uninstall docker desktop on macos”
  2. Install docker, docker-machine และ docker-compose (ถ้าต้องการใช้)
❯ brew install docker docker-compose docker-machine 

3. Install VirtualBox

❯ brew install --cask virtualbox
❯ brew install --cask virtualbox-extension-pack

4. ถ้าเราสั่ง create docker-machine เลยหลังจากนี้จะติดปัญหาเรื่องข้อจำกัดของ IP สำหรับ Host-Only network ใน VirtualBox version ใหม่ โดยจะได้ error “VBoxManage: error: Code E_ACCESSDENIED (0x80070005) – Access denied (extended info not available)” อ่านเพิ่มเติมได้จาก redit สามารถแก้ปัญหาด้วยขั้นตอนดังนี้ อ้างอิง

  • สร้าง folder vbox ใน directory /etc
  • สร้าง file networks.conf ภายใน folder vbox และเขียนข้อมูลในไฟล์ตามด้านล่าง
* 0.0.0.0/0 ::/0

5. create docker-machine

❯ docker-machine create -d virtualbox default
Running pre-create checks...
Creating machine...
(default) Copying /Users/pongsakk/.docker/machine/cache/boot2docker.iso to /Users/pongsakk/.docker/machine/machines/default/boot2docker.iso...
(default) Creating VirtualBox VM...
(default) Creating SSH key...
(default) Starting the VM...
(default) Check network to re-create if needed...
(default) Found a new host-only adapter: "vboxnet0"
(default) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env default

ตรวจสอบหลังจากสร้างเสร็จ

❯ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER      ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v19.03.12

ลองเล่น command อื่นๆ > docker-machine –help

6. setup docker environment เพื่อให้ docker CLI เชื่อมต่อไปยัง docker engine ที่สร้างใหม่

❯ eval $(docker-machine env default)

7. ทดสอบใช้ command docker cli

❯ docker version
Client: Docker Engine - Community
 Version:           20.10.12
 API version:       1.40
 Go version:        go1.17.5
 Git commit:        e91ed5707e
 Built:             Sun Dec 12 06:28:24 2021
 OS/Arch:           darwin/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          19.03.12
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.10
  Git commit:       48a66213fe
  Built:            Mon Jun 22 15:49:35 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

เท่านี้เราก็สามารถใช้ docker CLI ได้ปกติโดยไม่ต้องมี Docker Desktop

Credit: ข้อมูลบางส่วนได้สรุปเนื้อหาจาก https://dhwaneetbhatt.com/blog/run-docker-without-docker-desktop-on-macos