Docker 教程:容器化平台详解

1. 什么是 Docker?

Docker 是一个开源的容器化平台,它允许开发者将应用及其依赖打包成一个轻量级、可移植的容器,然后在任何环境中运行。Docker 容器与虚拟机不同,它共享主机操作系统的内核,因此更加轻量级、启动更快,并且资源占用更少。

1.1 核心概念

  • 镜像(Image):容器的只读模板,包含运行应用所需的所有文件和依赖。
  • 容器(Container):镜像的运行实例,可以被创建、启动、停止、删除和暂停。
  • 仓库(Repository):存储镜像的地方,如 Docker Hub。
  • Dockerfile:定义如何构建镜像的文本文件。
  • Docker Compose:用于定义和运行多容器 Docker 应用的工具。

1.2 核心特性

  • 容器化:将应用及其依赖打包成容器,实现环境隔离和一致性。
  • 镜像管理:通过镜像仓库管理和分发应用。
  • 网络管理:提供容器间的网络通信能力。
  • 存储管理:管理容器的数据持久化。
  • 编排:通过 Docker Compose、Kubernetes 等工具管理多容器应用。

1.3 适用场景

  • 应用打包和分发:确保应用在不同环境中运行一致。
  • 微服务架构:每个服务作为独立容器运行,便于管理和扩展。
  • 持续集成和持续部署:加速构建、测试和部署流程。
  • 开发环境标准化:确保开发、测试和生产环境一致。
  • 资源隔离:在同一主机上运行多个隔离的应用。

2. 安装和配置

2.1 Windows 安装

  1. 下载 Docker Desktop for Windows:https://www.docker.com/products/docker-desktop
  2. 运行安装程序,按照提示完成安装。
  3. 启动 Docker Desktop,等待它完全启动。
  4. 验证安装:
docker --version
docker-compose --version

2.2 macOS 安装

  1. 下载 Docker Desktop for Mac:https://www.docker.com/products/docker-desktop
  2. 运行安装程序,按照提示完成安装。
  3. 启动 Docker Desktop,等待它完全启动。
  4. 验证安装:
docker --version
docker-compose --version

2.3 Linux 安装

以 Ubuntu 为例:

# 更新包索引
sudo apt-get update

# 安装必要的依赖
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent 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"

# 更新包索引并安装 Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

# 验证安装
sudo docker --version

# 安装 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo docker-compose --version

2.4 配置 Docker

2.4.1 非 root 用户使用 Docker(Linux)

sudo usermod -aG docker $USER
# 重新登录或执行以下命令使更改生效
su - $USER

2.4.2 配置 Docker 镜像加速

对于中国用户,可以配置 Docker 镜像加速以提高拉取镜像的速度:

  1. 登录阿里云容器镜像服务:https://cr.console.aliyun.com/
  2. 获取镜像加速器地址
  3. 配置 Docker daemon.json 文件:
{
  "registry-mirrors": ["https://你的加速器地址.mirror.aliyuncs.com"]
}
  1. 重启 Docker 服务:
# Linux
sudo systemctl restart docker

# Windows/macOS
# 在 Docker Desktop 中重启

3. 基本使用

3.1 镜像管理

# 拉取镜像
docker pull ubuntu

# 列出本地镜像
docker images

# 删除镜像
docker rmi ubuntu

# 构建镜像
docker build -t my-app .

3.2 容器管理

# 运行容器
docker run -it --name my-container ubuntu bash

# 运行后台容器
docker run -d --name my-container ubuntu

# 查看运行中的容器
docker ps

# 查看所有容器
docker ps -a

# 停止容器
docker stop my-container

# 启动容器
docker start my-container

# 删除容器
docker rm my-container

# 进入运行中的容器
docker exec -it my-container bash

3.3 网络管理

# 创建网络
docker network create my-network

# 运行容器并连接到网络
docker run -d --name container1 --network my-network nginx

docker run -d --name container2 --network my-network nginx

# 查看网络
docker network ls

# 查看网络详情
docker network inspect my-network

3.4 存储管理

# 创建卷
docker volume create my-volume

# 运行容器并挂载卷
docker run -d --name my-container -v my-volume:/app nginx

# 查看卷
docker volume ls

# 查看卷详情
docker volume inspect my-volume

# 删除卷
docker volume rm my-volume

# 挂载主机目录
docker run -d --name my-container -v /host/path:/container/path nginx

4. 高级功能

4.1 Dockerfile

创建一个 Dockerfile 文件来定义如何构建镜像:

# 指定基础镜像
FROM node:14-alpine

# 设置工作目录
WORKDIR /app

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

# 安装依赖
RUN npm install

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 3000

# 启动应用
CMD ["node", "app.js"]

4.2 Docker Compose

创建一个 docker-compose.yml 文件来定义和运行多容器应用:

version: '3'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - db
  db:
    image: mongo
    volumes:
      - mongo-data:/data/db

volumes:
  mongo-data:

4.3 多阶段构建

使用多阶段构建来减小镜像大小:

# 构建阶段
FROM node:14-alpine as builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 运行阶段
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

5. 实用案例

5.1 部署一个简单的 Node.js 应用

场景:使用 Docker 部署一个简单的 Node.js Express 应用。

步骤

  1. 创建应用目录
mkdir docker-node-app && cd docker-node-app
  1. 创建 package.json 文件
{
  "name": "docker-node-app",
  "version": "1.0.0",
  "description": "Node.js app with Docker",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^4.17.1"
  }
}
  1. 创建 app.js 文件
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello Docker!');
});

