Пример MultibranchPipeline сборки и деплоя NodeJS при помощи Jenkins'а, упаковывание собранного в контейнер с Nginx'ом и обновлением образа в Kubernetes. В качестве хранилища образов используется AWS ECR, уведомления о сборке отправляются в SLACK канал.
Jenkinsfile:
pipeline{ parameters { booleanParam(name: 'del_cache', defaultValue: false, description: 'Toggle this value to build with cache clearing.') } agent any environment { SLACK_CHANNEL = '#maintenance-test' IMAGE_REPO = 'XXXXXXXXXXXX.dkr.ecr.eu-west-1.amazonaws.com/artem' KUBECTL = 'kubectl --kubeconfig=/var/lib/jenkins/.kube/k8s-artem.yml' PROJECT_NAME = 'test-web' REPO = 'https://git.artem.services/scm/dev/test-web.git' REPO_CRED = 'svc-bitbucket' } options { ansiColor('xterm') timeout(time: 30, unit:'MINUTES') timestamps() } stages { stage ('Authorization in repo') { steps { script { sh 'eval "$(aws ecr get-login --profile artem --region eu-west-1 --no-include-email)" &> /dev/null' } } } stage ('Delete Work Dir') { when { expression { return params.del_cache } } steps { deleteDir() git branch: "${BRANCH_NAME}", credentialsId: "${REPO_CRED}", url: "${REPO}" } } stage ('Build app') { agent { docker { image 'node:latest' args "--name ${BUILD_TAG}-app \ -v /etc/passwd:/etc/passwd:ro" reuseNode true } } environment { HOME = "${WORKSPACE}" } steps { sh "npm install" sh "npm run build" } } stage ('Build app image') { steps { script { withDockerServer([uri:'tcp://127.0.0.1:4243']) { sh 'eval "$(aws ecr get-login --profile artem --region eu-west-1 --no-include-email)" &> /dev/null' echo "Debug: Building with docker.build(${IMAGE_REPO}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER})" sh "cp ./.jenkins/Dockerfile ./Dockerfile" def image = docker.build ("${IMAGE_REPO}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER}") echo "Debug: Before push to registry" image.push () echo "Debug: After push to registry" } } } } stage ('Deploy on staging.') { when { branch 'staging' } steps { sh "${KUBECTL} -n staging set image deployment.v1.apps/${PROJECT_NAME}-app ${PROJECT_NAME}=${IMAGE_REPO}:${PROJECT_NAME}-${JOB_BASE_NAME}-${BUILD_NUMBER} --record" } } } post { success { slackSend channel: "${SLACK_CHANNEL}", color: 'good', message: "Job: ${JOB_NAME}${BUILD_NUMBER} build was successful." } failure { slackSend channel: "${SLACK_CHANNEL}", color: 'danger', message: "Job: ${JOB_NAME}${BUILD_NUMBER} was finished with some error. It may occurs because of the build was rollbacked by docker swarm, or because of other error (watch the Jenkins Console Output): ${JOB_URL}${BUILD_ID}/consoleFull" } unstable { slackSend channel: "${SLACK_CHANNEL}", color: 'warning', message: "Job: ${JOB_NAME}${BUILD_NUMBER} was finished with some error. Please watch the Jenkins Console Output: ${JOB_URL}${BUILD_ID}/console." } } }
Dockerfile:
FROM nginx:latest RUN rm -f /etc/nginx/nginx.conf /etc/nginx/sites-enabled/default COPY ./.jenkins/nginx.conf /etc/nginx COPY ./.jenkins/app.conf /etc/nginx/conf.d/default.conf COPY ./build/ /usr/src/app CMD /usr/sbin/nginx -c /etc/nginx/nginx.conf WORKDIR /usr/src/app EXPOSE 80
nginx.conf
user root; worker_processes auto; pid /run/nginx.pid; events { worker_connections 2048; # multi_accept on; } http { ## # Basic Settings ## client_body_buffer_size 256K; client_max_body_size 0; send_timeout 300s; sendfile on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL Settings ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ## # Logging Settings ## log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"' '$request_time $upstream_response_time $pipe'; access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; gzip_disable "msie6"; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.0; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } daemon off;
app.conf
server { listen 80 default_server; root /usr/src/app; index index.html; location / { try_files $uri $uri/ /index.html; } location ~* \.(mp4|obj|mtl|ttf|woff|pdf|jpg|jpeg|gif|png|ico|css|bmp|swf|js|html|txt|svg)$ { expires max; } }