Zzzxb's Blog

你要静心学习那份等待时机的成熟的情绪,也要你一定保有这份等待之外的努力和坚持。

Docker Feb 27, 2026

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参考

常用命令

# 依赖镜像
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"]
  1. 启动命令这里需要注意的是,服务不能后台运行,不然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 应用程序的工具

Compose file 参考

常用命令

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. 目录准备脚本 **

#!/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. 环境配置脚本 **

#!/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. 构建脚本 **

#!/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

部署脚本

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 '' 容器名