Docker

返回运维工具

容器化平台,将应用及其依赖打包为镜像,实现「一次构建,到处运行」。


核心概念

概念说明
镜像(Image)只读模板,包含运行应用所需的一切
容器(Container)镜像的运行实例,相互隔离
仓库(Registry)存储和分发镜像,如 Docker Hub
Dockerfile构建镜像的声明式脚本
卷(Volume)持久化存储,容器重启后数据不丢失
网络(Network)容器间通信的虚拟网络层

docker run 详解

docker run 是最常用命令,完整语法:

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

运行模式

docker run -d nginx                  # 后台(detached)模式
docker run -it ubuntu bash           # 交互模式,分配伪终端
docker run --rm alpine echo "hello"  # 容器退出后自动删除
docker run -d -it ubuntu             # 后台运行但保持 stdin 打开

命名与标识

docker run --name web nginx              # 指定容器名称
docker run --hostname myhost nginx       # 设置容器内主机名
docker run --label env=prod nginx        # 添加标签

端口映射(-p)

docker run -p 8080:80 nginx              # 主机 8080 → 容器 80
docker run -p 127.0.0.1:8080:80 nginx   # 仅绑定本地回环
docker run -p 8080:80/udp nginx          # UDP 协议
docker run -P nginx                      # 随机映射所有 EXPOSE 端口

环境变量(-e / —env-file)

docker run -e MYSQL_ROOT_PASSWORD=secret mysql
docker run -e APP_ENV=prod -e LOG_LEVEL=info myapp
docker run --env-file .env myapp         # 从文件批量注入

