
Пример 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;
}
}