我的一次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,并优化镜像层顺序,把依赖安装和应用代码分离,提升了构建和启动速度。
经过三周的努力,系统终于实现了自动化构建、测试和部署。发布频率从每周一次提升到每天多次,环境一致性问题也消失了。说实话,这次实战让我深刻体会到容器化部署的价值,虽然踩了不少坑,但收获很大。
本文基于实际项目经验整理,欢迎在评论区交流技术问题。
网硕互联帮助中心




评论前必须登录!
注册