返回文章列表

Docker容器化部署完全指南

作为拥有18年运维经验的技术人,我见证了从物理机部署→虚拟机部署→容器化部署的全历程。Docker作为容器化技术的事实标准,已成为现代运维的必备技能。本文从零开始讲解Docker核心概念、环境搭建、Dockerfile编写、镜像优化、容器编排、生产级部署等核心内容,结合实战避坑点,帮你掌握容器化部署的最佳实践,解决"容器部署容易,稳定运行难"的痛点。

📋 文章目录

一、Docker容器化核心价值(为什么放弃传统部署)

1. 传统部署的痛点

2. Docker容器化的核心优势

优势维度 具体价值 运维效率提升
环境一致性 镜像打包所有依赖,一次构建,处处运行 部署故障减少80%
轻量级隔离 基于内核的容器隔离,启动毫秒级,单机可部署数百个容器 资源利用率提升50%+
部署时间从小时级→分钟级
弹性伸缩 基于镜像快速扩缩容,适配业务峰值 扩容响应速度提升10倍
版本管理 镜像版本化,支持一键回滚,灰度发布 回滚时间从小时级→秒级
DevOps落地 标准化镜像构建、部署流程,打通开发→测试→生产 迭代效率提升30%+

3. Docker vs 虚拟机 核心对比

特性 Docker容器 虚拟机(VM)
启动时间 秒级/毫秒级 分钟级
资源占用 MB级,共享宿主机内核 GB级,独立内核
隔离级别 进程级隔离(内核级) 硬件级隔离(完全隔离)
镜像体积 小(几十MB) 大(几GB)
移植性 极高(跨平台/跨云厂商) 较低(依赖虚拟化平台)
性能损耗 接近原生(<5%) 较高(10%-20%)
⚠️ 避坑提示:

Docker不是银弹!容器化适合无状态服务、微服务架构,对于强依赖硬件、需要完全隔离的场景(如高安全要求的金融服务),虚拟机仍是更好选择。生产环境建议"核心服务容器化,特殊服务虚拟化"的混合架构。

二、Docker环境搭建(多系统+避坑版)

1. CentOS 7/8 安装Docker(生产环境推荐)

# ========== 1. 卸载旧版本(避免冲突) ==========
yum remove -y docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

# ========== 2. 安装依赖包 ==========
yum install -y yum-utils device-mapper-persistent-data lvm2

# ========== 3. 添加Docker官方源(国内建议用阿里云源) ==========
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# ========== 4. 安装Docker CE(指定版本,避免自动升级) ==========
# 查看可用版本
yum list docker-ce --showduplicates | sort -r
# 安装稳定版(推荐24.0.x系列)
yum install -y docker-ce-24.0.9 docker-ce-cli-24.0.9 containerd.io

# ========== 5. 启动并设置开机自启 ==========
systemctl start docker
systemctl enable docker
systemctl status docker

