Cách Build Docker Image và Host Docker Image Repository với GitLab

4 năm trước

 

Containerization đang nhanh chóng trở thành phương pháp ưu tiên nhất trong đóng gói và triển khai ứng dụng trong các môi trường điện toán đám mây. Các tiêu chuẩn hóa nó cung cấp, cùng với 
việc sử dụng hiệu quả tài nguyên (khi so sánh với các virtual machine) và tính linh hoạt, làm cho nó trở thành nền tảng của tư duy DevOps hiện đại. Nhiều cloud native thú vị và chiến lược giám sát đặc biệt trở nên khả thi khi các ứng dụng và microservice của bạn được containerize hoàn toàn.

Docker container là loại container phổ biến nhất hiện nay. Mặc dù các kho image công cộng của Docker như Docker Hub có đầy đủ các image của các phần mềm open source được containerize mà bạn có thể sử dụng, nhưng đối các private source bạn sẽ cần phải trả tiền cho một một dịch vụ để build và lưu trữ image riêng của bạn, hoặc chạy phần mềm của riêng bạn để containerize nó.

GitLab Community Edition là một bộ phần mềm tự lưu trữ cung cấp dịch vụ host Git repository, theo dõi dự án (project tracking),dịch vụ CI / CD, Docker Image registry cùng nhiều tính năng khác. Trong hướng dẫn này chúng tôi sẽ sử dụng dịch vụ tích hợp liên tục (continuous integration service) GitLab để xây dựng Docker Image từ một ứng dụng Node.js. Những Image này sau đó sẽ được kiểm tra và tải lên Docker registry riêng.

 

Yêu cầu

Trước khi bắt đầu, bạn cần có một GitLab server được bảo mật, và một GitLab CI runner để triển khai các tác vụ CI. 

GitLab Server Bảo mật bởi SSL

Để lưu mã nguồn, chạy các tác vụ CI/CD và host Docker registry, ta cần một bản cài GitLab trên server Ubuntu 16.04. Hiện tại GitLab khuyến nghị một server với ít nhất 2 lõi CPU và 4GB RAM. Thêm nữa, ta sẽ bảo mật server với chứng chỉ SSL từ Let's Encrypt nên sẽ cần thêm một domain trỏ đến server.

GitLab CI Runner

Bạn cần có hiểu biết overview về các dịch vụ của GitLab cùng cách thiết lập CI Runner trên Ubuntu 16.04.

Giờ hãy đi vào các bước cụ thể.

Bước 1 — Thiết lập GitLab CI Runner

Giả sử ta đã cấu hình thành công một GitLab runner với lệnh sudo gitlab-runner register. CI runner này có khả năng chạy các lệnh build và test ứng dụng bên trong một Docker container riêng biệt.

Tuy nhiên, để build Docker image, runner của ta cần được cấp quyền truy cập tối đa đến Docker service. Cách thông thường để làm việc này là dùng image docker-in-docker. Lệnh này yêu cầu ta đặt runner ở chế độ privileged, nên ta cần tạo một runner thứ hai được chạy ở chế độ này.

Note: Đặt runner ở chế độ privileged vô hiệu tất cả các tầng bảo mật của container. Không may là phương pháp khác để kích hoạt  Docker-capable runner cũng kéo theo một số vấn đề bảo mật khác. Hãy xem bài viết này để tìm hiểu thêm và các tùy chọn của runner.

Bởi vì có những tác động an ninh để sử dụng một privileged runner, ta sẽ tạo ra một project-specific runner mà chỉ chấp nhận công việc Docker của hello_hapi project (admin của GitLab luôn có thể thêm runner này cho các project khác sau này). Từ trang dự án hello_hapi của bạn, nhấp vào Settings ở dưới cùng của menu bên trái, sau đó nhấp vào CI / CD trong menu con:

GitLab project settings menu

Click Expand :

GitLab

Sẽ có vài thông tin về thiết lập một Specific Runner, bao gồm cả một token dùng cho việc đăng kí. Lưu ý vào token này.

GitLab project-specific runners options

Click vào Disable shared Runners. Ta cần đảm bảo rằng các tác vụ Docker chỉ được chạy trên privileged runner. Nếu một non-privileged runner được kích hoạt, GitLab có khả năng sẽ sử dụng runner đó, dẫn đến các lỗi.

Log in vào server( đã được cấu hình với CI runner)

