Docker Feb 27, 2026
- Docker build
- Docker compose
- 构建脚本
- 颜色定义
- 步骤1:检查 Docker
- 步骤2:准备目录
- 步骤3:创建环境配置
- 步骤4:构建镜像
- 步骤5:部署服务
- 停止旧服务
- 启动新服务
- 等待启动
- 检查状态
docker images # 列出所有镜像
docker images -a # 包含中间层镜像
docker pull nginx:1.21-alpine # 拉取指定版本
docker rmi nginx # 删除镜像
docker tag nginx my-nginx:v1 # 给镜像打标签
docker tag nginx:latest umyun.com/nginx:prod # 推送到私有仓库
docker inspect nginx # 查看镜像详细信息
docker run nginx # 运行容器
docker run -d nginx # 后台运行
docker run -it nginx bash # 交互模式运行
docker run --name my-nginx nginx # 指定名称
docker run --rm nginx # 运行后自动删除
docker run -p 8080:80 nginx # 端口映射
docker run -v /host/path:/container/path nginx # 挂载卷
docker run -e MY_ENV=value nginx # 设置环境变量
docker start container_name # 启动容器
docker stop container_name # 优雅停止
docker stop -t 30 container_name # 指定超时时间
docker restart container_name # 重启容器
docker pause container_name # 暂停容器
docker unpause container_name # 恢复容器
docker kill container_name # 强制停止
docker rm container_name # 删除容器
docker container prune # 删除所有停止的容器
docker ps # 查看运行中的容器
docker ps -a # 查看所有容器
docker exec -it container_name bash # 进入容器(推荐)
docker exec container_name ls /app # 执行单条命令
docker logs container_name # 查看日志
docker logs -f container_name # 实时查看(类似 tail -f)
docker logs --tail 100 container_name # 查看最后100行
docker logs --since 10m container_name # 查看最近10分钟
docker logs -t container_name # 显示时间戳
docker inspect container_name # 查看容器详细信息
docker stats # 实时查看资源使用
docker stats --no-stream # 单次查看资源使用
docker top container_name # 查看容器内进程
docker port container_name # 查看端口映射
docker diff container_name # 查看容器文件变化
Docker build
可用来将本地服务构建成镜像 Docker file参考
常用命令
docker build .使用当前目录作为构建上下文docker build ./fnp指定特定目录作为构建上下文docker build -t fnp:latest .为镜像指定名称和标签docker build -f Dockerfile.dev .使用非默认的 Dockerfile 文件名
# 依赖镜像
FROM openjdk:8u312-oraclelinux8
# 环境变量
ENV JAVA_HOME=/usr/java/openjdk-8
ENV APP_USER=umcc
ENV APP_GROUP=umcc
ENV PROJECT_NAME=fnp
# 设置固定 UID/GID(便于宿主机权限映射)
ARG USER_ID=1000
ARG GROUP_ID=1000
# 创建专用用户组和用户
RUN groupadd -g ${GROUP_ID} ${APP_GROUP} && \
useradd -u ${USER_ID} -g ${APP_GROUP} -s /sbin/nologin -M ${APP_USER}
# 创建数据卷,SpringBoot服务会在/tmp存储临时文件
VOLUME /tmp
# 创建必要目录并设置权限
RUN mkdir -p /opt/app/${PROJECT_NAME}/{bin,lib,conf,config,log,logs} && \
chown -R ${APP_USER}:${APP_GROUP} /opt/app/${PROJECT_NAME}
# 工作目录
WORKDIR /opt/app/${PROJECT_NAME}
# 将宿主机上的文件复制到容器
COPY --chown=${APP_USER}:${APP_GROUP} rms-gpd-fnp.jar ./
COPY --chown=${APP_USER}:${APP_GROUP} lib/ ./lib/
COPY --chown=${APP_USER}:${APP_GROUP} conf/ ./conf/
COPY --chown=${APP_USER}:${APP_GROUP} config/ ./config/
COPY --chown=${APP_USER}:${APP_GROUP} doc/ ./doc/
COPY --chown=${APP_USER}:${APP_GROUP} on-off.sh ./
# 设置脚本执行权限
RUN chmod +x on-off.sh
# 创建需要的目录结构(脚本需要的)
RUN mkdir -p bin && chown ${APP_USER}:${APP_GROUP} bin
# 切换到非 root 用户
USER ${APP_USER}
# 声明端口
EXPOSE 18081
# 启动命令
ENTRYPOINT ["sh", "on-off.sh"]
CMD ["start"]
启动命令这里需要注意的是,服务不能后台运行,不然Docker检查不到容器内服务运行就自己停止了
docker run -d \ --name myapp \ --add-host="redis.server:192.168.2.100" \ # B服务器的真实IP --add-host="host.docker.internal:host-gateway" myapp:latest 注意第三行:如果容器内服务需要连接其他服务器内网地址需要进行映射 注意第四行:宿主主机的映射,容器内服务就不能访问宿主主机上的服务地址需要用到此映射
Docker compose
用于定义和运行多容器 Docker 应用程序的工具
常用命令
-
docker-compose up -d启动 -
docker-compose down停止 -
docker-compose down -v停止并清理卷 -
docker-compose restart重启
version: '3.8' # docker compose 版本,默认这个就行
services:
fnp:
image: fnp:latest
container_name: umcc-fnp
user: "${CURRENT_UID:-1000}:${CURRENT_GID:-1000}"
ports:
- "18081:18081"
volumes:
- /opt/app/fnp/doc:/opt/app/fnp/doc:ro
- ./conf:/opt/app/fnp/conf:ro
- /opt/app/fnp/config:/opt/app/fnp/config:ro
- /opt/app/fnp/log:/opt/app/fnp/log
- /opt/app/fnp/pid/pid:/opt/app/fnp/bin/pid
# 临时目录 - 使用 tmpfs 提高性能和安全
- /tmp:/tmp:rw,noexec,nosuid
environment:
- PROJECT_NAME=fnp
- JAVA_HOME=/usr/java/openjdk-8
- XMS=-Xms2g
- XMX=-Xmx4g
- LOG_DIR=/opt/app/fnp/log
#restart: "no" # 从不自动重启(默认)
#restart: always # 总是重启
#restart: on-failure # 失败时重启
#restart: unless-stopped # 除非手动停止,否则总是重启
# 最大内存限制
mem_limit: 4G
# 最小内存限制
mem_reservation: 2G
# cpu分配可填写小数
cpus: 4.0
# CPU 权重(可选) 权重只在CPU紧张时生效
cpu_shares: 1024
# 容器在接收到停止信号后,允许完成关闭的宽限期
stop_grace_period: 30s
构建脚本
**1. 目录准备脚本 **
prepare-directories.sh
#!/bin/bash
set -e
PROJECT_NAME=fnp
PROJECT_DIR=/opt/app/fnp
CONTAINER=umcc-fnp
UNAME=umcc
UGROUP=umcc
echo "=== 准备宿主机目录 ==="
# 获取当前用户 UID/GID
CURRENT_UID=$(id -u)
CURRENT_GID=$(id -g)
# 创建目录结构
echo "创建目录..."
sudo mkdir -p /opt/app/${PROJECT_NAME}/{doc,config,log,pid}
# 设置目录权限
echo "设置目录权限..."
# 日志目录(容器需要写入)
echo "设置 ${PROJECT_DIR}/log 权限..."
sudo chown -R $CURRENT_UID:$CURRENT_GID ${PROJECT_DIR}/log
sudo chmod 755 ${PROJECT_DIR}/log
# PID 目录和文件
echo "设置 ${PROJECT_DIR}/pid 权限..."
sudo chown -R $CURRENT_UID:$CURRENT_GID ${PROJECT_DIR}/pid
sudo chmod 755 ${PROJECT_DIR}/pid
sudo touch ${PROJECT_DIR}/pid/pid
sudo chown $CURRENT_UID:$CURRENT_GID ${PROJECT_DIR}/pid/pid
# 文档目录(只读)
echo "设置 ${PROJECT_DIR}/doc 权限..."
sudo chown -R ${UNAME}:${UGROUP} ${PROJECT_DIR}/doc
sudo chmod 755 ${PROJECT_DIR}/doc
# 配置目录(只读)
echo "设置 /opt/app/fnp/config 权限..."
sudo chown -R ${UNAME}:${UGROUP} ${PROJECT_DIR}/config
sudo chmod 755 /opt/app/fnp/config
# 创建本地 conf 目录(如果不存在)
mkdir -p ./conf
# 显示目录结构
echo ""
echo "=== 目录结构 ==="
ls -la ${PROJECT_DIR}
echo ""
echo "/opt/app/fnp/log 权限:"
ls -ld ${PROJECT_DIR}/log
echo ""
echo "/opt/app/fnp/pid 权限:"
ls -ld ${PROJECT_DIR}/pid
ls -l ${PROJECT_DIR}/pid/
echo "✅ 目录准备完成"
**2. 环境配置脚本 **
create-env.sh
#!/bin/bash
# create-env.sh - 创建环境配置文件
set -e
echo "=== 创建环境配置文件 ==="
# 获取当前用户 UID/GID
CURRENT_UID=$(id -u)
CURRENT_GID=$(id -g)
# 创建 .env 文件
cat > .env << EOF
# Docker Compose 环境变量
CURRENT_UID=$CURRENT_UID
CURRENT_GID=$CURRENT_GID
PROJECT_NAME=fnp
# JVM 参数(可在 docker-compose.yml 中覆盖)
JAVA_HOME=/usr/java/openjdk-8
XMS=-Xms2g
XMX=-Xmx4g
LOG_DIR=/opt/app/fnp/log
# 容器资源限制(可在 docker-compose.yml 中覆盖)
MEM_LIMIT=4G
MEM_RESERVATION=2G
CPUS=4.0
CPU_SHARES=1024
EOF
echo "✅ .env 文件已创建:"
echo "=========================="
cat .env
echo "=========================="
echo ""
echo "如需修改,请编辑 .env 文件"
**3. 构建脚本 **
build-image.sh
#!/bin/bash
set -e
echo "=== 构建 FNP Docker 镜像 ==="
# 获取当前用户 UID/GID(用于权限映射)
CURRENT_UID=$(id -u)
CURRENT_GID=$(id -g)
echo "当前用户: $(whoami)"
echo "UID: $CURRENT_UID, GID: $CURRENT_GID"
# 检查必要文件是否存在
echo "检查必要文件..."
REQUIRED_FILES=("rms-gpd-fnp.jar" "on-off.sh" "lib/" "conf/" "config/" "doc/")
for file in "${REQUIRED_FILES[@]}"; do
if [ ! -e "$file" ]; then
echo "❌ 错误:缺少必要文件或目录: $file"
exit 1
fi
done
# 验证 JAR 文件
if [ ! -f "rms-gpd-fnp.jar" ]; then
echo "❌ 错误:rms-gpd-fnp.jar 文件不存在"
exit 1
fi
# 验证启动脚本
if [ ! -x "on-off.sh" ]; then
echo "设置启动脚本执行权限..."
chmod +x on-off.sh
fi
echo "文件检查通过 ✓"
# 构建镜像
echo "开始构建 Docker 镜像..."
docker build \
--build-arg USER_ID=$CURRENT_UID \
--build-arg GROUP_ID=$CURRENT_GID \
-t fnp:latest \
-t fnp:$(date +%Y%m%d_%H%M%S) \
.
# 验证构建结果
echo "验证镜像..."
if docker image inspect fnp:latest &>/dev/null; then
echo "✅ 镜像构建成功:fnp:latest"
# 显示镜像信息
echo ""
echo "=== 镜像信息 ==="
docker images fnp:latest
# 测试启动
echo ""
echo "=== 测试启动 ==="
docker run --rm fnp:latest sh -c "id && ls -la /opt/app/fnp/"
else
echo "❌ 镜像构建失败"
exit 1
fi
部署脚本
deploy.sh```bash #!/bin/bash
set -e
PROJECT_NAME=fnp PROJECT_DIR=/opt/app/fnp CONTAINER=umcc-fnp
echo “=== ${PROJECT_NAME} 服务一键部署 ===”
颜色定义
RED=’\033[0;31m’ GREEN=’\033[0;32m’ YELLOW=’\033[1;33m’ NC=’\033[0m’ # No Color
步骤1:检查 Docker
echo -e “${YELLOW}[1/5] 检查 Docker 环境…${NC}” if ! command -v docker &> /dev/null; then echo -e “${RED}❌ Docker 未安装${NC}” exit 1 fi
if ! command -v docker-compose &> /dev/null; then echo -e “${RED}❌ Docker Compose 未安装${NC}” exit 1 fi echo -e “${GREEN}✓ Docker 环境正常${NC}”
步骤2:准备目录
echo -e “${YELLOW}[2/5] 准备目录…${NC}” ./prepare-directories.sh
步骤3:创建环境配置
echo -e “${YELLOW}[3/5] 创建环境配置…${NC}” ./create-env.sh
步骤4:构建镜像
echo -e “${YELLOW}[4/5] 构建镜像…${NC}” ./build-image.sh
步骤5:部署服务
echo -e “${YELLOW}[5/5] 部署服务…${NC}”
停止旧服务
echo “停止旧服务…” docker-compose down 2>/dev/null || true
启动新服务
echo “启动服务…” docker-compose up -d
等待启动
echo “等待服务启动…” sleep 15
检查状态
if docker ps | grep -q umcc-fnp; then echo -e “${GREEN}✅ 服务启动成功!${NC}”
# 显示服务信息
echo ""
echo "================================"
echo " ${PROJECT_NAME} 服务信息"
echo "================================"
echo "容器名称: ${CONTAINER}"
echo "日志目录: /opt/app/${PROJECT_NAME}/log"
echo "PID 文件: /opt/app/${PROJECT_NAME}/pid/pid"
echo ""
echo "常用命令:"
echo " 查看日志: docker logs -f ${CONTAINER}"
echo " 进入容器: docker exec -it ${CONTAINER} bash"
echo " 停止服务: docker-compose down"
echo " 重启服务: docker-compose restart"
echo "================================"
# 显示资源使用
echo ""
echo "资源限制:"
docker inspect umcc-fnp --format \
' ' | \
awk '{printf "内存限制: %.1fG\n内存预留: %.1fG\nCPU限制: %.1f核\nCPU权重: %d\n",
$1/1024/1024/1024, $2/1024/1024/1024, $3/1000000000, $4}'
# 查看启动日志
echo ""
echo "最近日志:"
docker logs --tail 10 ${CONTAINER}
else echo -e “${RED}❌ 服务启动失败!${NC}” echo “查看错误日志:” docker logs ${CONTAINER} exit 1 fi
### **管理脚本**
* `manage.sh`
```bash
#!/bin/bash
set -e
PROJECT_NAME=fnp
PROJECT_DIR=/opt/app/fnp
CONTAINER=umcc-fnp
function show_usage() {
echo "${PROJECT_NAME} 服务管理脚本"
echo "用法: $0 {start|stop|restart|status|logs|shell|update|clean}"
echo ""
echo "命令:"
echo " start 启动服务"
echo " stop 停止服务"
echo " restart 重启服务"
echo " status 查看状态"
echo " logs 查看日志"
echo " shell 进入容器"
echo " update 更新并重启"
echo " clean 清理旧镜像"
}
function start_service() {
echo "启动 ${CONTAINER} 服务..."
docker-compose up -d
sleep 5
status_service
}
function stop_service() {
echo "停止 ${CONTAINER} 服务..."
docker-compose down
}
function restart_service() {
echo "重启 ${CONTAINER} 服务..."
docker-compose restart
sleep 5
status_service
}
function status_service() {
echo "=== 服务状态 ==="
if docker ps | grep -q ${CONTAINER}; then
echo -e "状态: \033[32m运行中\033[0m"
# 获取容器信息
CONTAINER_ID=$(docker ps -q --filter "name=${CONTAINER}")
echo "容器ID: ${CONTAINER_ID:0:12}"
echo "启动时间: $(docker inspect -f '' ${CONTAINER} | cut -d'T' -f1)"
echo "运行时长: $(docker inspect -f ' ' ${CONTAINER})"
# 检查进程
if docker exec ${CONTAINER} sh -c "test -f ${PROJECT_DIR}/bin/pid && ps -p \$(cat ${PROJECT_DIR}/bin/pid)" &>/dev/null; then
echo "应用进程: 正常"
else
echo "应用进程: 异常"
fi
# 资源使用
echo ""
echo "=== 资源使用 ==="
docker stats --no-stream ${CONTAINER} | tail -1 | awk '{print "CPU: "$2", 内存: "$3"/"$4}'
else
echo -e "状态: 未运行"
fi
}
function show_logs() {
echo "查看日志 (Ctrl+C 退出)..."
docker logs -f ${CONTAINER}
}
function enter_shell() {
echo "进入容器 shell..."
docker exec -it ${CONTAINER} sh
}
function update_service() {
echo "更新服务..."
./build-image.sh
docker-compose down
docker-compose up -d
echo "更新完成"
}
function clean_images() {
echo "清理无用镜像..."
docker image prune -f
echo "已清理的镜像:"
docker images --filter "dangling=true"
}
case "$1" in
start)
start_service
;;
stop)
stop_service
;;
restart)
restart_service
;;
status)
status_service
;;
logs)
show_logs
;;
shell)
enter_shell
;;
update)
update_service
;;
clean)
clean_images
;;
*)
show_usage
exit 1
;;
esac
CPU分配
Java 应用经验法则
| 应用类型 | CPU 需求 | 内存需求 | 说明 |
|---|---|---|---|
| 小型服务 | 0.5-1 核 | 1-2 GB | 简单 CRUD,低并发 |
| 中型服务 | 1-2 核 | 2-4 GB | 业务逻辑复杂,中等并发 |
| 大型服务 | 2-4 核 | 4-8 GB | 计算密集,高并发 |
| 计算密集型 | 4+ 核 | 8+ GB | 数据处理、批量任务 |
Docker install
安装
# yum 增强工具
sudo yum install -y yum-utils
# 添加阿里云Docker仓库
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装最新版本
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 或者安装特定版本
sudo yum install -y docker-ce-<VERSION> docker-ce-cli-<VERSION> containerd.io
# 启动Docker
sudo systemctl start docker
# 设置开机自启
sudo systemctl enable docker
# 查看Docker状态
sudo systemctl status docker
# 重启Docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker
# 查看Docker版本
docker version
# 查看详细信息
docker info
docker版本信息(测试时使用的)
[root@iZuf67p7qk4cx1osxgoj87Z yum.repos.d]# docker version
Client: Docker Engine - Community
Version: 26.1.4
API version: 1.45
Go version: go1.21.11
Git commit: 5650f9b
Built: Wed Jun 5 11:32:04 2024
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 26.1.4
API version: 1.45 (minimum version 1.24)
Go version: go1.21.11
Git commit: de5c9cf
Built: Wed Jun 5 11:31:02 2024
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.33
GitCommit: d2d58213f83a351ca8f528a95fbd145f5654e957
runc:
Version: 1.1.12
GitCommit: v1.1.12-0-g51d5e94
docker-init:
Version: 0.19.0
GitCommit: de40ad0
自定义配置
# 创建配置文件目录
sudo mkdir -p /etc/docker
vim /etc/docker/daemon.json
删除
# 停止服务
sudo systemctl stop docker
# 卸载软件包
sudo yum remove docker-ce docker-ce-cli containerd.io
# 删除相关文件
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
关于网络访问
使用 Docker 网络
# 创建网络
docker network create mynetwork
# 运行容器时加入同一网络
docker run -d --name web --network mynetwork nginx
docker run -d --name redis --network mynetwork redis:alpine
使用主机网络模式(–network host)
--add-host="redis.server:192.168.2.100" \ # B服务器的真实IP
--add-host="host.docker.internal:host-gateway" # 宿主主机地址
Inspect 查看容器内网IP
# 查看容器IP
docker inspect -f '' 容器名