app.listen(port, () => {
  console.log(`App listening at http://localhost:${port}`);
});
  1. 创建 Dockerfile 文件
FROM node:14-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
  1. 构建镜像
docker build -t node-app .
  1. 运行容器
docker run -d --name node-container -p 3000:3000 node-app
  1. 测试应用

打开浏览器访问 http://localhost:3000,应该看到 "Hello Docker!"。

5.2 使用 Docker Compose 部署多容器应用

场景:使用 Docker Compose 部署一个包含 Node.js 应用和 MongoDB 数据库的多容器应用。

步骤

  1. 创建应用目录
mkdir docker-compose-app && cd docker-compose-app
  1. 创建 package.json 文件
{
  "name": "docker-compose-app",
  "version": "1.0.0",
  "description": "App with Docker Compose",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^4.17.1",
    "mongoose": "^5.13.7"
  }
}
  1. 创建 app.js 文件
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const port = 3000;

// 连接到 MongoDB
mongoose.connect('mongodb://db:27017/docker-compose-demo', {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

// 定义模型
const Item = mongoose.model('Item', {
  name: String
});

// 路由
app.get('/', async (req, res) => {
  // 创建一个新项
  const item = new Item({ name: 'Test Item' });
  await item.save();
  
  // 获取所有项
  const items = await Item.find();
  res.send(`Items: ${JSON.stringify(items)}`);
});

app.listen(port, () => {
  console.log(`App listening at http://localhost:${port}`);
});
  1. 创建 Dockerfile 文件
FROM node:14-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
  1. 创建 docker-compose.yml 文件
version: '3'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - db
  db:
    image: mongo
    volumes:
      - mongo-data:/data/db

volumes:
  mongo-data:
  1. 启动应用
docker-compose up -d
  1. 查看容器状态
docker-compose ps
  1. 测试应用

打开浏览器访问 http://localhost:3000,应该看到包含测试项的响应。

  1. 停止应用
docker-compose down

6. 代码示例

6.1 构建和运行简单应用

Dockerfile

FROM node:14-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]

构建和运行命令

# 构建镜像
docker build -t my-app .

# 运行容器
docker run -d --name my-container -p 3000:3000 my-app

# 查看容器状态
docker ps

# 停止容器
docker stop my-container

# 删除容器
docker rm my-container

6.2 使用 Docker Compose 部署多容器应用

docker-compose.yml

version: '3'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    depends_on:
      - db
  db:
    image: postgres
    environment:
      - POSTGRES_PASSWORD=secret
      - POSTGRES_USER=user
      - POSTGRES_DB=app
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  postgres-data:

启动和停止命令

# 启动应用
docker-compose up -d

# 查看日志
docker-compose logs

# 停止应用
docker-compose down

7. 常见问题和解决方案

7.1 容器无法启动

问题:容器启动后立即退出。

解决方案

  • 检查容器日志:docker logs [容器名称]
  • 确保容器有一个前台进程在运行
  • 检查应用是否有错误

7.2 端口映射失败

问题:无法通过主机端口访问容器应用。

解决方案

  • 检查端口映射是否正确:docker run -p [主机端口]:[容器端口]
  • 确保容器内的应用正在监听正确的端口
  • 检查主机防火墙是否阻止了该端口

7.3 数据持久化问题

问题:容器重启后数据丢失。

解决方案

  • 使用 Docker 卷:docker run -v [卷名]:[容器路径]
  • 使用主机目录挂载:docker run -v [主机路径]:[容器路径]

7.4 镜像拉取缓慢

问题:从 Docker Hub 拉取镜像速度缓慢。

解决方案

  • 配置 Docker 镜像加速
  • 使用国内镜像源

7.5 容器间通信问题

问题:同一网络中的容器无法相互通信。

解决方案

  • 确保容器在同一个网络中:docker network createdocker run --network
  • 使用容器名称作为主机名进行通信
  • 检查容器的网络配置:docker network inspect

8. 总结

Docker 是一个强大的容器化平台,它彻底改变了应用的开发、部署和运行方式。通过将应用及其依赖打包成容器,Docker 实现了环境的一致性和可移植性,大大简化了应用的部署和管理。

8.1 优点

  • 环境一致性:确保应用在不同环境中运行一致
  • 轻量级:相比虚拟机,容器更加轻量级,启动更快
  • 可移植性:容器可以在任何支持 Docker 的环境中运行
  • 资源隔离:容器之间相互隔离,避免资源冲突
  • 易于管理:提供了简单易用的命令行工具和 API

8.2 局限性

  • 学习曲线:对于初学者来说,Docker 有一定的学习曲线
  • 网络复杂性:在复杂的网络环境中,容器网络配置可能变得复杂
  • 存储管理:容器的存储管理需要额外的配置和考虑
  • 安全考虑:需要注意容器的安全配置,避免安全漏洞

8.3 适用场景

  • 微服务架构:每个服务作为独立容器运行
  • 持续集成和持续部署:加速构建、测试和部署流程
  • 开发环境标准化:确保开发、测试和生产环境一致
  • 多环境部署:快速在不同环境中部署应用
  • 资源优化:提高服务器资源利用率

通过本教程,你应该已经掌握了 Docker 的基本概念、安装配置、基本使用和常见场景的应用。在实际开发和部署中,Docker 可以大大简化工作流程,提高开发效率和应用的可靠性。

« 上一篇 Forever 教程:Node.js 应用的简单进程管理器 下一篇 » Kubernetes 教程:容器编排平台详解