Docker容器化应用部署完全指南

本文最后更新于 1 分钟前,文中所描述的信息可能已发生改变。

容器化技术彻底改变了应用程序的开发、测试和部署方式。Docker 作为最流行的容器平台,提供了一种轻量级、可移植且独立的方式来打包和运行应用程序。本文将详细介绍如何使用 Docker 进行应用程序容器化和部署。

Docker 基础概念

在深入了解部署过程之前,先来理解几个关键概念:

  • 容器(Container):轻量级、可执行的软件包,包含应用程序及其所有依赖
  • 镜像(Image):容器的不可变模板,用于创建容器
  • Dockerfile:构建镜像的脚本文件
  • 仓库(Repository):存储和分发 Docker 镜像的地方
  • Docker Compose:定义和运行多容器 Docker 应用的工具
  • Docker Swarm/Kubernetes:容器编排工具,管理多个容器的部署

安装 Docker

Linux(Ubuntu)

bash
# 更新软件包索引
sudo apt update

# 安装依赖
sudo apt install apt-transport-https ca-certificates curl software-properties-common

# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# 添加 Docker 源
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# 再次更新软件包索引
sudo apt update

# 安装 Docker
sudo apt install docker-ce

# 验证 Docker 是否安装成功
docker --version

macOS

最简单的方式是安装 Docker Desktop for Mac:

  1. Docker 官网 下载 Docker Desktop
  2. 双击 .dmg 文件并将 Docker 拖到应用程序文件夹
  3. 启动 Docker Desktop 应用程序

Windows

与 macOS 类似,安装 Docker Desktop for Windows:

  1. Docker 官网 下载 Docker Desktop
  2. 运行安装程序
  3. 启动 Docker Desktop 应用程序

创建 Docker 镜像

编写 Dockerfile

以一个简单的 Node.js 应用为例:

dockerfile
# 使用官方 Node.js 镜像作为基础镜像
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 package-lock.json 文件
COPY package*.json ./

# 安装依赖
RUN npm ci

# 复制源代码
COPY . .

# 如果有构建步骤(例如 TypeScript 编译或 Next.js 构建)
RUN npm run build

# 设置环境变量
ENV NODE_ENV=production

# 开放端口
EXPOSE 3000

# 设置启动命令
CMD ["npm", "start"]

Dockerfile 最佳实践

  1. 使用精简的基础镜像:例如 Alpine 版本的镜像
  2. 多阶段构建:减小最终镜像的大小
  3. 合理使用缓存:将变更频率较低的指令放在前面
  4. 减少层数:合并相关的 RUN 命令
  5. 使用 .dockerignore:排除不需要的文件

.dockerignore 示例:

node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore
README.md

构建镜像

bash
# 语法: docker build -t 名称:标签 构建上下文路径
docker build -t myapp:1.0 .

多阶段构建示例(前端应用)

dockerfile
# 构建阶段
FROM node:18-alpine AS build

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

# 生产阶段
FROM nginx:alpine

# 将构建阶段的产物复制到 Nginx 目录
COPY --from=build /app/dist /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

运行 Docker 容器

基本运行

bash
# 语法: docker run [选项] 镜像名 [命令]
docker run -d -p 3000:3000 --name myapp myapp:1.0

常用选项:

  • -d:在后台运行容器
  • -p host:container:端口映射
  • --name:容器命名
  • -v host:container:卷挂载
  • -e KEY=VALUE:环境变量
  • --network:指定网络
  • --restart:重启策略

查看容器

bash
# 查看运行中的容器
docker ps

# 查看所有容器
docker ps -a

# 查看容器日志
docker logs myapp

# 实时查看日志
docker logs -f myapp

管理容器

bash
# 停止容器
docker stop myapp

# 启动已停止的容器
docker start myapp

# 重启容器
docker restart myapp

# 删除容器(需要先停止)
docker rm myapp

# 强制删除容器
docker rm -f myapp

使用 Docker Compose 管理多容器应用