# ========== 6. 配置国内镜像加速(解决拉取镜像慢) ==========
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << EOF
{
  "registry-mirrors": [
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com",
    "https://docker.mirrors.ustc.edu.cn"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "storage-driver": "overlay2"
}
EOF

# 重启Docker生效
systemctl daemon-reload
systemctl restart docker

# ========== 7. 验证安装 ==========
docker --version
docker run --rm hello-world

2. Ubuntu 20.04/22.04 安装Docker

# ========== 1. 卸载旧版本 ==========
apt-get remove -y docker docker-engine docker.io containerd runc

# ========== 2. 更新包索引 ==========
apt-get update
apt-get install -y ca-certificates curl gnupg lsb-release

# ========== 3. 添加Docker GPG密钥 ==========
mkdir -p /etc/apt/trusted.gpg.d
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg

# ========== 4. 添加源 ==========
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

# ========== 5. 安装Docker ==========
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io

# ========== 6. 配置加速(同CentOS) ==========
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << EOF
{
  "registry-mirrors": [
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ]
}
EOF

systemctl daemon-reload
systemctl restart docker
systemctl enable docker

# ========== 7. 验证 ==========
docker --version
docker run --rm hello-world

3. Windows/macOS 安装Docker Desktop

⚠️ 核心避坑点:
  • 生产环境必须指定Docker版本安装,禁止使用yum install docker-ce(会自动安装最新版,易出兼容性问题)
  • CentOS 7需确保内核版本≥3.10.0-1160,过低会导致Docker启动失败
  • 国内环境必须配置镜像加速,否则拉取官方镜像极慢甚至失败
  • 非root用户使用Docker需添加用户到docker组:usermod -aG docker $USER,然后重新登录
  • 禁止在生产环境使用Docker Desktop,仅用于开发测试

三、Docker核心概念与实战(镜像/容器/网络/数据卷)

1. 核心概念速览

概念 核心定义 类比理解
镜像(Image) 只读的模板,包含运行应用所需的代码、依赖、配置 软件安装包(如.exe)
容器(Container) 镜像的运行实例,可读写,独立隔离 安装好的软件进程
仓库(Repository) 存储镜像的仓库,分公有/私有 软件下载站(如应用商店)
数据卷(Volume) 持久化存储容器数据的目录 软件的数据文件夹
网络(Network) 容器间/容器与宿主机的通信方式 局域网/交换机

2. 镜像核心操作

# 1. 拉取镜像(指定版本,避免latest)
docker pull nginx:1.24.0
docker pull mysql:8.0.36

# 2. 查看本地镜像
docker images
docker image ls

# 3. 搜索镜像
docker search redis

# 4. 标记镜像(用于推送到仓库)
docker tag nginx:1.24.0 myregistry.com/nginx:1.24.0

# 5. 删除镜像(先删容器,再删镜像)
docker rmi nginx:1.24.0
# 强制删除
docker rmi -f nginx:1.24.0

# 6. 导出/导入镜像(离线部署)
docker save -o nginx-1.24.0.tar nginx:1.24.0
docker load -i nginx-1.24.0.tar

# 7. 清理无用镜像
docker image prune -a

3. 容器核心操作

# 1. 创建并启动容器(常用参数)
# -d: 后台运行 -p: 端口映射 -v: 数据卷挂载 --name: 容器名 --restart: 重启策略
docker run -d \
  -p 80:80 \
  -v nginx-html:/usr/share/nginx/html \
  -v nginx-conf:/etc/nginx/conf.d \
  --name nginx-server \
  --restart=always \
  nginx:1.24.0

# 2. 查看容器
# 运行中的容器
docker ps
# 所有容器(含停止的)
docker ps -a

# 3. 容器启停/重启
docker start nginx-server
docker stop nginx-server
docker restart nginx-server

# 4. 进入容器(调试用)
# 方式1:bash终端
docker exec -it nginx-server /bin/bash
# 方式2:sh终端(兼容更多镜像)
docker exec -it nginx-server /bin/sh

# 5. 查看容器日志
# 实时日志
docker logs -f nginx-server
# 最近100行
docker logs --tail=100 nginx-server
# 按时间筛选
docker logs --since="2025-12-01" nginx-server

# 6. 查看容器详情
docker inspect nginx-server

# 7. 删除容器
# 停止并删除
docker stop nginx-server && docker rm nginx-server
# 强制删除运行中的容器
docker rm -f nginx-server

# 8. 清理停止的容器
docker container prune

4. 数据卷(持久化核心)

# 1. 创建数据卷
docker volume create mysql-data

# 2. 查看数据卷
docker volume ls
# 查看数据卷详情(含存储路径)
docker volume inspect mysql-data

# 3. 挂载数据卷到容器
docker run -d \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \
  --name mysql-server \
  mysql:8.0.36

# 4. 删除数据卷(谨慎!数据会丢失)
docker volume rm mysql-data
# 清理未使用的数据卷
docker volume prune

5. 网络配置

# 1. 查看网络
docker network ls

# 2. 创建自定义网络(推荐,容器间可通过容器名通信)
docker network create my-app-network

# 3. 将容器加入自定义网络
docker run -d \
  --name nginx-1 \
  --network my-app-network \
  nginx:1.24.0

docker run -d \
  --name nginx-2 \
  --network my-app-network \
  nginx:1.24.0

# 4. 容器间互通(在nginx-1中ping nginx-2)
docker exec -it nginx-1 ping nginx-2

# 5. 删除网络
docker network rm my-app-network
⚠️ 实战避坑:

1. 禁止使用docker run的--privileged=true参数(赋予容器根权限,安全风险极高);
2. 容器内不要存储重要数据,必须通过数据卷挂载宿主机/外部存储;
3. 自定义网络优先于默认桥接网络,避免端口冲突和通信问题;
4. 生产环境容器必须设置--restart=always,避免宿主机重启后容器不启动。

四、Dockerfile编写与镜像优化(生产级规范)

1. Dockerfile核心指令

指令 作用 示例
FROM 基础镜像(必须第一个指令) FROM centos:7
FROM python:3.9-slim
WORKDIR 设置工作目录 WORKDIR /app
COPY/ADD 复制文件到镜像(ADD支持解压) COPY ./app /app
ADD app.tar.gz /app
RUN 执行命令(构建时运行) RUN yum install -y nginx
ENV 设置环境变量 ENV PYTHONUNBUFFERED=1
EXPOSE 声明端口(仅文档,不实际映射) EXPOSE 8080
CMD/ENTRYPOINT 容器启动命令(CMD可被覆盖) CMD ["python", "app.py"]
ENTRYPOINT ["/usr/sbin/nginx"]
VOLUME 声明数据卷 VOLUME ["/data"]

2. 生产级Dockerfile示例(Python应用)

# ========== 阶段1:构建依赖 ==========
FROM python:3.9-slim AS builder

# 设置工作目录
WORKDIR /app

# 复制依赖文件
COPY requirements.txt .

# 安装依赖到临时目录
RUN pip install --no-cache-dir -r requirements.txt -t /app/lib

# ========== 阶段2:构建最终镜像 ==========
FROM python:3.9-slim

# 设置非root用户(安全)
RUN useradd -m appuser
WORKDIR /app

# 复制依赖和代码
COPY --from=builder /app/lib /app/lib
COPY app.py .

# 设置环境变量
ENV PYTHONPATH=/app/lib \
    PYTHONUNBUFFERED=1

# 暴露端口
EXPOSE 8080

# 切换非root用户
USER appuser

# 启动命令
CMD ["python", "app.py"]

3. 镜像优化核心技巧

4. 构建镜像与推送到仓库

# 1. 构建镜像(-t: 标签,.:Dockerfile所在目录)
docker build -t my-python-app:1.0.0 .

# 2. 本地测试镜像
docker run -p 8080:8080 my-python-app:1.0.0

# 3. 推送到私有仓库(先登录)
docker login myregistry.com
docker tag my-python-app:1.0.0 myregistry.com/my-python-app:1.0.0
docker push myregistry.com/my-python-app:1.0.0
⚠️ 安全规范:

1. 镜像必须使用非root用户运行(避免容器逃逸风险);
2. 禁止在Dockerfile中硬编码密码/密钥(用环境变量或外部配置);
3. 定期扫描镜像漏洞:docker scan my-python-app:1.0.0
4. 构建镜像后删除构建依赖(如编译工具、源码)。

五、Docker Compose容器编排(多服务部署实战)

1. Compose安装(Linux)

# 下载Compose(指定版本)
curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 添加执行权限
chmod +x /usr/local/bin/docker-compose

# 验证安装
docker-compose --version

2. 核心概念

3. 生产级docker-compose.yml示例(Web+MySQL+Redis)

version: '3.8'

# 自定义网络
networks:
  app-network:
    driver: bridge

# 数据卷
volumes:
  mysql-data:
  redis-data:
  nginx-html:

# 服务定义
services:
  # Nginx服务
  nginx:
    image: nginx:1.24.0
    container_name: app-nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - nginx-html:/usr/share/nginx/html
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/ssl:/etc/nginx/ssl
    networks:
      - app-network
    restart: always
    # 健康检查
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  # MySQL服务
  mysql:
    image: mysql:8.0.36
    container_name: app-mysql
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
      - ./mysql/init:/docker-entrypoint-initdb.d
    environment:
      - MYSQL_ROOT_PASSWORD=MyPass123!
      - MYSQL_DATABASE=app_db
      - MYSQL_USER=app_user
      - MYSQL_PASSWORD=AppPass456!
    networks:
      - app-network
    restart: always
    # 资源限制
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 1G
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Redis服务
  redis:
    image: redis:7.2.3
    container_name: app-redis
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    command: redis-server --requirepass RedisPass789! --appendonly yes
    networks:
      - app-network
    restart: always
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "RedisPass789!", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3

4. Compose核心操作

# 1. 启动所有服务(后台运行)
docker-compose up -d

# 2. 查看服务状态
docker-compose ps

# 3. 查看指定服务日志
docker-compose logs -f nginx

# 4. 启动/停止/重启服务
docker-compose start mysql
docker-compose stop mysql
docker-compose restart nginx

# 5. 构建自定义镜像(如果有build字段)
docker-compose build

# 6. 扩展服务(仅适用于swarm模式)
docker-compose up -d --scale web=3

# 7. 停止并删除容器/网络(保留数据卷)
docker-compose down

# 8. 停止并删除所有(含数据卷,谨慎!)
docker-compose down -v
⚠️ Compose避坑:

1. 生产环境不要用--scale扩展服务(推荐K8s),Compose仅适用于单机部署;
2. 环境变量不要硬编码在yml中,用env_file: .env分离;
3. 必须设置restart: always和healthcheck,确保服务异常自动恢复;
4. 配置资源限制(cpus/memory),避免单个服务占满宿主机资源。

六、Docker镜像仓库管理(私有仓库搭建)

1. 搭建私有仓库(Docker Registry)

# 1. 拉取registry镜像
docker pull registry:2.8.3

# 2. 创建数据卷
docker volume create registry-data

# 3. 启动私有仓库(带认证+HTTPS)
# 先创建认证文件
mkdir -p /opt/registry/auth
docker run --rm \
  -v /opt/registry/auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
  registry:2.8.3 \
  htpasswd -Bbn admin MyRegistryPass123! > /opt/registry/auth/htpasswd

# 创建SSL证书目录(替换为自己的域名/IP)
mkdir -p /opt/registry/certs
# 生成自签证书(生产环境用CA签发证书)
openssl req -newkey rsa:4096 -nodes -sha256 -keyout /opt/registry/certs/domain.key -x509 -days 365 -out /opt/registry/certs/domain.crt

# 启动仓库容器
docker run -d \
  -p 5000:5000 \
  --name docker-registry \
  --restart=always \
  -v registry-data:/var/lib/registry \
  -v /opt/registry/auth:/auth \
  -v /opt/registry/certs:/certs \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
  -e "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt" \
  -e "REGISTRY_HTTP_TLS_KEY=/certs/domain.key" \
  registry:2.8.3

# 4. 验证仓库
curl -u admin:MyRegistryPass123! https://your-registry-ip:5000/v2/_catalog

2. 客户端配置(信任私有仓库)

# 1. 复制证书到客户端
mkdir -p /etc/docker/certs.d/your-registry-ip:5000
cp /opt/registry/certs/domain.crt /etc/docker/certs.d/your-registry-ip:5000/ca.crt

# 2. 重启Docker
systemctl restart docker

# 3. 登录私有仓库
docker login your-registry-ip:5000

# 4. 推送/拉取镜像
docker tag nginx:1.24.0 your-registry-ip:5000/nginx:1.24.0
docker push your-registry-ip:5000/nginx:1.24.0
docker pull your-registry-ip:5000/nginx:1.24.0

3. 仓库管理最佳实践

⚠️ 仓库安全:

1. 禁止开放私有仓库到公网,仅允许内网访问;
2. 必须启用HTTPS和认证,避免镜像被篡改/窃取;
3. 定期更换仓库密码,删除离职人员账号;
4. 不要将敏感信息(如密钥)打包进镜像,通过配置中心挂载。

七、生产环境最佳实践(安全/监控/日志/避坑)

1. 安全加固

2. 监控告警

3. 日志管理

4. 容灾与备份

5. 生产环境避坑清单

🚫 绝对禁止:
  • 生产环境使用latest标签镜像
  • 容器内存储重要数据(未挂载数据卷)
  • 赋予容器root权限(--privileged=true)
  • 宿主机和容器共享网络命名空间(--net=host)
  • 硬编码密码/密钥到Dockerfile/Compose文件
  • 不设置资源限制,导致服务抢占资源
  • 关闭Docker日志限制,导致磁盘占满
  • 生产环境直接修改容器内配置(未通过镜像/配置中心)

八、总结与进阶方向

1. 核心总结

Docker容器化的核心价值是环境一致性、轻量级隔离、快速部署,解决了传统部署的效率低、环境不一致、扩缩容难等痛点。生产环境落地需遵循:

2. 进阶方向

3. 最后建议

容器化不是目的,而是手段。落地Docker的核心是标准化、自动化、可运维化,避免为了容器化而容器化。建议从小规模服务(如内部工具、非核心API)开始试点,积累经验后再推广到核心业务,同时建立完善的运维规范和故障处理流程,确保容器化落地的稳定性和可持续性。