云计算百科
云计算领域专业知识百科平台

Docker容器化部署实战:从手动部署到自动化流水线

我的一次Docker容器化部署实战:踩坑实录(耗时3周)

前不久接了一个项目,客户是一家中小型电商公司,他们的系统部署全靠手动操作,经常出现环境问题,导致发布延迟。我决定帮他们搭建Docker容器化部署,从手动部署过渡到自动化流水线。

手动部署的痛点与决策

客户的生产环境是几台Linux服务器,每次发布都要运维手动打包、上传、重启服务。说实话,这种模式效率极低,而且容易出错。有一次因为环境变量配置错误,整个系统挂了两个小时,客户投诉不断。更头疼的是,开发环境和生产环境不一致,代码在本地跑得好好的,上线就报错。客户希望我们能实现自动化构建和部署,减少人为干预。

当时我面临两个方案:一是直接上Kubernetes集群,二是用Docker加Jenkins搭建CI/CD流水线。说实话,K8s虽然强大,但学习成本高,运维复杂,而且客户团队只有三个人,没有专门负责K8s的运维。试了一圈发现,Docker加Jenkins更轻量,能快速实现自动化,成本也低。我选了方案B,因为项目规模不大,快速落地更重要。另外,客户预算有限,K8s的硬件成本也高,Docker方案更经济。

容器化与流水线搭建

我开始写Dockerfile,把应用打包成镜像。核心代码如下:

```dockerfileFROM openjdk:11-jre-slimWORKDIR /appCOPY target/*.jar app.jarEXPOSE 8080ENTRYPOINT ["java","-jar","/app/app.jar"]```

有意思的是,我发现用slim镜像能减少镜像大小,但有些依赖包在slim版本里缺失,导致应用启动失败。当时我觉得这样就行,结果发现错了。后来换成openjdk:11-jdk-slim,问题解决。另外,我还添加了多阶段构建,进一步压缩镜像体积:

```dockerfileFROM maven:3.8.4-openjdk-11 AS buildWORKDIR /appCOPY pom.xml .COPY src ./srcRUN mvn clean package -DskipTests

FROM openjdk:11-jre-slimWORKDIR /appCOPY –from=build /app/target/*.jar app.jarEXPOSE 8080ENTRYPOINT ["java","-jar","/app/app.jar"]```

接着配置Jenkins流水线。Jenkinsfile内容如下:

```groovypipeline {agent anystages {stage('Checkout') {steps {checkout scm}}stage('Build') {steps {sh 'mvn clean package -DskipTests'}}stage('Docker Build') {steps {sh 'docker build -t myapp:${BUILD_NUMBER} .'}}stage('Deploy') {steps {sh 'docker stop myapp || true && docker rm myapp || true'sh 'docker run -d -p 8080:8080 –name myapp myapp:${BUILD_NUMBER}'}}}}```

坑死了,Jenkins在部署阶段执行docker命令时,总是报权限错误。排查后发现,Jenkins用户不在docker组里。解决办法是给Jenkins用户添加docker组权限:sudo usermod -aG docker jenkins,然后重启Jenkins服务。另外,我还配置了SSH免密登录,让Jenkins能安全地部署到多台服务器。

为了管理多容器应用,我引入了docker-compose。docker-compose.yml配置:

```yamlversion: '3.8'services:app:image: myapp:latestports:

  • "8080:8080"

depends_on:

  • db
  • redis

environment:

  • DB_HOST=db
  • REDIS_HOST=redis

db:image: mysql:8.0environment:MYSQL_ROOT_PASSWORD: rootMYSQL_DATABASE: mydbvolumes:

  • db_data:/var/lib/mysql

redis:image: redis:alpinevolumes:

  • redis_data:/data

volumes:db_data:redis_data:```

部署时,一条命令docker-compose up -d就能拉起所有服务。这比手动启动容器方便多了。我还配置了Jenkins流水线调用docker-compose,实现一键部署。

配置Jenkins时,我安装了Docker插件和Pipeline插件。还配置了Docker Registry凭证,避免每次拉取镜像都要登录。在Jenkins系统配置里,我添加了Docker服务器地址和认证信息,这样流水线就能自动推送镜像到私有仓库。

Docker网络方面,为了让容器间通信,我创建了自定义网络:docker network create myapp-network。然后在docker-compose.yml中指定网络:

```yamlnetworks:default:external:name: myapp-network```

这样app、db、redis容器都在同一网络,可以通过服务名互相访问。

性能上,我发现容器启动慢,后来发现是Java应用初始化慢。通过调整JVM参数,比如-Xms256m -Xmx512m,并优化镜像层顺序,把依赖安装和应用代码分离,提升了构建和启动速度。

经过三周的努力,系统终于实现了自动化构建、测试和部署。发布频率从每周一次提升到每天多次,环境一致性问题也消失了。说实话,这次实战让我深刻体会到容器化部署的价值,虽然踩了不少坑,但收获很大。

本文基于实际项目经验整理,欢迎在评论区交流技术问题。

赞(0)
未经允许不得转载:网硕互联帮助中心 » Docker容器化部署实战:从手动部署到自动化流水线
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!