介绍

Docker是一个开源的应用容器引擎,基于Go语言开发,可以让开发者打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上。容器化技术使应用的部署变得更加简单和一致,有效解决了”在我的机器上能运行”的问题。本文将详细介绍Docker的核心概念、基本使用方法及最佳实践,帮助读者快速掌握这一强大的容器化工具。

Docker 官方文档地址

为什么选择Docker?

在众多容器化技术中,Docker具有以下优势:

  1. 轻量级:相比传统虚拟机,Docker容器占用资源少,启动快速
  2. 一致性环境:从开发到测试到生产,保持环境一致性
  3. 隔离性:应用和依赖打包到一起,避免环境冲突
  4. 可移植性:一次构建,到处运行
  5. 版本控制:类似Git,可以跟踪容器镜像的版本变化
  6. 组件重用:可以使用已有的容器镜像作为基础,加快开发
  7. 共享:通过Docker Hub等平台共享和获取镜像

安装Docker

Linux安装

1
2
3
4
5
6
7
8
# Ubuntu
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

# CentOS
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io

Windows安装

在Windows上,可以下载并安装Docker Desktop:
https://www.docker.com/products/docker-desktop

Mac安装

在Mac上,同样可以使用Docker Desktop:
https://www.docker.com/products/docker-desktop

安装完成后,验证安装:

1
2
docker --version
docker run hello-world

核心概念

镜像(Image)

Docker镜像是一个只读模板,用于创建Docker容器。镜像可以看作是容器的”源代码”,是静态的文件。

1
2
3
4
5
6
7
8
# 列出本地镜像
docker images

# 拉取镜像
docker pull ubuntu:20.04

# 删除镜像
docker rmi ubuntu:20.04

容器(Container)

容器是镜像的运行实例,可以被启动、停止、删除等。容器之间相互隔离,可以将其看作是一个微型Linux系统。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 启动容器
docker run -it ubuntu:20.04 /bin/bash

# 列出运行中的容器
docker ps

# 列出所有容器(包括停止的)
docker ps -a

# 停止容器
docker stop <container_id>

# 启动停止的容器
docker start <container_id>

# 删除容器
docker rm <container_id>

仓库(Repository)

Docker仓库用于存储和分发Docker镜像。Docker Hub是Docker官方维护的公共仓库。

1
2
3
4
5
6
7
8
# 登录Docker Hub
docker login

# 推送镜像到Docker Hub
docker push username/image_name:tag

# 从Docker Hub拉取镜像
docker pull username/image_name:tag

Dockerfile

Dockerfile是用来构建Docker镜像的文本文件,包含了一系列的指令和参数。

常用指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 基础镜像
FROM ubuntu:20.04

# 维护者信息
LABEL maintainer="your-email@example.com"

# 执行命令
RUN apt-get update && apt-get install -y nginx

# 设置工作目录
WORKDIR /app

# 复制文件
COPY . /app

# 添加文件
ADD package.json /app/

# 设置环境变量
ENV NODE_ENV=production

# 暴露端口
EXPOSE 80

# 设置卷
VOLUME ["/data"]

# 设置启动命令
CMD ["nginx", "-g", "daemon off;"]

# 健康检查
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1

构建镜像

1
2
# 在Dockerfile所在目录执行
docker build -t my-image:1.0 .

Docker Compose

Docker Compose是一个用于定义和运行多容器Docker应用的工具。使用Compose,你可以通过YAML文件配置应用的服务,然后使用一个命令创建和启动所有服务。

安装Docker Compose

1
2
3
4
5
6
# Linux
sudo curl -L "https://github.com/docker/compose/releases/download/v2.12.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装
docker-compose --version

Windows和Mac的Docker Desktop已内置Docker Compose。

docker-compose.yml示例

1
2
3
4
5
6
7
8
9
10
11
12
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
depends_on:
- redis
redis:
image: redis:alpine

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 启动服务
docker-compose up

# 后台启动服务
docker-compose up -d

# 停止服务
docker-compose down

# 查看服务状态
docker-compose ps

# 查看服务日志
docker-compose logs

Docker网络

Docker提供了多种网络驱动,用于容器之间以及容器与外部世界的通信。

网络类型

  1. bridge:默认网络驱动,适用于单主机内的容器通信
  2. host:容器直接使用主机网络
  3. overlay:用于Swarm服务之间的通信
  4. macvlan:允许容器具有MAC地址,看起来像物理设备
  5. none:禁用容器的所有网络

网络命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查看网络列表
docker network ls

# 创建网络
docker network create --driver bridge my_network

# 查看网络详情
docker network inspect my_network

# 删除网络
docker network rm my_network

# 连接容器到网络
docker network connect my_network container_name

