Oinone Pamirs容器化部署:Docker Compose编排实战
前言:企业级应用容器化的必然选择
在当今云原生时代,传统的单体应用部署方式已经无法满足企业级应用的快速迭代和弹性伸缩需求。Oinone Pamirs作为一款企业级产品化引擎,采用容器化部署能够带来以下核心优势:
- 环境一致性:消除"在我本地是好的"问题,确保开发、测试、生产环境完全一致
- 快速部署:一键启动完整服务栈,大幅缩短部署时间
- 资源隔离:每个服务独立运行,避免资源冲突和依赖污染
- 弹性伸缩:根据业务负载动态调整服务实例数量
- 高可用性:通过容器编排实现服务自动恢复和负载均衡
本文将深入讲解如何将Oinone Pamirs项目通过Docker Compose进行完整的容器化部署。
技术架构与组件分析
Oinone Pamirs核心组件
依赖服务矩阵
| 服务组件 | 版本要求 | 容器镜像 | 默认端口 |
|---|---|---|---|
| MySQL | 5.7+ | mysql:5.7 | 3306 |
| Redis | 6.0+ | redis:6-alpine | 6379 |
| Nacos | 2.0+ | nacos/nacos-server:2.0.3 | 8848 |
| 消息队列 | 4.6+ | 消息队列镜像:4.6.0 | 9876,10909,10911 |
环境准备与前置条件
系统要求
- Docker Engine 20.10+
- Docker Compose 2.0+
- 至少4GB可用内存
- 至少10GB可用磁盘空间
目录结构规划
oinone-pamirs-deploy/
├── docker-compose.yml # Docker Compose编排文件
├── .env # 环境变量配置文件
├── config/ # 应用配置文件目录
│ ├── application.yml # 主配置文件
│ └── bootstrap.yml # 启动配置文件
├── scripts/ # 部署脚本目录
│ ├── init-database.sql # 数据库初始化脚本
│ └── wait-for-it.sh # 服务等待脚本
├── logs/ # 日志目录
└── data/ # 数据持久化目录
├── mysql/ # MySQL数据目录
├── redis/ # Redis数据目录
└── nacos/ # Nacos数据目录
Dockerfile构建应用镜像
基础Dockerfile配置
# 使用OpenJDK 8基础镜像
FROM openjdk:8-jdk-alpine
# 维护者信息
LABEL maintainer="oinone@shushi.pro"
# 设置工作目录
WORKDIR /app
# 添加JAR包到容器
COPY target/pamirs-*.jar app.jar
# 暴露应用端口
EXPOSE 8080
# 配置JVM参数
ENV JAVA_OPTS="-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom"
# 创建非root用户运行
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
# 启动命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
多阶段构建优化
# 第一阶段:构建阶段
FROM maven:3.8.4-openjdk-8 AS builder
WORKDIR /build
COPY . .
RUN mvn clean package -DskipTests
# 第二阶段:运行阶段
FROM openjdk:8-jdk-alpine
WORKDIR /app
COPY --from=builder /build/target/pamirs-*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Docker Compose编排配置
完整的docker-compose.yml
version: '3.8'
services:
# MySQL数据库服务
mysql:
image: mysql:5.7
container_name: pamirs-mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
ports:
- "3306:3306"
volumes:
- ./data/mysql:/var/lib/mysql
- ./scripts/init-database.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- pamirs-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 3
# Redis缓存服务
redis:
image: redis:6-alpine
container_name: pamirs-redis
ports:
- "6379:6379"
volumes:
- ./data/redis:/data
command: redis-server --appendonly yes
networks:
- pamirs-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
# Nacos配置中心
nacos:
image: nacos/nacos-server:2.0.3
container_name: pamirs-nacos
environment:
MODE: standalone
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: mysql
MYSQL_SERVICE_PORT: 3306
MYSQL_SERVICE_DB_NAME: nacos
MYSQL_SERVICE_USER: ${MYSQL_USER}
MYSQL_SERVICE_PASSWORD: ${MYSQL_PASSWORD}
ports:
- "8848:8848"
volumes:
- ./data/nacos:/home/nacos/logs
networks:
- pamirs-network
depends_on:
mysql:
condition: service_healthy
# 消息队列服务
mq:
image: 消息队列镜像:4.6.0
container_name: pamirs-mq
ports:
- "9876:9876"
- "10909:10909"
- "10911:10911"
volumes:
- ./data/mq/logs:/home/mq/logs
- ./data/mq/store:/home/mq/store
command: sh mqnamesrv
networks:
- pamirs-network
# Oinone Pamirs应用服务
pamirs-app:
build: .
container_name: pamirs-application
environment:
SPRING_PROFILES_ACTIVE: docker
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=utf8&useSSL=false
SPRING_DATASOURCE_USERNAME: ${MYSQL_USER}
SPRING_DATASOURCE_PASSWORD: ${MYSQL_PASSWORD}
SPRING_REDIS_HOST: redis
SPRING_REDIS_PORT: 6379
SPRING_CLOUD_NACOS_CONFIG_SERVER_ADDR: nacos:8848
ports:
- "8080:8080"
volumes:
- ./logs:/app/logs
networks:
- pamirs-network
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
nacos:
condition: service_started
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
networks:
pamirs-network:
driver: bridge
环境变量配置文件(.env)
# MySQL配置
MYSQL_ROOT_PASSWORD=root123456
MYSQL_DATABASE=pamirs_db
MYSQL_USER=pamirs_user
MYSQL_PASSWORD=pamirs_pass123
# 应用配置
SPRING_PROFILES_ACTIVE=docker
JAVA_OPTS=-Xms512m -Xmx1024m
# 网络配置
APP_PORT=8080
MYSQL_PORT=3306
REDIS_PORT=6379
NACOS_PORT=8848
应用配置优化
Nacos配置中心配置
# application-docker.yml
spring:
datasource:
url: jdbc:mysql://mysql:3306/pamirs_db?useUnicode=true&characterEncoding=utf8&useSSL=false
username: pamirs_user
password: pamirs_pass123
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
redis:
host: redis
port: 6379
database: 0
timeout: 3000ms
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
cloud:
nacos:
config:
server-addr: nacos:8848
file-extension: yaml
group: DEFAULT_GROUP
namespace: public
discovery:
server-addr: nacos:8848
# MyBatis Plus配置
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 日志配置
logging:
level:
pro.shushi.pamirs: DEBUG
org.springframework: INFO
file:
name: /app/logs/application.log
pattern:
file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
数据库初始化脚本
-- init-database.sql
CREATE DATABASE IF NOT EXISTS pamirs_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS nacos CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'pamirs_user'@'%' IDENTIFIED BY 'pamirs_pass123';
GRANT ALL PRIVILEGES ON pamirs_db.* TO 'pamirs_user'@'%';
GRANT ALL PRIVILEGES ON nacos.* TO 'pamirs_user'@'%';
FLUSH PRIVILEGES;
-- 初始化Nacos需要的表结构
USE nacos;
SOURCE /tmp/nacos-mysql.sql;
部署流程与操作指南
一键部署脚本
#!/bin/bash
# deploy.sh
echo "开始部署Oinone Pamirs容器化环境..."
# 检查Docker和Docker Compose
if ! command -v docker &> /dev/null; then
echo "错误: Docker未安装"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
echo "错误: Docker Compose未安装"
exit 1
fi
# 创建必要的目录
mkdir -p data/mysql data/redis data/nacos data/mq/{logs,store} logs config scripts
# 构建应用镜像
echo "构建应用镜像..."
docker-compose build
# 启动所有服务
echo "启动服务栈..."
docker-compose up -d
# 等待服务启动
echo "等待服务启动..."
sleep 30
# 检查服务状态
echo "检查服务状态:"
docker-compose ps
echo "部署完成!"
echo "应用访问地址: http://localhost:8080"
echo "Nacos控制台: http://localhost:8848/nacos"
服务管理命令
# 启动所有服务
docker-compose up -d
# 停止所有服务
docker-compose down
# 查看服务状态
docker-compose ps
# 查看应用日志
docker-compose logs -f pamirs-app
# 重启单个服务
docker-compose restart pamirs-app
# 进入容器调试
docker-compose exec pamirs-app sh
# 查看资源使用情况
docker stats
# 备份数据
docker-compose exec mysql mysqldump -u root -p${MYSQL_ROOT_PASSWORD} pamirs_db > backup.sql
监控与运维
健康检查端点
Oinone Pamirs提供了完整的健康检查端点:
| 端点 | 描述 | 访问方式 |
|---|---|---|
| /actuator/health | 应用健康状态 | GET |
| /actuator/info | 应用信息 | GET |
| /actuator/metrics | 性能指标 | GET |
| /actuator/env | 环境变量 | GET |
日志收集配置
# logback-spring.xml
<configuration>
<property name="LOG_PATH" value="/app/logs"/>
<property name="LOG_FILE" value="${LOG_PATH}/application.log"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/application.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
</configuration>
常见问题排查
问题1:数据库连接失败
症状:应用启动时报数据库连接错误 解决方案:
# 检查MySQL容器状态
docker-compose logs mysql
# 检查网络连通性
docker-compose exec pamirs-app ping mysql
# 手动测试数据库连接
docker-compose exec mysql mysql -u pamirs_user -ppamirs_pass123 pamirs_db
问题2:Nacos配置无法加载
症状:应用启动时报Nacos连接超时 解决方案:
# 检查Nacos服务状态
curl http://localhost:8848/nacos/v1/ns/instance/list
# 查看Nacos日志
docker-compose logs nacos
# 检查Nacos数据库连接
docker-compose exec mysql mysql -u root -proot123456 nacos -e "SHOW TABLES;"
问题3:内存不足
症状:容器频繁重启,OOM错误 解决方案:
# 调整JVM内存参数
environment:
JAVA_OPTS: "-Xms1g -Xmx2g -XX:MaxMetaspaceSize=512m"
性能优化建议
1. JVM调优参数
environment:
JAVA_OPTS: >
-Xms2g
-Xmx2g
-XX:MaxMetaspaceSize=512m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:ParallelGCThreads=4
-XX:ConcGCThreads=2
-XX:InitiatingHeapOccupancyPercent=70
2. 数据库连接池优化
spring:
datasource:
druid:
initial-size: 10
min-idle: 10
max-active: 50
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1
test-while-idle: true
test-on-borrow: false
test-on-return: false
3. Redis连接池优化
spring:
redis:
lettuce:
pool:
max-active: 20
max-idle: 10
min-idle: 5
max-wait: 3000ms
time-between-eviction-runs: 60s
安全加固措施
1. 网络隔离
networks:
pamirs-internal:
internal: true
pamirs-external:
driver: bridge
services:
mysql:
networks:
- pamirs-internal
redis:
networks:
- pamirs-internal
pamirs-app:
networks:
- pamirs-internal
- pamirs-external
2. 安全环境变量
# 使用Docker Secrets管理敏感信息
echo "strong_password_123" | docker secret create mysql_root_password -
3. 镜像安全扫描
# 定期扫描镜像漏洞
docker scan pamirs-app
# 使用最小化基础镜像
FROM openjdk:8-jre-alpine
总结与展望
通过本文的Docker Compose编排实战,我们实现了Oinone Pamirs企业级应用的全栈容器化部署。这种部署方式不仅提高了部署效率,还增强了系统的可维护性和可扩展性。
部署收益总结:
- ✅ 环境一致性:开发、测试、生产环境完全一致
- ✅ 快速部署:从代码到运行环境只需几分钟
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