Chạy các lệnh sau:

sudo gitlab-runner register -n \
--url https://gitlab.example.com/ \--registration-token your-token \
--executor docker \
--description "docker-builder" \
--docker-image "docker:latest" \--docker-privileged
OutputRegistering runner... succeeded runner=61SR6BwV 
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
 

Thay phần chữ đỏ bằng giá trị của riêng bạn. Ta sẽ đặt tất cả tùy chọn của runner trên giao diện dòng lệnh thay vì interactive prompt, vì nó không cho phép chỉ rõ chế độ --docker-privileged .

Đến đây runner đã được cấu hình và đang chạy. Click vào icon trên thanh menu của GitLab, rồi click Runners.Các runner sẽ được hiển thị:

GitLab runner listing

 

Bước 2 — Cài đặt Docker Registry

Thiết lập Docker registry cho phép bạn đẩy và kéo image từ máy chủ riêng của bạn, tăng tính bảo mật và giảm sự phụ thuộc của công việc của bạn đến các dịch vụ bên ngoài.

GitLab sẽ thiết lập một private Docker registry với một vài bản cập nhật cấu hình. Đầu tiên chúng ta sẽ thiết lập URL trỏ đến registry. Sau đó ta sẽ cấu hình registry để sử dụng một dịch vụ lưu trữ đối tượng S3 tương thích để lưu trữ dữ liệu của nó.(tùy chọn)

SSH đến GitLab server, rồi mở file cấu hình của GitLab:

sudo nano /etc/gitlab/gitlab.rb

Kéo xuống phần Container Registry settings. Ta sẽ uncomment dòng registry_external_url và đặt nó vào hostname của GitLab trên cổng 5555:

/etc/gitlab/gitlab.rb
registry_external_url 'https://gitlab.example.com:5555'

Tiếp theo thêm vào hai dòng sau để cho registry biết nơi lưu trữ chứng chỉ Let's Encrypt:

/etc/gitlab/gitlab.rb
registry_nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.example.com/fullchain.pem"
registry_nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.example.com/privkey.pem"

Lưu và đóng file, sau đó reconfigure GitLab:

sudo gitlab-ctl reconfigure
Output
. . . gitlab Reconfigured!

Update tường lửa để cho phép kết nối trên cổng của registry

sudo ufw allow 5555

Giờ chuyển sang một máy khác đã được cài Docker, và log in đến private Docker registry. Nếu không có Docker trên local computer, bạn có thể dùng bất cứ server nào được cấu hình để chạy GitLab CI, vì chúng đều đã được cài Docker:

docker login gitlab.example.com:5555

Nhập vào username và  password của GitLab để tiếp tục:

OutputLogin Succeeded

Đến đây registry đã được cài đặt và hoạt động bình thướng.

Để set up một object storage backend cho registry, bạn cần biết về một số khái niệm sau:

  • Access Key
  • Secret Key
  • Region: (ví dụ us-east-1),nếu đang dùng Amazon S3, hay Region Endpoint nếu đang dùng một dịch vụ tương thích với S3
  • Bucket Name

Sau khi hiểu về các khái niệm trên, ta sẽ bắt đầu bằng việc mở file cấu hình của GitLab:

sudo nano /etc/gitlab/gitlab.rb

Tìm khối registry['storage'] uncomment và update nó với các lệnh như sau:

/etc/gitlab/gitlab.rb
registry['storage'] = {
's3' => {
'accesskey' => 'your-key',
'secretkey' => 'your-secret',
'bucket' => 'your-bucket-name',
'region' => 'nyc3',
'regionendpoint' => 'https://nyc3.digitaloceanspaces.com'
}}

Nếu đang dùng Amazon S3, bạn chỉ cần region mà không cần regionendpoint.

Lưu và đóng file.

Note: Đang có một bug là registry sẽ tự shut down sau 30s nếu kho lưu trữ kiểu đối tượng rỗng. Để tránh lỗi này hãy thêm một file bấy kì vào kho chứa, rồi xóa nó đi sau khi lưu dũ liệu thật vào nó.

Reconfigure GitLab :

sudo gitlab-ctl reconfigure

Log in vào registry theo địa chỉ như trên:

docker login gitlab.example.com:5555

Bạn sẽ nhận được một thông báo Login Succeeded

 

