Mục tiêu là “Xây dựng hệ thống CI/CD sử dụng Jenkins multibranch pipeline and docker cho Laravel project”.
Mô hình chúng ta sẽ thực hiện
Chúng ta thực hiện các bước build 03 branches cho Laravel project như sau:
- Feature branch: Khi Developers commit code lên nhánh này thì Jenkins thực hiện các stage: check smc, cài đặt
thư viện, chạy test trực tiếp trên Jenkins. - Develop branch: Khi accepted code vào develop branch, thì thực hiện các stage check scm, cài đặt thư viện,
chạy test và đồng bộ code sang test server, sau đó thực hiện chạy ứng dụng trên môi trường test với docker
containers -
Master branch: Khi yêu cầu merge từ develop to master branch được accept, thì thực hiện các stage check
scm, cài đặt thư viện, chạy test và đồng bộ code sang prod server, sau đó thực hiện chạy ứng dụng trên
môi trường product với docker containers. Ở bước này, nếu có điều kiện chúng ta thực hiện thêm stage
“integration test”
Yêu cầu trước khi thực hiện cấu hình:
- Máy chủ Jenkins, cài đặt các PHP7 modules cho Testing
-
Máy chủ SCM (GitLab), kết nối webhook với Jenkins
-
Test Server: Cài đặt docker, docker-compose
-
Prod Server: Cài đặt docker, docker-compose
1. Tạo thư mục chứa project (code)
Thư mục project gồm: source code, Jenkinsfile, docker-compose.yml
Khi đó cấu trúc thư mục được xây dựng như sau
Nội dung trong cấu trúc thư mục như sau:
1.1 Jenkinsfile
Tệp tin Jenkinsfile được viết bằng scripted pipeline có nội dung sau:
node { currentBuild.result = "SUCCESS" try { stage('Checkout'){ checkout scm } stage("Composer Update") { // Run composer update sh 'cd src && composer update' } stage("PHPUnit") { // Run PHPUnit sh 'cd src && ./vendor/bin/phpunit' } // Deploy to each branch switch (env.BRANCH_NAME) { case "master": stage("Build Docker"){ sh 'rsync -avzhP --delete --exclude=.git/ --exclude=Jenkinsifle $WORKSPACE/ root@192.168.1.111:/root/docker/' //build docker & mount source to /var/www/html sh 'ssh root@192.168.1.111 "cd /root/docker/ && bash docker-compose.sh"' //push image to private dockerhub //.... } break case "develop": stage("Build Docker"){ sh 'rsync -avzhP --delete --exclude=.git/ --exclude=Jenkinsifle $WORKSPACE/ root@192.168.1.112:/root/docker/' //build docker & mount source to /var/www/html sh 'ssh root@192.168.1.112 "cd /root/docker/ && bash docker-compose.sh"' } break default: // No deployments for other branches break } } catch (err) { currentBuild.result = "FAILURE" mail body: "project build error is here: ${env.BUILD_URL}" , from: 'info@vnsys.wordpress.com', replyTo: 'info@vnsys.wordpress.com', subject: 'project build failed', to: 'keepwalking86@vnsys.wordpress.com' throw err } }
Trong script này, chúng ta sử dụng biến “currentBuild.result” để xác định kết quả trạng thái build là
“SUCCESS” hay “FAILURE”
Sử dụng try/catch block. Trong đó chúng ta sử dụng “try” block để định nghĩa 4 stage đơn giản sau:
- Checkout: sẽ kiểm tra source code từ GitLab và pull project từ gitlab có địa chỉ http://gitlab.example.local/dungnv/laravel-docker-compose.git
- Composer_Update: sẽ thực hiện lệnh “composer update”
- PHPUnit: Sẽ thực hiện lệnh phpunit cho để test source code. Tùy thuộc vào nhu cầu và điều kiện
chúng ta sẽ thực hiện chi tiết và nhiều hơn các bước test. Trong bài viết này, chúng ta chỉ sử dụng PHPUnit
cho test đơn giản - Build Docker: Sẽ thực hiện đồng bộ code sang server (test/prod), tùy thuộc vào điều
kiện kiểm tra. Nếu source code trên develop branch, khi đó nó sẽ đồng bộ sang test server và sau đó chạy
script docker-composer.sh để thực hiện build docker
images và chạy các container. Nếu source code trên master branch, khi đó code sẽ được đồng bộ sang
production server và chạy docker-composer.sh để
thực hiện build docker images và chạy các container. Đối với các nhánh khác thì chỉ thực hiện 3 bước đầu
tiên. - Khối “catch” được sử dụng khi biến “ currentBuild.result” xác định kết quả trạng thái build
“FAILURE”, khi đó nó thực hiện gửi thông báo build lỗi qua mail
1.2 ./docker Directory
Thư mục ./docker chứa thông tin cấu hình để build các image: nginx và php-fpm
- Nội dung tệp Dockerfile cho nginx docker image
FROM nginx:latest
MAINTAINER KeepWalking86
ADD ./default.conf /etc/nginx/conf.d/
RUN mkdir -p /var/www/example/
#ADD ./src /var/www/example/public/
RUN chown -R nginx:nginx /var/www/example
#Install net tools
RUN apt-get update
RUN apt-get install net-tools lsof -y
#Change nginx uid & gid
RUN usermod -u 1000 nginx && groupmod -g 1000 nginx
##Clearing the apt-get caches
RUN apt-get clean
## Expose ports
EXPOSE 80
- Ngoài ra ta sẽ add tệp cấu hình default nginx cho site (ví dụ example.local)
server { listen 80; listen [::]:80 ipv6only=on; # Log files for Debugging access_log /var/log/nginx/laravel-access.log; error_log /var/log/nginx/laravel-error.log; # Webroot Directory for Laravel project root /var/www/example/public; index index.php index.html index.htm; # Your Domain Name server_name example.local; location ~* \.(jpg|jpeg|gif|css|png|js|ico|txt|srt|swf|zip|rar|html|htm|pdf)$ { access_log off; log_not_found off; expires 30d; # caching, expire after 30 days } location / { try_files $uri $uri/ /index.php?$query_string; } # PHP-FPM Configuration Nginx location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; #fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_pass php-fpm:9000; } }
- Nội dung tệp tin Dockerfile cho php-fpm docker image
FROM php:7.2-fpm RUN apt-get update RUN apt-get install libxml2-dev unzip libmcrypt-dev zlib1g-dev -y #Using docker-php-ext-install to install php modules RUN docker-php-ext-install pdo_mysql mysqli mbstring xml opcache zip EXPOSE 9000 CMD ["php-fpm", "-F"]
1.3 Tệp Compose (docker-compose.yml)
Chúng ta tạo tệp tin docker-compose.yml để định nghĩa
các service và kết hợp chúng với nhau để chạy ứng dụng. Tệp tin được định nghĩa gồm 03 service: db, php-fpm và
webapp
version: "3" services: db: image: mariadb:latest volumes: - ./db:/var/lib/mysql/laravel restart: always environment: MYSQL_ROOT_PASSWORD: P@ssw0rd MYSQL_DATABASE: laravel MYSQL_USER: keepwalking MYSQL_PASSWORD: P@ssw0rd php-fpm: build: ./docker/php-fpm volumes: - ./src:/var/www/example/ webapp: depends_on: - db - php-fpm build: ./docker/nginx ports: - 8081:80 restart: always volumes: - ./src:/var/www/example/
1.4 Tệp bash script (docker-compose.sh)
Chúng ta tạo tệp tin docker-compose.sh cho phép chạy tự động để kiểm tra
điều kiện port, container và gọi tệp tin docker-compose.yml
#!/bin/bash PORT="8081" #Check port exists netstat -nta |grep -i listen |grep $PORT &>/dev/null if [[ $? -eq 0 ]]; then echo "Port ${PORT} is existing. Please, use different ports for Nginx" exit 0; else echo "Creating docker containers for NGINX MARIADB PHP7.2" sleep 2 docker-compose up -d fi
1.5 ./src directory
Cuối cùng là thư mục ./src mà chứa dữ liệu source code (ở đây sử dụng Laravel framework) để cho phép bind
sourcecode giữa docker host và container.
Source code chúng ta có thể download tại https://github.com/laravel/framework
3.2 Tạo repository trên GitLab
Chúng ta sẽ tạo repository trên GitLab với tên “laravel-docker-compose” khi đó đường dẫn repository là:
http://gitlab.example.local/dungnv/laravel-docker-compose.git
Thực hiện push project lên GitLab repository
Truy cập thư mục chứa project, thực hiện đẩy lên gitlab repository “multibranch_pipeline_docker”
git init git remote add origin http://gitlab.example.local/dungnv/laravel-docker-compose.git git add . git commit -m "Add repo" git push origin master
Sau đó chúng ta thực hiện tạo thêm một branch “develop”
3.3 Tạo Job (item) trên Jenkins
Thực hiện tạo Job (item) “multibranch_pipleline_docker” trên Jenkins
Tại thẻ Branch Sources → vào thông tin đường dẫn repo “http://gitlab.example.local/dungnv/laravel-docker-compose.git”
→ Chọn Credentials
Tại thẻ Build Configuration → Sử dụng với tệp Jenkinsfile với đường dẫn gốc của repository.
→ nhấn Save để lưu lại Jenkins job.
a. Kiểm tra build trên Jenkins
Truy cập giao diện web của Jenkins, khi đó nó scan ra được 2 branch: master và develop. Quá trình build cũng bắt
đầu được thực hiện
Chúng ta truy cập vào từng branch vào xem kết quả
Trên nhánh master
- Xem chi tiết kết quả build qua console output
- Xem kết quả build qua stage view
Trên nhánh develop
- Xem kết quả build qua console output
- Xem kết quả build qua stage view
b. Kiểm tra trên 02 Server (Test/Prod)
- Trên Prod Server
- Trên Test Server
Chúng ta thấy docker-compose đã tạo 03 containers ở mỗi Test/Prod server cho chạy ứng dụng Laravel.
Cảm ơn bạn đã trả lời.