# 断开容器与网络的连接
docker network disconnect my_network container_name

Docker卷(Volume)

Docker卷用于持久化数据,即使容器被删除,卷中的数据也会保留。

卷命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建卷
docker volume create my_volume

# 查看卷列表
docker volume ls

# 查看卷详情
docker volume inspect my_volume

# 删除卷
docker volume rm my_volume

# 清理未使用的卷
docker volume prune

使用卷

1
2
3
4
5
# 在启动容器时挂载卷
docker run -v my_volume:/app/data ubuntu:20.04

# 使用主机目录作为卷
docker run -v /host/path:/container/path ubuntu:20.04

常见应用场景

Web应用部署

使用Docker部署Web应用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 使用Node.js作为基础镜像
FROM node:14

# 设置工作目录
WORKDIR /app

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

# 安装依赖
RUN npm install

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 3000

# 启动应用
CMD ["npm", "start"]

数据库部署

使用Docker Compose部署数据库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: '3'
services:
db:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: mydb
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"

volumes:
db_data:

微服务架构

使用Docker Compose构建微服务应用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: '3'
services:
frontend:
build: ./frontend
ports:
- "80:80"
depends_on:
- backend

backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- db

db:
image: postgres:13
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: app
volumes:
- db_data:/var/lib/postgresql/data

volumes:
db_data:

Docker Swarm

Docker Swarm是Docker的原生集群管理工具,可以将多个Docker主机组成一个集群,提供高可用性和负载均衡。

初始化Swarm

1
2
3
4
5
6
7
8
# 初始化Swarm(在管理节点上执行)
docker swarm init --advertise-addr <MANAGER-IP>

# 将工作节点加入Swarm
docker swarm join --token <TOKEN> <MANAGER-IP>:2377

# 查看节点
docker node ls

部署服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建服务
docker service create --replicas 3 --name my-web nginx

# 查看服务
docker service ls

# 查看服务详情
docker service inspect my-web

# 查看服务任务
docker service ps my-web

# 扩展服务
docker service scale my-web=5

# 删除服务
docker service rm my-web

使用Docker Stack

Docker Stack是用于在Swarm中部署和管理应用栈的工具,类似于Docker Compose。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 部署应用栈
docker stack deploy -c docker-compose.yml my_stack

# 查看应用栈
docker stack ls

# 查看应用栈服务
docker stack services my_stack

# 查看应用栈任务
docker stack ps my_stack

# 删除应用栈
docker stack rm my_stack

安全最佳实践

镜像安全

  1. 使用官方镜像:尽量使用Docker Hub上的官方镜像
  2. 定期更新镜像:及时更新基础镜像,修复已知漏洞
  3. 扫描镜像漏洞:使用Docker Scan或第三方工具扫描镜像漏洞
  4. 使用多阶段构建:减小镜像体积,降低攻击面

容器安全

  1. 以非root用户运行容器:通过USER指令设置非特权用户
  2. 限制资源使用:使用–memory和–cpu-shares等参数限制资源使用
  3. 使用只读文件系统:通过–read-only参数设置只读文件系统
  4. 使用安全计算模式:通过–security-opt参数设置安全选项
  5. 使用网络隔离:合理配置网络,避免不必要的暴露

主机安全

  1. 更新Docker:及时更新Docker到最新版本
  2. 保护Docker守护进程:限制对Docker守护进程的访问
  3. 使用内容信任:启用Docker Content Trust验证镜像签名
  4. 监控容器活动:使用审计工具监控容器活动

常见问题及解决方案

容器日志过大

问题:容器日志过大,占用磁盘空间。
解决方案:设置日志轮转。

1
2
3
4
5
6
7
8
# 在/etc/docker/daemon.json中配置
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}

容器无法访问网络

问题:容器无法访问外部网络。
解决方案:检查网络配置和DNS设置。

1
2
3
4
5
# 检查DNS配置
docker run --rm busybox nslookup google.com

# 指定DNS服务器
docker run --dns 8.8.8.8 busybox nslookup google.com

容器启动失败

问题:容器启动失败,无法创建。
解决方案:查看容器日志,检查错误信息。

1
2
3
4
5
# 查看容器日志
docker logs <container_id>

# 使用交互式方式启动容器,观察错误
docker run -it --rm <image_name> /bin/bash

总结

Docker已成为现代软件开发和部署的标准工具,它通过容器化技术简化了应用的构建、分发和运行过程。本文介绍了Docker的核心概念、基本使用方法及最佳实践,希望能帮助读者快速掌握这一技术,并在实际项目中充分发挥Docker的优势。随着云原生技术的不断发展,Docker作为其中重要的基础设施,将继续在软件工程中发挥重要作用。