Bước 3 — Update gitlab-ci.yaml và Build Docker Image

 

Để build ứng dụng trong Docker,  ta sẽ cần update file .gitlab-ci.yml .Bạn có thể chỉnh sửa file này ngay trong GitLab bằng cách nhấp vào nó từ trang chính của project, sau đó nhấp vào nút Edit. Cách khác, bạn có thể nhân bản các repo đến local machine của bạn, chỉnh sửa các tập tin, sau đó git push nó trở lại GitLab như sau:

git clone git@gitlab.example.com:sammy/hello_hapi.git
cd hello_hapi
# edit the file w/ your favorite editor
git commit -am "updating ci configuration"
git push

Xóa tất các các dòng trong file rồi paste đoạn sau vào:

.gitlab-ci.yml
image: docker:latest
services:
- docker:dind
stages:
- build
- test
- release
variables:
TEST_IMAGE: gitlab.example.com:5555/sammy/hello_hapi:$CI_COMMIT_REF_NAME
RELEASE_IMAGE: gitlab.example.com:5555/sammy/hello_hapi:latest
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN gitlab.example.com:5555build:
stage: build
script:
- docker build --pull -t $TEST_IMAGE .
- docker push $TEST_IMAGE
test:
stage: test
script:
- docker pull $TEST_IMAGE
- docker run $TEST_IMAGE npm test
release:
stage: release
script:
- docker pull $TEST_IMAGE
- docker tag $TEST_IMAGE $RELEASE_IMAGE
- docker push $RELEASE_IMAGE
only:
- master

Sau khi thay thế các giá trị ví dụ thành các giá trị thật của bạn, lưu lại bằng cách bấm vào Commit changes. Nếu đang update file bên ngoài GitLab, xác nhận thay đổi rồi git push chúng lại về GitLab.

Các tập tin cấu hình mới này cho GitLab để sử dụng Docker image mới nhất (image: docker:latest) và liên kết nó với các dịch vụ Docker-in-Docker (docker: dind) sau đó xác định các giai đoạn buildtest, và release. Bước build build image bằng cách sử dụng file Dockerfile  trong repo, sau đó upload nó vào registry. Nếu quá trình thành công, giai đoạn test sẽ dowload các image vừa được build và chạy lệnh npm test bên trong nó. Sau đó nếu test thành công, giai đoạn release sẽ pull image, tag nó với hello_hapi:latest và đẩy nó trở lại registry.

Tùy thuộc vào công việc của bạn, bạn cũng có thể thêm các giai đoạn kiểm tra bổ sung.

Update file cấu hình đã khởi động một build mới. Trở lại project hello_hapi trong GitLab và click vào để xác nhận:

GitLab commit notification with pipeline status icon

Trên trang kết quả bạn có thể click vào bất cứ tiến trình nào trên nó để xem:

GitLab pipeline detail

GitLab pipeline stage progress

Sau cùng, tất cả các giai đoạn sẽ kết thúc với dấu tích xanh bên cạnh. Ta có thể tìm Docker image vừa build bằng cách click vào Registry ở menu bên tay trái:

GitLab container registry image list

Nếu click vào icon"document" bên cạnh tên image, tiện ích sẽ copy lệnh docker pull ... thích hợp vào clipboard. Sau đó bạn có thể pull và run image:

docker pull gitlab.example.com:5555/sammy/hello_hapi:latestdocker run -it --rm -p 3000:3000 gitlab.example.com:5555/sammy/hello_hapi:latest√√√√√
  •  
Output> hello@1.0.0 start /usr/src/app 
> node app.js 
Server running at: http://56fd5df5ddd3:3000
 
 

Image đã được kéo về từ registry và khởi động trong một container. Chuyển sang trình duyệt và kết nối đến cổng 3000 để kiểm tra. Vì đang chạy container trên local machine, ta có thể truy cập nó thông qua localhost với URL:

http://localhost:3000/hello/test
 
OutputHello, test!

Thế là xong. Bạn có thể dừng container với lệnh CTRL-C. Từ giờ trở đi, mỗi lần push code lên nhánh master của repository, ta sẽ tự động builf và test hello_hapi:latest image.

 

Tổng kết

Trong bài viết này, ta đã thiết lập một GitLab runner để build Docker image, tạo một private Docker registry để lưu trữ chúng, và update một ứng dụng Node.js để build và test bên trong Docker container.