创建 docker-compose.yml

yaml
version: '3.8'

services:
  web:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:80"
    depends_on:
      - api
    environment:
      - API_URL=http://api:5000

  api:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    depends_on:
      - db
    environment:
      - DB_HOST=db
      - DB_USER=postgres
      - DB_PASSWORD=secret
      - DB_NAME=myapp
    volumes:
      - ./uploads:/app/uploads

  db:
    image: postgres:13-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp

volumes:
  postgres_data:

使用 Docker Compose 命令

bash
# 启动所有服务
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看服务日志
docker-compose logs

# 查看特定服务的日志
docker-compose logs api

# 停止所有服务
docker-compose down

# 停止并删除所有卷
docker-compose down -v

数据持久化

挂载卷

Docker 提供三种主要的数据挂载方式:

  1. 卷(Volumes):由 Docker 管理的持久化存储
  2. 绑定挂载(Bind mounts):将主机上的目录挂载到容器
  3. tmpfs 挂载:在内存中存储临时数据

创建和使用命名卷:

bash
# 创建卷
docker volume create mydata

# 使用卷
docker run -v mydata:/app/data myapp:1.0

在 Docker Compose 中使用卷:

yaml
services:
  app:
    image: myapp:1.0
    volumes:
      - mydata:/app/data

volumes:
  mydata:

使用绑定挂载进行开发

在开发环境中,可以使用绑定挂载实现代码热更新:

bash
docker run -v $(pwd):/app myapp:1.0

应用程序配置

环境变量

通过环境变量传递配置是 Docker 的最佳实践:

bash
docker run -e DATABASE_URL=postgres://user:pass@db:5432/dbname myapp:1.0

配置文件

对于复杂配置,可以挂载配置文件:

bash
docker run -v ./config.json:/app/config.json myapp:1.0

使用 Docker Secrets(Swarm 模式)

对于敏感信息,可以使用 Docker Secrets:

bash
# 创建密钥
echo "supersecretpassword" | docker secret create db_password -

# 在服务中使用密钥
docker service create \
  --name myapp \
  --secret db_password \
  myapp:1.0

容器网络

网络类型

Docker 提供了几种不同的网络驱动:

  1. bridge:默认网络,适用于单机容器通信
  2. host:使用主机网络,无隔离
  3. overlay:用于 Swarm 服务,实现跨主机通信
  4. macvlan:为容器分配 MAC 地址,直接连接物理网络
  5. none:禁用网络

创建自定义网络

bash
# 创建网络
docker network create mynetwork

# 将容器连接到网络
docker run --network mynetwork myapp:1.0

在 Docker Compose 中:

yaml
networks:
  frontend:
  backend:

services:
  web:
    networks:
      - frontend
  api:
    networks:
      - frontend
      - backend
  db:
    networks:
      - backend

生产环境部署

单主机部署

对于小型应用,可以使用 Docker Compose 进行单主机部署:

  1. 准备服务器并安装 Docker
  2. 编写生产环境的 docker-compose.yml
  3. 使用 docker-compose up -d 启动服务
  4. 配置反向代理和 HTTPS(如 Nginx)

使用容器编排系统

对于较大规模应用,推荐使用容器编排工具:

Docker Swarm

Docker 内置的编排工具,适合 Docker 重度用户:

bash
# 初始化 Swarm
docker swarm init

# 创建服务
docker service create \
  --name myapp \
  --replicas 3 \
  --publish 80:3000 \
  myapp:1.0

使用 Docker Stack 部署多容器应用:

bash
docker stack deploy -c docker-compose.yml mystack

Kubernetes

更强大、更复杂的容器编排平台:

  1. 准备 Kubernetes 集群(可使用 GKE、AKS、EKS 等托管服务)
  2. 编写 Kubernetes 资源文件(Deployment、Service、ConfigMap 等)
  3. 使用 kubectl apply 部署应用

持续集成和持续部署

GitHub Actions 示例

