本文是 Linux 系列教程,从基础到进阶,附完整代码示例,收藏备用!
一、前言
Docker 容器化技术已经成为现代应用部署的标准方案,配合宝塔面板的可视化管理,可以大幅降低运维门槛。本文将介绍如何在宝塔面板中集成 Docker,实现应用的一键容器化部署。
学完本文,你将掌握:
- Docker 在宝塔面板中的安装与配置
- 常用服务的 Docker 化部署(Nginx、MySQL、Redis)
- Spring Boot 应用的容器化打包与部署
- Docker Compose 多服务编排
- 数据持久化与备份策略
二、环境准备
2.1 安装宝塔面板
bash
# CentOS 安装命令
yum install -y wget && wget -O install.sh https://download.bt.cn/install/install_6.0.sh && sh install.sh ed8484bec
# Ubuntu/Debian 安装命令
wget -O install.sh https://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh ed8484bec
安装完成后访问面板地址,安装推荐的 LNMP 套件。
2.2 安装 Docker
宝塔面板 8.0+ 版本已内置 Docker 管理器:
- 登录宝塔面板 → 软件商店 → 搜索 "Docker"
- 安装 "Docker管理器" 和 "Docker Compose"
或手动安装:
bash
# 一键安装 Docker
curl -fsSL https://get.docker.com | bash
# 启动 Docker
systemctl start docker
systemctl enable docker
# 安装 Docker Compose
pip3 install docker-compose
# 验证安装
docker --version
docker-compose --version
2.3 配置镜像加速
bash
# 创建/编辑配置文件
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
EOF
# 重启 Docker
systemctl daemon-reload
systemctl restart docker
三、Docker 基础命令
3.1 镜像管理
bash
# 搜索镜像
docker search nginx
# 拉取镜像
docker pull nginx:latest
docker pull mysql:8.0
# 查看本地镜像
docker images
# 删除镜像
docker rmi nginx:latest
# 导出/导入镜像
docker save -o nginx.tar nginx:latest
docker load -i nginx.tar
3.2 容器管理
bash
# 运行容器
docker run -d \
--name my-nginx \
-p 80:80 \
-v /www/nginx/html:/usr/share/nginx/html \
-v /www/nginx/conf:/etc/nginx/conf.d \
nginx:latest
# 参数说明:
# -d: 后台运行
# --name: 容器名称
# -p: 端口映射(主机端口:容器端口)
# -v: 目录挂载(主机目录:容器目录)
# -e: 环境变量
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a
# 启动/停止/重启容器
docker start my-nginx
docker stop my-nginx
docker restart my-nginx
# 进入容器
docker exec -it my-nginx /bin/bash
# 查看容器日志
docker logs -f my-nginx
# 删除容器
docker rm my-nginx
docker rm -f my-nginx # 强制删除运行中的容器
四、常用服务部署
4.1 Nginx 部署
bash
# 创建目录
mkdir -p /www/docker/nginx/{html,conf,logs}
# 创建默认配置
cat > /www/docker/nginx/conf/default.conf <<EOF
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /api/ {
proxy_pass http://backend:8080/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
}
}
EOF
# 运行 Nginx 容器
docker run -d \
--name nginx \
--restart always \
-p 80:80 \
-p 443:443 \
-v /www/docker/nginx/html:/usr/share/nginx/html \
-v /www/docker/nginx/conf:/etc/nginx/conf.d \
-v /www/docker/nginx/logs:/var/log/nginx \
nginx:alpine
4.2 MySQL 部署
bash
# 创建目录
mkdir -p /www/docker/mysql/{data,conf,logs}
# 运行 MySQL 容器
docker run -d \
--name mysql \
--restart always \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=YourStrongPassword \
-e MYSQL_DATABASE=myapp \
-v /www/docker/mysql/data:/var/lib/mysql \
-v /www/docker/mysql/conf:/etc/mysql/conf.d \
-v /www/docker/mysql/logs:/var/log/mysql \
mysql:8.0 \
--default-authentication-plugin=mysql_native_password \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
# 创建自定义配置文件
cat > /www/docker/mysql/conf/custom.cnf <<EOF
[mysqld]
max_connections = 500
innodb_buffer_pool_size = 1G
query_cache_size = 64M
slow_query_log = 1
long_query_time = 2
EOF
# 重启生效
docker restart mysql
4.3 Redis 部署
bash
# 创建目录
mkdir -p /www/docker/redis/{data,conf}
# 创建配置文件
cat > /www/docker/redis/conf/redis.conf <<EOF
bind 0.0.0.0
port 6379
requirepass YourRedisPassword
maxmemory 512mb
maxmemory-policy allkeys-lru
appendonly yes
appendfsync everysec
EOF
# 运行 Redis 容器
docker run -d \
--name redis \
--restart always \
-p 6379:6379 \
-v /www/docker/redis/data:/data \
-v /www/docker/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \
redis:alpine \
redis-server /usr/local/etc/redis/redis.conf
4.4 MongoDB 部署
bash
mkdir -p /www/docker/mongodb/data
docker run -d \
--name mongodb \
--restart always \
-p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=YourMongoPassword \
-v /www/docker/mongodb/data:/data/db \
mongo:6.0
五、Spring Boot 应用容器化
5.1 编写 Dockerfile
dockerfile
# 多阶段构建
FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /app
COPY . .
RUN ./mvnw clean package -DskipTests
# 运行阶段
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
# 创建非 root 用户
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
# 复制 jar 包
COPY --from=builder /app/target/*.jar app.jar
# JVM 参数
ENV JAVA_OPTS="-Xms512m -Xmx512m -XX:+UseG1GC"
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
5.2 构建并推送镜像
bash
# 登录镜像仓库
docker login registry.cn-hangzhou.aliyuncs.com
# 构建镜像
docker build -t myapp:1.0.0 .
# 打标签
docker tag myapp:1.0.0 registry.cn-hangzhou.aliyuncs.com/myrepo/myapp:1.0.0
# 推送镜像
docker push registry.cn-hangzhou.aliyuncs.com/myrepo/myapp:1.0.0
5.3 部署应用
bash
# 运行应用容器
docker run -d \
--name myapp \
--restart always \
-p 8080:8080 \
-e SPRING_PROFILES_ACTIVE=prod \
-e SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/myapp \
-e SPRING_DATASOURCE_USERNAME=root \
-e SPRING_DATASOURCE_PASSWORD=YourPassword \
-e SPRING_REDIS_HOST=redis \
-e SPRING_REDIS_PASSWORD=YourRedisPassword \
--link mysql:mysql \
--link redis:redis \
myapp:1.0.0
六、Docker Compose 编排
6.1 编写 docker-compose.yml
yaml
version: '3.8'
services:
nginx:
image: nginx:alpine
container_name: nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/html:/usr/share/nginx/html
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/logs:/var/log/nginx
- ./nginx/ssl:/etc/nginx/ssl
networks:
- app-network
depends_on:
- app
mysql:
image: mysql:8.0
container_name: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/var/log/mysql
- ./mysql/init:/docker-entrypoint-initdb.d
networks:
- app-network
command: >
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
redis:
image: redis:alpine
container_name: redis
restart: always
command: redis-server --requirepass ${REDIS_PASSWORD}
ports:
- "6379:6379"
volumes:
- ./redis/data:/data
networks:
- app-network
app:
image: ${APP_IMAGE}:${APP_VERSION}
container_name: myapp
restart: always
environment:
SPRING_PROFILES_ACTIVE: prod
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/${DB_NAME}
SPRING_DATASOURCE_USERNAME: ${DB_USER}
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
SPRING_REDIS_HOST: redis
SPRING_REDIS_PASSWORD: ${REDIS_PASSWORD}
JAVA_OPTS: "-Xms512m -Xmx512m -XX:+UseG1GC"
networks:
- app-network
depends_on:
- mysql
- redis
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
app-network:
driver: bridge
6.2 环境变量文件 .env
bash
# 数据库配置
DB_ROOT_PASSWORD=Root@123456
DB_NAME=myapp
DB_USER=appuser
DB_PASSWORD=App@123456
# Redis 配置
REDIS_PASSWORD=Redis@123456
# 应用配置
APP_IMAGE=registry.cn-hangzhou.aliyuncs.com/myrepo/myapp
APP_VERSION=1.0.0
6.3 Compose 常用命令
bash
# 启动所有服务(后台运行)
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f app
# 重启服务
docker-compose restart app
# 停止服务
docker-compose stop
# 停止并删除容器
docker-compose down
# 停止并删除容器和数据卷(慎用)
docker-compose down -v
# 重新构建并启动
docker-compose up -d --build
# 扩展服务实例数
docker-compose up -d --scale app=3
七、数据备份与恢复
7.1 MySQL 自动备份脚本
bash
#!/bin/bash
# /www/docker/mysql/backup/backup.sh
BACKUP_DIR="/www/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="myapp"
RETENTION_DAYS=7
# 创建备份目录
mkdir -p $BACKUP_DIR
# 执行备份
docker exec mysql mysqldump -u root -p'YourPassword' \
--single-transaction \
--routines \
--triggers \
$DB_NAME > $BACKUP_DIR/${DB_NAME}_${DATE}.sql
# 压缩备份文件
gzip $BACKUP_DIR/${DB_NAME}_${DATE}.sql
# 删除过期备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: ${DB_NAME}_${DATE}.sql.gz"
7.2 添加定时任务
bash
# 编辑 crontab
crontab -e
# 每天凌晨 2 点备份
0 2 * * * /www/docker/mysql/backup/backup.sh >> /var/log/mysql_backup.log 2>&1
7.3 数据恢复
bash
# 解压备份文件
gunzip myapp_20240115_020000.sql.gz
# 恢复数据
docker exec -i mysql mysql -u root -p'YourPassword' myapp < myapp_20240115_020000.sql
八、监控与日志
8.1 部署 Portainer(Docker 可视化管理)
bash
# 创建数据卷
docker volume create portainer_data
# 运行 Portainer
docker run -d \
--name portainer \
--restart always \
-p 9000:9000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
访问 http://服务器IP:9000 进行初始化设置。
8.2 日志收集方案
yaml
# docker-compose.yml 添加日志服务
services:
# ... 其他服务
loki:
image: grafana/loki:latest
container_name: loki
restart: always
ports:
- "3100:3100"
volumes:
- ./loki/config:/etc/loki
command: -config.file=/etc/loki/loki-config.yaml
networks:
- app-network
promtail:
image: grafana/promtail:latest
container_name: promtail
restart: always
volumes:
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./promtail/config:/etc/promtail
command: -config.file=/etc/promtail/promtail-config.yaml
networks:
- app-network
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: always
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
networks:
- app-network
九、常见问题
❌ 问题1:容器无法访问外部网络
解决:
bash
# 检查 Docker 网络
iptables -L -n -v
# 开启 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
❌ 问题2:MySQL 中文乱码
解决:
bash
# 进入容器修改配置
docker exec -it mysql bash
# 修改 my.cnf
echo '[mysqld]' >> /etc/mysql/my.cnf
echo 'character-set-server=utf8mb4' >> /etc/mysql/my.cnf
echo 'collation-server=utf8mb4_unicode_ci' >> /etc/mysql/my.cnf
docker restart mysql
❌ 问题3:容器时区不正确
解决:
bash
# 运行容器时挂载时区文件
docker run -d \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/timezone:/etc/timezone:ro \
...
# 或在 Dockerfile 中设置
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
❌ 问题4:磁盘空间不足
bash
# 清理未使用的镜像、容器、卷
docker system prune -a -f --volumes
# 查看占用空间
docker system df -v
十、总结
Docker + 宝塔部署方案对比:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 宝塔原生 | 可视化操作,适合新手 | 灵活性差 |
| Docker 单容器 | 简单快速 | 服务多时不便管理 |
| Docker Compose | 编排方便,配置清晰 | 需要学习 YAML |
| K8s | 大规模集群管理 | 复杂度高 |
推荐方案:中小型项目使用 Docker Compose,配合宝塔的文件管理和计划任务功能,实现高效运维。
💬 觉得有用的话,点个赞+收藏,关注我,每周持续更新实战教程!
标签:docker | linux | 宝塔 | 运维 | 容器化 | 部署