您好,登录后才能下订单哦!
# Docker容器中怎么使用Jenkins部署Web项目
## 前言
在当今DevOps实践中,持续集成和持续部署(CI/CD)已成为现代软件开发的核心环节。Jenkins作为最流行的开源自动化服务器,与Docker容器化技术的结合,为Web项目部署提供了高效、可靠的解决方案。本文将详细介绍如何在Docker环境中使用Jenkins实现Web项目的自动化部署,涵盖从环境搭建到高级配置的全流程。
## 第一章:环境准备与基础概念
### 1.1 Docker与Jenkins概述
**Docker**是一种轻量级的容器化技术,它允许开发者将应用及其依赖打包到标准化的单元中,实现"一次构建,随处运行"的目标。与传统虚拟机相比,Docker容器更加轻量、启动更快且资源占用更少。
**Jenkins**是一个用Java编写的开源自动化服务器,提供了数百个插件支持构建、部署和自动化任何项目。其主要特点包括:
- 易于安装和配置
- 丰富的插件生态系统
- 分布式构建能力
- 强大的流水线(Pipeline)支持
### 1.2 为什么要在Docker中使用Jenkins?
将Jenkins运行在Docker容器中具有以下优势:
1. **环境隔离**:Jenkins及其依赖被封装在容器中,与主机系统隔离
2. **快速部署**:通过Docker镜像可以快速部署Jenkins实例
3. **易于维护**:升级或回滚只需更换镜像版本
4. **资源可控**:可以限制容器使用的CPU、内存等资源
5. **可移植性**:相同的配置可以在不同环境中运行
### 1.3 系统要求
在开始之前,请确保您的系统满足以下要求:
- **操作系统**:Linux/Windows/macOS(推荐Linux)
- **Docker**:版本20.10.0或更高
- **Docker Compose**:版本1.29.0或更高(可选但推荐)
- **硬件**:
- 至少4GB RAM(建议8GB以上)
- 至少20GB可用磁盘空间
- 2核CPU或更多
## 第二章:安装与配置Docker环境
### 2.1 安装Docker引擎
根据不同操作系统,安装步骤略有差异:
#### Ubuntu/Debian系统
```bash
# 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 安装依赖
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
# 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 设置稳定版仓库
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装Docker引擎
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# 验证安装
sudo docker run hello-world
# 卸载旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 安装必要工具
sudo yum install -y yum-utils
# 设置仓库
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 安装Docker引擎
sudo yum install docker-ce docker-ce-cli containerd.io
# 启动Docker
sudo systemctl start docker
# 验证安装
sudo docker run hello-world
Docker Compose是一个用于定义和运行多容器Docker应用的工具,推荐安装:
# 下载最新稳定版
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 赋予执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 创建符号链接(可选)
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 验证安装
docker-compose --version
为避免每次使用docker命令都需要sudo,可以将当前用户加入docker组:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker # 刷新组权限
# 验证配置
docker run hello-world
Jenkins官方提供了Docker镜像,可以直接使用:
# 拉取最新LTS版本
docker pull jenkins/jenkins:lts
# 运行Jenkins容器
docker run -d \
--name jenkins \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
jenkins/jenkins:lts
参数说明:
- -d
:后台运行容器
- --name
:指定容器名称
- -p
:端口映射(8080为Web界面,50000为代理通信)
- -v
:数据卷挂载,持久化Jenkins数据
对于生产环境,推荐使用docker-compose.yml文件定义服务:
version: '3.8'
services:
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins
restart: unless-stopped
ports:
- "8080:8080"
- "50000:50000"
volumes:
- jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock # 允许容器内使用Docker命令
environment:
- TZ=Asia/Shanghai
networks:
- jenkins-net
volumes:
jenkins_home:
networks:
jenkins-net:
driver: bridge
启动服务:
docker-compose up -d
http://localhost:8080
或 http://<服务器IP>:8080
docker logs jenkins
或查看指定文件:
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
配置全局安全:
设置CSRF保护:
配置代理(如果需要):
进入”Manage Jenkins” > “Manage Plugins” > “Available”,搜索并安装以下插件:
安装完成后重启Jenkins。
docker --version
我们以一个简单的Node.js应用为例:
项目结构:
my-web-app/
├── app.js
├── package.json
├── Dockerfile
└── Jenkinsfile
app.js:
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World from Dockerized Node.js app!')
})
app.listen(port, () => {
console.log(`App listening at http://localhost:${port}`)
})
package.json:
{
"name": "my-web-app",
"version": "1.0.0",
"description": "Sample Node.js web app",
"main": "app.js",
"scripts": {
"start": "node app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"express": "^4.17.1"
}
}
Dockerfile:
FROM node:14-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Jenkinsfile (声明式Pipeline):
pipeline {
agent {
docker {
image 'node:14-alpine'
args '-v /var/run/docker.sock:/var/run/docker.sock'
}
}
stages {
stage('Checkout') {
steps {
git branch: 'main', url: 'https://github.com/your-repo/my-web-app.git'
}
}
stage('Build') {
steps {
sh 'npm install'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
stage('Build Docker Image') {
steps {
script {
dockerImage = docker.build("my-web-app:${env.BUILD_ID}")
}
}
}
stage('Deploy') {
steps {
script {
docker.withRegistry('https://registry.hub.docker.com', 'docker-hub-credentials') {
dockerImage.push()
}
// 停止并移除旧容器
sh 'docker stop my-web-app || true'
sh 'docker rm my-web-app || true'
// 运行新容器
sh 'docker run -d --name my-web-app -p 3000:3000 my-web-app:${env.BUILD_ID}'
}
}
}
}
post {
always {
echo 'Cleanup workspace'
deleteDir()
}
success {
echo 'Deployment succeeded!'
}
failure {
echo 'Deployment failed!'
}
}
}
修改Deploy阶段:
stage('Deploy') {
steps {
script {
// 确定当前运行的颜色
def runningColor = sh(script: 'docker ps -f name=my-web-app --format "{{.Names}}" | grep -o "green\\|blue" || echo "blue"', returnStdout: true).trim()
def newColor = runningColor == 'blue' ? 'green' : 'blue'
// 构建带颜色的镜像标签
dockerImage = docker.build("my-web-app:${env.BUILD_ID}-${newColor}")
// 推送镜像
docker.withRegistry('https://registry.hub.docker.com', 'docker-hub-credentials') {
dockerImage.push()
}
// 启动新容器
sh "docker run -d --name my-web-app-${newColor} -p ${newColor == 'blue' ? '3000' : '3001'}:3000 my-web-app:${env.BUILD_ID}-${newColor}"
// 更新负载均衡或代理配置
// 这里需要根据你的基础设施进行调整
// 可能是更新Nginx配置或Service Mesh规则
// 停止旧容器
sh "docker stop my-web-app-${runningColor} || true"
sh "docker rm my-web-app-${runningColor} || true"
}
}
}
stage('Canary Deploy') {
steps {
script {
// 构建镜像
dockerImage = docker.build("my-web-app:${env.BUILD_ID}")
// 推送镜像
docker.withRegistry('https://registry.hub.docker.com', 'docker-hub-credentials') {
dockerImage.push()
}
// 部署金丝雀版本(例如10%流量)
sh 'docker run -d --name my-web-app-canary -p 3001:3000 -e TRAFFIC_WEIGHT=0.1 my-web-app:${env.BUILD_ID}'
// 运行自动化测试验证金丝雀版本
// ...
// 如果验证通过,全量部署
sh 'docker stop my-web-app-production || true'
sh 'docker rm my-web-app-production || true'
sh 'docker run -d --name my-web-app-production -p 3000:3000 my-web-app:${env.BUILD_ID}'
// 清理金丝雀
sh 'docker stop my-web-app-canary || true'
sh 'docker rm my-web-app-canary || true'
}
}
}
Jenkins Configuration as Code (JCasC)插件允许通过YAML文件配置Jenkins:
jenkins.yaml
:jenkins:
systemMessage: "Jenkins configured automatically by Configuration as Code"
securityRealm:
local:
allowsSignup: false
users:
- id: admin
password: ${JENKINS_ADMIN_PASSWORD}
authorizationStrategy:
globalMatrix:
permissions:
- "Overall/Administer:admin"
- "Overall/Read:authenticated"
unclassified:
location:
url: "http://jenkins.example.com/"
adminAddress: "admin@example.com"
tool:
git:
installations:
- name: Default
home: /usr/bin/git
credentials:
system:
domainCredentials:
- credentials:
- usernamePassword:
scope: SYSTEM
id: docker-hub-credentials
username: ${DOCKER_HUB_USERNAME}
password: ${DOCKER_HUB_PASSWORD}
environment:
- JENKINS_ADMIN_PASSWORD=securepassword
- DOCKER_HUB_USERNAME=yourusername
- DOCKER_HUB_PASSWORD=yourpassword
- CASC_JENKINS_CONFIG=/var/jenkins_home/jenkins.yaml
volumes:
- ./jenkins.yaml:/var/jenkins_home/jenkins.yaml
创建Docker代理模板:
在Pipeline中指定标签:
pipeline {
agent {
label 'docker-agent'
}
// ...
}
stage('Build on Dynamic Agent') {
steps {
script {
// 启动临时构建容器
def builder = docker.build('my-builder-image', '--build-arg ENV=production .')
// 在容器内执行构建
builder.inside {
sh 'make all'
}
}
}
}
Docker构建缓存:
Jenkins执行器配置:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。