Tag: docker registry

  • เตาะแตะไปกับ Docker ตอนที่ 6 Harbor (an enterprise-class registry server)

    จากตอนที่แล้ว เราสามารถทำ Docker registry แบบง่าย ๆ โดยใช้ basic authentication (htpasswd) สำหรับในตอนนี้ เราจะมาทำ Harbor ซึ่งเป็น docker registry ที่มีผู้พัฒนาให้เราสร้างได้ง่ายมากขึ้น และเพิ่มขีดความสามารถให้เราเชื่อมต่อ LDAP/AD เพื่อทำ user authentication และอื่น ๆ อีกมาก

    ผมทดสอบกับ ubuntu server เวอร์ชั่น 16.04 สมมติว่า เราจดชื่อ FQDN ไว้คือ docker-registry.in.psu.ac.th

    ให้แก้ไข hostname ให้ถูกต้อง ดังนี้

    $ sudo vi /etc/hostname
    docker-registry.in.psu.ac.th

    สั่งรีบูตเครื่อง

    $ sudo reboot

     

    ติดตั้ง ssl certificate เนื่องจากเรายังไม่ได้ใช้ certificate ที่ซื้อมา เราจะใช้ ssl-cert-snakeoil ไปก่อนก็ได้

    $ sudo apt install ssl-cert

    ก่อนจะทำในขั้นตอนต่อไป ขณะนี้ได้ติดตั้ง docker ไว้แล้ว วิธีติดตั้งดูจากเรื่อง เตาะแตะไปกับ Docker ตอนที่ 1 Containers (Build, Ship and Run)

    หลังจากติดตั้ง docker แล้ว ในการติดตั้ง harbor จะต้องติดตั้ง docker-compose เพิ่ม ทำดังนี้

    $ sudo apt install docker-compose

     

    ติดตั้ง harbor

    $ wget https://github.com/vmware/harbor/releases/download/v1.1.2/harbor-offline-installer-v1.1.2.tgz
    $ tar xvf harbor-offline-installer-v1.1.2.tgz
    $ cd harbor/

    แก้ไขค่า hostname, ui_url_protocol และ ssl_cert ดังนี้

    $ vi harbor.cfg
    #set hostname
     hostname = docker-registry.in.psu.ac.th
     #set ui_url_protocol
     ui_url_protocol = https
     ......
     #The path of cert and key files for nginx, they are applied only the protocol is set to https 
     ssl_cert = /etc/ssl/certs/ssl-cert-snakeoil.pem
     ssl_cert_key = /etc/ssl/private/ssl-cert-snakeoil.key

    ทำการติดตั้ง

    sudo ./install.sh

     

    เข้า web browser ไปยัง https://docker-registry.in.psu.ac.th


    login เข้าเป็น username admin ในครั้งแรกจะได้รหัสผ่านคือ Harbor12345
    แล้วตั้งค่า configuration ตัวอย่างเช่น Authentication ด้วย OpenLDAP แบบ Anonymous Bind ที่เครื่อง ldap server IP คือ 10.168.16.18 ดังนี้

    เข้าเมนูตามลำดับดังนี้ Administration > Configuration > Authentication
    ใส่ข้อมูลเฉพาะช่องที่แนะนำ

     

    Auth Mode: LDAP

    LDAP URL*: ldaps://10.168.16.18

    LDAP Base DN*: dc=example,dc=com

    LDAP UID*: uid

     

    หากเราใช้ AD และเป็น LDAPS แบบ simple bind จะต้องใส่ข้อมูลใน 2 บรรทัดนี้ด้วย เช่น ldaps ของที่ทำงานของผม (psu.ac.th)

    LDAP Search DN:

    LDAP Search Password:

    LDAP UID*: sAMAccountName

     

    กด SAVE แล้วกด TEST LDAP SERVER เพื่อดูว่า connect ldap server ได้หรือไม่

    ให้ logout ออกจาก username admin

     

    ให้ login ด้วย username ของ ldap server เช่น lulu

    แล้วสร้าง project เช่น job1 (ผมพบว่า หากเรามี user มาใช้ร่วมด้วยหลาย ๆ คน ให้ตั้งชื่อ project ให้ตรงกับชื่อ username เพราะว่า user แต่ละคนไม่สามารถใช้ชื่อ project ซ้ำกันกับของอีกคนได้)

    ผลลัพธ์

     

    ที่ Harbor registry อาจจำเป็นต้องตั้งค่า TLS_REQCERT เป็น never เพื่อติดต่อกับ ldaps server เฉพาะบางเครื่อง ให้เพิ่มคำสั่งดังนี้

    $ sudo sh -c 'echo "TLS_REQCERT never" >> /etc/ldap/ldap.conf'

     

    หากมีการแก้ไข configuration files สำหรับ Harbor ให้ทำขั้นตอนตามลำดับดังนี้

    $ docker-compose down 
    $ vi harbor.cfg
    $ sudo ./prepare
    $ docker-compose up -d

     

    ที่เครื่อง client หากเจอแบบนี้ ก็เพราะว่า ไม่ได้ใช้ certificates จริง

    $ docker login docker-registry.in.psu.ac.th
    Username: lulu
    Password:
    Error response from daemon: Get https://docker-registry.in.psu.ac.th/v2/: x509: certificate signed by unknown authority

    เนื่องจากไม่ได้ใช้ certificates จริง เราต้องทำที่ client ทุกเครื่อง ด้วยคำสั่งเหล่านี้ ก่อนที่จะใช้งานกับ Harbor Registry ได้ ทำดังนี้

    $ export DOMAIN_NAME=docker-registry.in.psu.ac.th
    $ openssl s_client -connect $DOMAIN_NAME:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee /usr/local/share/ca-certificates/$DOMAIN_NAME.crt
    $ sudo update-ca-certificates

    จากนั้นต้อง restart docker ด้วยคำสั่งดังนี้

    $ sudo service docker restart

    ทดสอบ login อีกครั้ง

    $ docker login docker-registry.in.psu.ac.th
    Username: lulu
    Password:
    Login Succeeded

    ทดสอบ push image
    ไป pull image จาก hub.docker.com สัก 1 อัน เช่น

    $ docker pull woonpsu/docsdocker:part1

    ใส่ tag ก่อน push image ไปยัง Harbor registry ที่ project ชื่อ job1 ตั้งชื่อ image ว่า hellolulu

    $ docker tag woonpsu/docsdocker:part1 docker-registry.in.psu.ac.th/job1/hellolulu

    ทำการ push image

    $ docker push docker-registry.in.psu.ac.th/job1/hellolulu

    แล้ว logout

    $ docker logout docker-registry.in.psu.ac.th

     

    ดูในหน้าเว็บเพจของ Username ชื่อ lulu และ project ชื่อ job1 จะมี image ที่ upload ขึ้นมาไว้ ดังรูป

     

    เราได้รู้จักกับคุณสมบัติ 1 เรื่องของ Harbor Registry ซึ่งยังมีอีกมากครับ แต่ตอนนี้ ผมคิดว่าเอาแค่นี้ก่อนนะ

    เพิ่มเติม (9 ต.ค. 60)

    หากพบว่าจำเป็นต้องสั่งคำสั่ง docker-compose up -d ทุกครั้งหลังจากเปิดเครื่อง ผมพบว่าวิธีแก้ไข คือ นำบรรทัดข้างล่างน่ี้ไปใส่ไว้ในไฟล์ /etc/rc.local (ก่อนบรรทัด exit 0) อย่าลืมเปลี่ยนคำว่า username เป็นชื่อ user ที่คุณใช้งานด้วยนะ

    cd /home/username/harbor ; docker-compose up -d ; cd

    exit 0

    หาก Harbor ใช้งานได้ปรกติทันทีหลังจากเปิดเครื่อง ก็ไม่ต้องใช้วิธีแก้ไขอันนี้

     

    References:
    https://github.com/vmware/harbor
    https://github.com/vmware/harbor/blob/master/docs/installation_guide.md
    https://success.docker.com/KBase/I_get_%22×509%3A_certificate_signed_by_unknown_authority%22_error_when_I_try_to_login_to_my_DTR_with_default_certificates

     

  • เตาะแตะไปกับ Docker ตอนที่ 5 Docker registry

    อยากลองใช้ docker แต่ยังไม่ต้องการนำ image อัปโหลดไปไว้บน docker hub จะทำอย่างไรได้มั้ย ที่นี่มีคำตอบครับ

    เราสามารถนำ docker image ที่ได้สร้างขึ้นนั้นไปเก็บไว้ในสิ่งที่เรียกว่า Docker registry ซึ่งแบ่งได้เป็น 2 อย่างคือ Public registry อยู่ที่ hub.docker.com เราจะต้องลงทะเบียนเพื่อขอมีบัญชีผู้ใช้จึงจะสามารถอัปโหลด image ไปเก็บไว้ได้ ส่วนอีกอย่างก็คือ Private (Local) registry จะเป็นการสร้างที่เก็บส่วนตัว ที่เก็บของหน่วยงาน ในบทความนี้จะสาธิตทำที่เก็บ image สำหรับทดสอบงาน

    การใช้งาน Docker public registry ต้องมี user account ที่ cloud.docker.com
    จะต้อง login ก่อนจึงจะ push image ขึ้นไปได้ เหมือนที่แสดงตัวอย่างไว้ในบล็อก “เตาะแตะไปกับ Docker ตอนที่ 1”

    $ docker login

    ตัวอย่างคำสั่ง push ที่ผมนำ image ไปเก็บไว้

    $ docker push woonpsu/docsdocker:part1

    ซึ่งเรียกใช้จากที่เครื่องใดก็ได้ ด้วยคำสั่ง pull

    $ docker pull woonpsu/docsdocker:part1

     

    แต่หากเรายังไม่พร้อมที่จะนำ image ไปไว้บนนั้น เราก็ทำ Local registry ไว้ใช้เองไปพราง ๆ ก่อน ทำได้ 2 แบบ คือ
    1. Local registry ที่ใช้งานภายในเครื่องของเราเครื่องเดียว
    2. Local registry ที่เราเปิดให้เครื่อง client อื่น ๆ เข้ามาใช้ร่วมได้

    Local registry แบบที่ใช้งานภายในเครื่องของเราเครื่องเดียว (localhost:5000)
    ใช้คำสั่งนี้เพื่อเริ่มต้นสร้าง registry container

    $ docker run -d -p 5000:5000 --restart=always --name myregistry registry:2

    จากนั้นเรา pull image สักอัน จาก hub.docker.com เช่น

    $ docker pull ubuntu:16.04

    หลังจากดัดแปลง(ไม่ทำก็ได้)ตามต้องการแล้วก็ใส่ tag localhost:5000/my-ubuntu ดังนี้

    $ docker tag ubuntu:16.04 localhost:5000/my-ubuntu
    $ docker images

    แล้วก็ push image ไปยัง local registry ซึ่งก็คือ เครื่องที่เรากำลังใช้งาน (localhost) ใช้ port หมายเลข 5000 ดังนี้

    $ docker push localhost:5000/my-ubuntu

    ซึ่งวิธีการเรียกใช้งาน image ที่เก็บไว้นั้น เป็นดังนี้

    $ docker pull localhost:5000/my-ubuntu

    ก่อนไปทำตัวอย่างถัดไปซึ่งเป็นแบบที่ 2 ให้ลบ container ชื่อ myregistry ที่ทดสอบเสร็จแล้ว ที่ต้องลบเพราะว่าใช้ port หมายเลขเดียวกัน หากใช้หมายเลข port ต่างกัน ก็ไม่ต้องลบ

    $ docker stop myregistry
    $ docker rm myregistry

     

    Local registry แบบที่เราเปิดให้เครื่อง client อื่น ๆ เข้ามาใช้ร่วมได้ (docker-registry.localdomain:5000)

    เราจะต้องเริ่มต้นที่การกำหนดชื่อเครื่อง ผมสมมติตั้งชื่อว่า docker-registry.localdomain ให้กับ host ที่ติดตั้ง docker registry ใครจะตั้งอย่างไรก็ได้ครับ

    ในบทความนี้ เนื่องจากว่า ผมจะทดสอบแบบไม่ได้ไปจด Domain Name จริงให้กับเครื่อง ผมจะต้องแก้ไขไฟล์ /etc/hosts และ /etc/hostname ดังนี้

    ที่ไฟล์ /etc/hosts ให้เพิ่มบรรทัด

    10.168.16.19 docker-registry.localdomain

    ที่ไฟล์ /etc/hostname ให้เปลี่ยนชื่อเครื่องจากเดิม มาเป็นดังนี้

    docker-registry.localdomain

    เสร็จแล้ว reboot เครื่อง

    ขั้นตอนการตั้งค่า มาดูกันครับ
    เริ่มต้นที่เครื่อง docker-registry.localdomain
    ให้ทำคำสั่งตั้งค่า TLS certificate เพราะว่าจำเป็นต้องใช้ด้วย (หากมี certificate ของจริงก็นำมาใช้แทน domain.crt และ domain.key ได้เลย)

    $ cd
    $ mkdir certs
    $ openssl req \
    -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
    -x509 -days 365 -out certs/domain.crt

    จะมีการถามให้เติมข้อมูล เอาคล้าย ๆ ตัวอย่างก็ได้

    Generating a 4096 bit RSA private key
    writing new private key to 'certs/domain.key'
    Country Name (2 letter code) [AU]:TH
    State or Province Name (full name) [Some-State]:SK
    Locality Name (eg, city) [ ]:HDY
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:PSU
    Organizational Unit Name (eg, section) [ ]:CC
    Common Name (e.g. server FQDN or YOUR name) [ ]:docker-registry.localdomain
    Email Address [ ]:

    จะพบว่าในไดเรกทอรี certs จะเกิดไฟล์ 2 ไฟล์

    $ ls certs/
    domain.crt domain.key

    ใช้คำสั่ง docker run สร้าง container และสมมติตั้งชื่อว่า netregistry

    $ docker run -d --restart=always --name netregistry \
    -v `pwd`/certs:/certs \
    -e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
    -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
    -p 5000:5000 \
    registry:2

    ต่อไปจะเป็นการทดสอบการใช้งาน local registry
    ใส่ tag ก่อนที่จะ push ดังนี้

    $ docker tag ubuntu:16.04 docker-registry.localdomain:5000/my-ubuntu
    $ docker images

    แล้ว push image เก็บไว้ใน local registry

    $ docker push docker-registry.localdomain:5000/my-ubuntu

     

    ไปที่เครื่อง client สมมติตั้งชื่อ hostname ว่า docker-vm3
    ที่ไฟล์ /etc/hosts ให้เพิ่มบรรทัด

    127.0.1.1 docker-vm3
    10.168.16.19 docker-registry.localdomain

    ที่ไฟล์ /etc/hostname เป็นดังนี้

    docker-vm3

    เสร็จแล้ว reboot เครื่อง
    ต่อไปก็ทดสอบ pull image จาก local registry ที่ทำขึ้นนั้น

    $ docker pull docker-registry.localdomain:5000/my-ubuntu
    $ docker images

    ต่อไปก็ทดสอบ push image โดยเราก็ไปเอา image จาก hub.docker.com มาสัก 1 อัน ใส่ tag แล้ว push ดังนี้

    $ docker pull woonpsu/docsdocker:part1
    $ docker tag woonpsu/docsdocker:part1 docker-registry.localdomain:5000/helloworld
    $ docker push docker-registry.localdomain:5000/helloworld

    จะพบว่าเราสามารถ push image ไปยังเครื่อง local registry ได้ด้วย

    วิธีที่แนะนำไปแล้วข้างต้น เป็นการสร้าง Local registry ที่ไม่ได้มีความปลอดภัย เพราะว่าแค่รู้ชื่อเครื่อง รู้หมายเลข port (เลือกทดสอบกับ port 5000) ก็สามารถ push image ได้แล้ว

     

    ดังนั้นหากจะสร้าง Local registry ให้บริการ (production) เราก็ต้องทำขั้นตอนเพิ่มอีกคือต้องใช้ TLS certificate ร่วมกับ Access control

    ดังนี้

    ที่เครื่อง docker-registry.localdomain
    สร้าง username ที่มีสิทธิจะเข้ามา (access) ใช้ local registry สมมติชื่อ testuser และรหัสผ่านคือ testpassword ดังนี้

    $ mkdir auth
    $ docker run \
     --entrypoint htpasswd \
     registry:2 -Bbn testuser testpassword > auth/htpasswd
    $ cat auth/htpasswd
    testuser:$2y$05$UMOEA8bdBqSbHp/2LfiQ/uxLkf5IkXNqNE8V3Mp2IR/fRCsLXE5Q2

    รัน container ตั้งชื่อว่า privateregistry และเราจะเปลี่ยนมาใช้ port 443 ดังนี้

    $ docker run -d \
     --restart=always \
     --name privateregistry \
     -v `pwd`/auth:/auth \
     -e "REGISTRY_AUTH=htpasswd" \
     -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
     -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
     -v `pwd`/certs:/certs \
     -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
     -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
     -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
     -p 443:443 \
     registry:2

    ไปที่เครื่อง client ชื่อ docker-vm3

    $ docker login docker-registry.localdomain
    Username: testuser
    Password:

    ทดสอบ push image

    $ docker tag woonpsu/docsdocker:part1 docker-registry.localdomain/sawadee
    $ docker push docker-registry.localdomain/sawadee

    ลองทดสอบดูว่าหากไม่ได้ login ก็จะ push ไม่ได้

    $ docker logout docker-registry.localdomain
    $ docker push docker-registry.localdomain/sawadee
    The push refers to a repository [docker-registry.localdomain/sawadee]
    0d960f1d4fba: Preparing
    no basic auth credentials

     

    ข้อควรระวังในการทำ local registry คือ image ที่เรานำไปเก็บไว้ จะอยู่ใน container ซึ่งหากเราลบ container ด้วยคำสั่ง

    $ docker stop privateregistry
    $ docker rm privateregistry

    ก็จะเป็นการลบ image ทั้งหมด
    ดังนั้น เราจะต้องศึกษาวิธี mount volume เข้าไปใน container เพื่อให้ image ที่ push ไว้นั้น ถูกเก็บใน file system ของเครื่อง host แทน โดยเพิ่มบรรทัด -v นี้เข้าไปด้วยวางไว้ก่อนบรรทัดสุดท้าย (registry:2)

    -v /mnt/registry:/var/lib/registry \

    โดยที่ /mnt/registry คือ file system บน host และ /var/lib/registry คือไดเรกทอรีใน container

     

    ขอให้สนุกกับการทดลองเล่น docker กันนะครับ

     

    Reference:
    https://docs.docker.com/registry/deploying/
    https://docs.docker.com/registry/deploying/#restricting-access