.env 文件格式(每行 KEY=VALUE# 开头为注释):

MYSQL_ROOT_PASSWORD=secret
MYSQL_DATABASE=mydb
APP_PORT=8080

数据卷挂载(-v / —mount)

# 绑定挂载(Bind Mount):挂载宿主机目录
docker run -v /host/data:/container/data nginx
docker run -v $(pwd)/logs:/app/logs myapp
 
# 具名卷(Named Volume):由 Docker 管理
docker run -v mydata:/var/lib/mysql mysql
 
# --mount 语法(更明确,推荐)
docker run --mount type=bind,source=/host/data,target=/data nginx
docker run --mount type=volume,source=mydata,target=/data nginx
docker run --mount type=tmpfs,target=/tmp nginx   # 内存临时文件系统
 
# 只读挂载
docker run -v /host/config:/config:ro nginx

网络配置(—network)

docker run --network bridge myapp            # 默认 bridge 网络
docker run --network host myapp              # 共享宿主机网络(Linux)
docker run --network none myapp              # 完全隔离,无网络
docker run --network mynet myapp             # 自定义网络
docker run --network mynet --network-alias db myapp  # 添加 DNS 别名
 
# 端口和 DNS
docker run --add-host db:192.168.1.10 myapp  # 添加 /etc/hosts 条目
docker run --dns 8.8.8.8 myapp               # 指定 DNS

重启策略(—restart)

docker run --restart no nginx            # 不自动重启(默认)
docker run --restart always nginx        # 总是重启(含宿主机重启)
docker run --restart unless-stopped nginx # 手动停止则不重启
docker run --restart on-failure nginx    # 仅非零退出码时重启
docker run --restart on-failure:3 nginx  # 最多重试 3 次

资源限制

# 内存
docker run --memory 512m nginx           # 最大内存 512MB
docker run --memory 512m --memory-swap 1g nginx  # 含 swap 共 1GB
 
# CPU
docker run --cpus 1.5 nginx              # 使用 1.5 个 CPU 核
docker run --cpu-shares 512 nginx        # 相对权重(默认 1024)
docker run --cpuset-cpus "0,2" nginx     # 绑定到指定 CPU 核
 
# 组合限制
docker run --memory 256m --cpus 0.5 myapp

用户与权限

docker run --user 1000:1000 nginx        # 指定 UID:GID
docker run --user nobody nginx           # 非特权用户
docker run --privileged myapp            # 完全特权(慎用)
docker run --cap-add NET_ADMIN myapp     # 添加单个 Linux capability
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp  # 最小权限
docker run --read-only myapp             # 只读文件系统

覆盖入口点

docker run --entrypoint /bin/sh myapp    # 覆盖 ENTRYPOINT
docker run --entrypoint "" myapp ls /    # 清空 ENTRYPOINT,直接执行命令

实用完整示例

# MySQL 生产环境
docker run -d \
  --name mysql \
  --restart unless-stopped \
  -p 127.0.0.1:3306:3306 \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=mydb \
  -v mysql_data:/var/lib/mysql \
  --memory 1g --cpus 2 \
  mysql:8.0
 
# Spring Boot 应用
docker run -d \
  --name myapp \
  --restart always \
  -p 8080:8080 \
  --env-file .env \
  -v $(pwd)/logs:/app/logs \
  --network app-net \
  --memory 512m --cpus 1 \
  myapp:1.0
 
# 一次性任务容器(执行完自动删除)
docker run --rm \
  -v $(pwd):/workspace \
  -w /workspace \
  node:20-alpine \
  npm install

镜像管理

docker pull nginx:latest             # 拉取镜像
docker pull nginx:1.25-alpine        # 指定版本
docker images                        # 列出本地镜像
docker images --filter dangling=true # 列出悬空镜像(<none>)
docker rmi nginx:latest              # 删除镜像
docker tag myapp:latest myapp:1.0    # 打标签
docker save myapp:1.0 | gzip > myapp.tar.gz   # 导出镜像
docker load < myapp.tar.gz           # 导入镜像
docker history myapp:1.0             # 查看镜像分层历史
docker inspect nginx                 # 查看镜像详细信息

容器管理

docker ps                            # 查看运行中容器
docker ps -a                         # 查看所有容器
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
 
docker stop web                      # 优雅停止(SIGTERM)
docker kill web                      # 强制停止(SIGKILL)
docker start web                     # 启动已停止容器
docker restart web                   # 重启
docker pause / unpause web           # 暂停/恢复
 
docker rm web                        # 删除已停止容器
docker rm -f web                     # 强制删除运行中容器
docker container prune               # 删除所有已停止容器
 
docker logs web                      # 查看日志
docker logs -f web                   # 实时追踪日志
docker logs --tail 100 web           # 最近 100 行
docker logs --since 30m web          # 最近 30 分钟
 
docker exec -it web bash             # 进入容器 shell
docker exec web cat /etc/nginx/nginx.conf  # 非交互执行命令
docker cp web:/etc/nginx/nginx.conf ./     # 从容器复制文件
docker cp ./nginx.conf web:/etc/nginx/     # 复制文件到容器
 
docker stats                         # 实时资源使用
docker top web                       # 查看容器进程
docker inspect web                   # 查看容器详细信息

网络管理

docker network ls                    # 列出网络
docker network create app-net        # 创建自定义 bridge 网络
docker network create \
  --driver overlay \
  --subnet 10.0.0.0/24 \
  my-overlay                         # Swarm overlay 网络
docker network inspect app-net       # 查看网络详情
docker network connect app-net web   # 将容器加入网络
docker network disconnect app-net web
docker network rm app-net

卷管理

docker volume create mydata          # 创建具名卷
docker volume ls                     # 列出卷
docker volume inspect mydata         # 查看卷详情
docker volume rm mydata              # 删除卷
docker volume prune                  # 删除所有未使用卷

Dockerfile 最佳实践

# 多阶段构建(减小最终镜像体积)
FROM maven:3.9-openjdk-17 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline        # 单独缓存依赖层
COPY src ./src
RUN mvn package -DskipTests
 
FROM openjdk:17-jre-slim
WORKDIR /app
 
# 非 root 用户运行(安全最佳实践)
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
 
COPY --from=builder /build/target/app.jar app.jar
 
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
  CMD curl -f http://localhost:8080/actuator/health || exit 1
 
EXPOSE 8080
ENV JAVA_OPTS="-Xmx512m -Xms256m"
 
USER appuser
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

Dockerfile 指令对比

指令说明
FROM基础镜像,多阶段构建可有多个
WORKDIR设置工作目录(自动创建)
COPY复制文件(推荐,比 ADD 更透明)
ADD支持 URL 和自动解压 tar
RUN构建时执行,每条创建一个层
CMD默认命令,docker run 末尾参数可覆盖
ENTRYPOINT入口点,CMD 作为其参数
ENV设置环境变量(构建和运行时生效)
ARG仅构建时变量,--build-arg 传入
EXPOSE声明监听端口(文档用途)
VOLUME声明挂载点
USER切换执行用户
HEALTHCHECK容器健康检查
LABEL添加元数据

层缓存优化

# 好:依赖文件单独复制,代码变动不影响依赖缓存
COPY package*.json ./
RUN npm ci
COPY . .
 
# 差:任何文件变动都导致 npm install 重新执行
COPY . .
RUN npm install

.dockerignore

node_modules
.git
*.log
.env
dist

Docker Compose

version: '3.8'
 
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        BUILD_ENV: production
    image: myapp:latest
    container_name: myapp
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
    env_file:
      - .env
    depends_on:
      db:
        condition: service_healthy    # 等待 db 健康检查通过
    volumes:
      - ./logs:/app/logs
    networks:
      - app-net
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
 
  db:
    image: mysql:8.0
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: mydb
    volumes:
      - mysql_data:/var/lib/mysql
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - app-net
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
 
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - app
    networks:
      - app-net
    restart: always
 
networks:
  app-net:
    driver: bridge
 
volumes:
  mysql_data:
    driver: local
docker compose up -d                  # 后台启动所有服务
docker compose up -d app              # 仅启动指定服务
docker compose down                   # 停止并删除容器、网络
docker compose down -v                # 同时删除具名卷
docker compose ps                     # 查看服务状态
docker compose logs -f app            # 追踪指定服务日志
docker compose exec app bash          # 进入服务容器
docker compose restart app            # 重启指定服务
docker compose pull                   # 拉取最新镜像
docker compose build --no-cache       # 重新构建镜像
docker compose config                 # 验证并查看合并后配置

清理

docker system prune                   # 删除停止容器、无用镜像、网络
docker system prune -a                # 同时删除未被使用的镜像
docker system prune --volumes         # 同时删除未使用卷
docker system df                      # 查看 Docker 磁盘占用
 
docker image prune                    # 仅清理悬空镜像
docker container prune                # 仅清理停止的容器
docker network prune                  # 仅清理未使用网络
docker volume prune                   # 仅清理未使用卷

从0-1快速启动

sudo apt update
 
sudo apt install -y ca-certificates curl gnupg lsb-release
 
sudo install -m 0755 -d /etc/apt/keyrings
 
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
 
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
 
sudo apt update
 
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
 
sudo mkdir -p /etc/docker
 
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://myspecialaddress.mirror.aliyuncs.com"]
}
EOF
 
 
sudo systemctl daemon-reload
sudo systemctl restart docker


相关文档