yaml
name: Build and Deploy

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
      
    - name: Login to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_HUB_USERNAME }}
        password: ${{ secrets.DOCKER_HUB_TOKEN }}
        
    - name: Build and push
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: |
          username/myapp:latest
          username/myapp:${{ github.sha }}
          
    - name: Deploy to production
      uses: appleboy/ssh-action@v0.1.10
      with:
        host: ${{ secrets.SSH_HOST }}
        username: ${{ secrets.SSH_USERNAME }}
        key: ${{ secrets.SSH_PRIVATE_KEY }}
        script: |
          cd /opt/myapp
          docker-compose pull
          docker-compose up -d

容器监控和日志

监控解决方案

  1. Prometheus + Grafana:开源监控和可视化方案
  2. Docker Stats:基本的容器资源使用统计
  3. cAdvisor:容器资源使用和性能特性分析器

日志管理

  1. ELK Stack:Elasticsearch, Logstash, Kibana
  2. Fluentd/Fluent Bit:轻量级日志收集器

安全最佳实践

  1. 使用官方镜像,避免使用不可信的第三方镜像
  2. 定期更新基础镜像,确保安全补丁
  3. 以非 root 用户运行容器
dockerfile
FROM node:18-alpine

# 创建非 root 用户
RUN addgroup -g 1000 appuser && \
    adduser -u 1000 -G appuser -s /bin/sh -D appuser

# 设置工作目录
WORKDIR /app

# 复制应用代码
COPY --chown=appuser:appuser . .

# 切换到非 root 用户
USER appuser

# ...其余部分
  1. 使用只读文件系统
bash
docker run --read-only myapp:1.0
  1. 限制容器资源
bash
docker run --memory="500m" --cpus="1.5" myapp:1.0
  1. 使用 Docker Content Trust 签名镜像
bash
# 启用 DCT
export DOCKER_CONTENT_TRUST=1

# 推送签名镜像
docker push myapp:1.0
  1. 扫描镜像漏洞
bash
# 使用 Docker Scout CLI
docker scout cves myapp:1.0

常见挑战与解决方案

容器化现有应用

  1. 分析应用依赖:理解应用所需的环境、库和配置
  2. 确定状态存储:识别需要持久化的数据
  3. 拆分服务:考虑将单体应用拆分为多个容器

容器化数据库

生产环境中容器化数据库需要特别注意:

  1. 使用命名卷:确保数据持久化
  2. 配置适当的内存和 CPU 限制
  3. 考虑备份策略
  4. 使用复制和高可用方案

对于生产环境,可能需要考虑使用托管数据库服务(如 RDS、Cloud SQL)而非自行容器化数据库。

调试容器

bash
# 进入运行中的容器
docker exec -it myapp sh

# 查看容器详情
docker inspect myapp

# 查看容器资源使用情况
docker stats myapp

高级主题

多架构构建

为不同的 CPU 架构构建镜像:

bash
# 创建构建器
docker buildx create --use

# 构建多架构镜像
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:1.0 --push .

使用 Docker Registry

搭建私有 Docker Registry:

bash
docker run -d -p 5000:5000 --name registry registry:2

# 标记本地镜像
docker tag myapp:1.0 localhost:5000/myapp:1.0

# 推送到私有仓库
docker push localhost:5000/myapp:1.0

总结

容器化部署为应用程序提供了一致、可靠且可扩展的环境。通过 Docker:

  1. 开发者可以更专注于代码而非环境
  2. 应用可以在任何支持 Docker 的地方运行
  3. 基础设施可以更高效地利用
  4. 微服务架构变得更加实用

本指南涵盖了 Docker 容器化部署的核心概念和实践。通过遵循这些最佳实践和技巧,你可以充分利用容器技术的优势,简化应用的开发、测试和部署流程。

随着应用规模的增长,可以考虑探索更高级的容器编排平台,如 Kubernetes,以提供更强大的自动化、扩展和自修复能力。

Keycloak身份认证系统:Docker部署与MySQL集成指南
Spring Boot微服务开发完全指南