Docker与容器化:从基础到实践

详细介绍Docker容器技术的核心概念、基本操作和最佳实践,帮助你掌握容器化应用的开发、部署和管理

Docker与容器化:从基础到实践

引言:容器化时代的到来

在当今快速迭代的软件行业,如何确保应用在不同环境中一致运行,如何简化应用部署流程,如何提高资源利用率,成为开发者和运维人员面临的共同挑战。Docker容器技术的出现,为解决这些问题提供了一套优雅的解决方案。

作为云原生技术栈的基础,Docker已经成为现代软件开发和部署的标准工具。本文将带你从基础概念开始,逐步深入Docker的核心功能和实践技巧,帮助你掌握容器化应用的开发、部署和管理。

第一章:Docker基础概念

1.1 什么是Docker?

Docker是一个开源的容器化平台,它允许开发者将应用及其依赖打包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以在Windows上运行。容器完全使用沙箱机制,相互之间不会有任何接口,更重要的是容器性能开销极低。

Docker与传统虚拟化技术的主要区别在于:

  • 传统虚拟机需要完整的操作系统,而容器共享宿主机内核
  • 容器启动速度快,通常在秒级别,而虚拟机需要几分钟
  • 容器资源占用小,一台宿主机可以运行数千个容器
  • 容器更轻量,镜像大小通常在MB级别,而虚拟机镜像在GB级别

1.2 Docker核心组件

Docker生态系统包含以下几个核心组件:

  • Docker Engine:Docker的核心运行时,包括Docker守护进程、REST API接口和命令行工具
  • Docker Image:容器的只读模板,包含运行应用所需的所有文件和配置
  • Docker Container:镜像的运行实例,可以被创建、启动、停止、删除和暂停
  • Docker Registry:存储和分发Docker镜像的仓库,如Docker Hub
  • Docker Compose:用于定义和运行多容器Docker应用的工具
  • Docker Swarm:Docker原生的容器编排工具

理解这些组件之间的关系,是掌握Docker的第一步。

1.3 Docker架构

Docker采用客户端-服务器(C/S)架构模式,主要包含以下部分:

  • Docker客户端:提供命令行界面,用户通过客户端与Docker守护进程通信
  • Docker守护进程:负责管理Docker对象,如镜像、容器、网络和卷
  • Docker镜像:容器的构建块,基于联合文件系统
  • Docker容器:镜像的运行实例
  • Docker注册表:存储Docker镜像的仓库

Docker使用REST API进行通信,客户端可以通过命令行或API与Docker守护进程交互,守护进程负责实际的容器创建和管理工作。

第二章:Docker安装与配置

2.1 在不同平台安装Docker

Docker支持多种操作系统,包括Linux、Windows和macOS。下面简要介绍在不同平台上的安装方法:

在Ubuntu/Debian上安装:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 更新软件包列表
sudo apt update

# 安装必要的依赖
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release

# 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 设置稳定版仓库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装Docker Engine
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io

# 验证安装是否成功
sudo docker run hello-world

在CentOS/RHEL上安装:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 安装必要的依赖
sudo yum install -y yum-utils

# 设置稳定版仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 安装Docker Engine
sudo yum install docker-ce docker-ce-cli containerd.io

# 启动Docker并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 验证安装是否成功
sudo docker run hello-world

在Windows或macOS上安装: 可以直接从Docker官网下载Docker Desktop安装包,这是一个图形化的安装程序,包含了Docker Engine、Docker CLI、Docker Compose等组件。

2.2 Docker配置与优化

安装完成后,可能需要进行一些基本配置来优化Docker的性能和安全性:

允许非root用户使用Docker:

1
2
3
4
5
6
7
8
# 创建docker用户组(如果不存在)
sudo groupadd docker

# 将当前用户添加到docker组
sudo usermod -aG docker $USER

# 重新登录或执行以下命令使更改生效
newgrp docker

修改Docker存储位置: 默认情况下,Docker镜像和容器存储在/var/lib/docker目录下。如果需要修改存储位置,可以编辑Docker配置文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 创建或编辑Docker配置文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "data-root": "/path/to/new/docker/location"
}
EOF

# 重启Docker服务
sudo systemctl restart docker

配置Docker网络: Docker默认提供了几种网络模式,包括bridge、host、none等。可以根据需要创建自定义网络:

1
2
3
4
5
# 创建自定义网络
docker network create --driver bridge my-network

# 查看所有网络
docker network ls

2.3 常用Docker命令

Docker提供了丰富的命令行工具,以下是一些最常用的Docker命令:

镜像相关命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 拉取镜像
docker pull [镜像名]:[标签]

# 列出本地镜像
docker images

# 构建镜像
docker build -t [镜像名]:[标签] [Dockerfile路径]

# 删除镜像
docker rmi [镜像ID或名称]

容器相关命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 运行容器
docker run [选项] [镜像名] [命令]

# 列出容器
docker ps [-a]

# 启动/停止/重启容器
docker start/stop/restart [容器ID或名称]

# 进入运行中的容器
docker exec -it [容器ID或名称] [shell]

# 删除容器
docker rm [容器ID或名称]

其他常用命令:

1
2
3
4
5
6
7
8
9
# 查看容器日志
docker logs [容器ID或名称]

# 查看容器资源使用情况
docker stats [容器ID或名称]

# 导出/导入容器
docker export [容器ID] > [文件名].tar
docker import [文件名].tar [镜像名]:[标签]

第三章:Docker镜像与容器管理

3.1 Docker镜像基础

Docker镜像是容器的构建块,它是一个只读的模板,包含运行应用所需的所有文件和配置。Docker镜像基于联合文件系统(UnionFS),采用分层设计,每一层都是只读的,这样可以实现镜像的复用和高效存储。

镜像层的特点:

  • 每一层都是只读的,新的层可以添加到现有层之上
  • 不同镜像可以共享基础层,节省存储空间
  • 当容器运行时,会在镜像层之上添加一个可写层

3.2 Dockerfile详解

Dockerfile是一个文本文件,包含了一系列构建Docker镜像的指令。通过Dockerfile,我们可以自动化镜像的构建过程,确保镜像的可重复性和一致性。

以下是一个典型的Dockerfile示例:

 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-alpine

# 设置工作目录
WORKDIR /app

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

# 安装依赖
RUN npm install

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 3000

# 定义启动命令
CMD ["node", "server.js"]

常用的Dockerfile指令:

  • FROM:指定基础镜像
  • WORKDIR:设置工作目录
  • COPY/ADD:复制文件到镜像
  • RUN:在镜像构建时执行命令
  • EXPOSE:声明容器运行时暴露的端口
  • CMD:指定容器启动时执行的命令
  • ENTRYPOINT:配置容器的入口点
  • ENV:设置环境变量
  • VOLUME:创建挂载点

3.3 构建高效的Docker镜像

构建高效的Docker镜像需要遵循一些最佳实践:

  1. 使用多阶段构建:将构建过程分为多个阶段,最终只保留必要的文件
  2. 使用轻量级基础镜像:如Alpine、distroless等
  3. 合理安排指令顺序:将不常变化的指令放在前面,利用Docker的缓存机制
  4. 最小化镜像层数:合并RUN指令,减少镜像层数
  5. 清理不必要的文件:在每个RUN指令后清理临时文件

以下是一个使用多阶段构建的Dockerfile示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 构建阶段
FROM node:14-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 运行阶段
FROM node:14-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm install --production
EXPOSE 3000
CMD ["node", "dist/server.js"]

3.4 容器生命周期管理

Docker容器有自己的生命周期,了解这个生命周期对于管理容器至关重要:

  1. 创建容器:通过docker create命令创建容器,但不启动
  2. 启动容器:通过docker start命令启动已创建的容器
  3. 运行容器:通过docker run命令一步完成创建和启动
  4. 暂停/恢复容器:通过docker pause/unpause命令暂停或恢复容器
  5. 停止容器:通过docker stop命令停止运行中的容器
  6. 删除容器:通过docker rm命令删除已停止的容器

在容器运行时,我们可以:

  • 通过docker exec命令在容器中执行命令
  • 通过docker cp命令在主机和容器之间复制文件
  • 通过docker logs命令查看容器日志

第四章:Docker网络与存储

4.1 Docker网络模型

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

  • bridge:默认网络驱动,适用于单机环境中运行的容器
  • host:容器直接使用宿主机网络,性能最好,但隔离性较差
  • none:容器没有网络接口,完全与外部隔离
  • overlay:适用于Docker Swarm或Kubernetes等多主机环境
  • macvlan:为容器分配MAC地址,使其看起来像物理设备

4.2 网络配置实战

创建和管理网络:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 创建自定义bridge网络
docker network create --driver bridge my-network

# 列出所有网络
docker network ls

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

# 将运行中的容器连接到网络
docker network connect my-network my-container

# 断开容器与网络的连接
docker network disconnect my-network my-container

在特定网络中运行容器:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 在指定网络中运行容器
docker run --network my-network --name my-app nginx

# 容器间通信示例
# 1. 在my-network网络中启动两个容器
docker run -d --network my-network --name app1 nginx
docker run -d --network my-network --name app2 nginx

# 2. 在app1容器中ping app2容器
docker exec app1 ping app2

4.3 Docker存储选项

Docker提供了多种存储选项,用于持久化容器数据:

  1. 卷(Volumes):由Docker管理的持久化存储,存储在Docker管理的目录中
  2. 绑定挂载(Bind mounts):将主机上的任意目录或文件挂载到容器中
  3. tmpfs挂载:存储在主机内存中,容器停止后数据丢失

卷的使用:

 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 run -d -v my-volume:/app/data --name my-app nginx

# 删除卷
docker volume rm my-volume

绑定挂载的使用:

1
2
# 使用绑定挂载运行容器
docker run -d -v /host/path:/container/path --name my-app nginx

4.4 数据持久化最佳实践

在使用Docker进行数据持久化时,应遵循以下最佳实践:

  1. 使用卷而非绑定挂载:卷由Docker管理,更安全可靠
  2. 分离数据和应用:应用代码和配置放在镜像中,数据使用卷存储
  3. 定期备份数据卷:可以使用docker cp命令或备份卷目录
  4. 使用命名卷:便于管理和引用
  5. 考虑使用外部存储:对于生产环境,可以使用云存储或网络存储

第五章:Docker Compose多容器应用

5.1 Docker Compose介绍

Docker Compose是一个用于定义和运行多容器Docker应用的工具。通过YAML文件,我们可以配置应用所需的所有服务,然后使用一个命令即可启动、停止和管理整个应用。

Docker Compose的主要功能:

  • 使用YAML文件定义多容器应用
  • 一次性启动、停止和重启所有服务
  • 管理服务之间的网络连接
  • 配置服务的环境变量、卷和端口映射等
  • 扩展服务实例数量

5.2 编写docker-compose.yml文件

一个基本的docker-compose.yml文件包含以下部分:

 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
version: '3'

services:
  web:
    build: .
    ports:
      - "80:80"
    depends_on:
      - db
    environment:
      - DB_HOST=db
      - DB_USER=user
      - DB_PASSWORD=password
  
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root_password
      - MYSQL_DATABASE=myapp
      - MYSQL_USER=user
      - MYSQL_PASSWORD=password

volumes:
  db_data:

主要配置项:

  • version:指定Compose文件格式的版本
  • services:定义应用所需的服务
  • build:指定构建上下文或Dockerfile
  • image:指定使用的镜像
  • ports:配置端口映射
  • volumes:配置数据卷
  • environment:设置环境变量
  • depends_on:定义服务间的依赖关系

5.3 使用Docker Compose管理应用

常用的Docker Compose命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 启动应用
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看服务日志
docker-compose logs [服务名]

# 停止应用
docker-compose down

# 重新构建镜像并启动
docker-compose up -d --build

# 扩展服务实例数量
docker-compose up -d --scale web=3

5.4 多环境配置策略

在实际开发中,我们通常需要为不同环境(开发、测试、生产)配置不同的设置。Docker Compose提供了几种处理多环境配置的方法:

  1. 使用环境变量文件(.env)
1
2
3
# 创建.env文件
DB_HOST=localhost
DB_USER=admin
  1. 使用扩展文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# docker-compose.yml(基础配置)
version: '3'
services:
  web:
    image: myapp:latest
    ports:
      - "80:80"

# docker-compose.prod.yml(生产环境覆盖配置)
version: '3'
services:
  web:
    ports:
      - "443:80"
    environment:
      - NODE_ENV=production

使用扩展文件启动:

1
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

第六章:Docker在CI/CD中的应用

6.1 Docker与持续集成

Docker在持续集成(CI)中的应用主要体现在以下几个方面:

  1. 统一构建环境:使用Docker镜像作为构建环境,确保所有开发人员和CI服务器使用相同的环境
  2. 隔离构建任务:每个构建任务在独立的容器中运行,避免环境冲突
  3. 简化CI配置:使用Dockerfile定义构建步骤,使CI配置更加清晰
  4. 加速构建过程:利用Docker的缓存机制加速构建

6.2 Docker与持续部署

在持续部署(CD)流程中,Docker扮演着重要角色:

  1. 标准化部署单元:Docker容器作为应用的部署单元,确保从构建到部署的一致性
  2. 简化部署流程:使用Docker Compose或Kubernetes定义部署配置
  3. 支持蓝绿部署和金丝雀发布:通过Docker容器的快速启动和停止,实现平滑的部署策略
  4. 提高部署可靠性:容器的隔离性和一致性降低了部署风险

6.3 构建CI/CD流水线

一个典型的基于Docker的CI/CD流水线包含以下步骤:

  1. 代码提交:开发人员将代码提交到代码仓库(如Git)
  2. 触发构建:CI服务器检测到代码变更,触发构建流程
  3. 构建镜像:使用Dockerfile构建应用镜像
  4. 运行测试:在容器中运行单元测试、集成测试等
  5. 推送镜像:将测试通过的镜像推送到镜像仓库
  6. 部署应用:从镜像仓库拉取镜像,部署到目标环境

以下是使用Jenkins实现的CI/CD流水线示例:

 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
pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp:${BUILD_NUMBER} .'
            }
        }
        stage('Test') {
            steps {
                sh 'docker run myapp:${BUILD_NUMBER} npm test'
            }
        }
        stage('Push') {
            steps {
                sh 'docker tag myapp:${BUILD_NUMBER} myregistry/myapp:${BUILD_NUMBER}'
                sh 'docker push myregistry/myapp:${BUILD_NUMBER}'
            }
        }
        stage('Deploy') {
            steps {
                sh 'docker-compose -f docker-compose.prod.yml up -d'
            }
        }
    }
}

结语:Docker与云原生未来

Docker作为容器化技术的代表,已经深刻改变了软件开发和部署的方式。通过本文的学习,你应该已经掌握了Docker的基础知识和常用操作,能够使用Docker构建、运行和管理容器化应用。

随着云原生技术的发展,Docker已经成为Kubernetes等容器编排平台的基础。在接下来的系列文章中,我们将深入探讨Kubernetes,学习如何在更大规模的环境中管理容器。

无论你是开发人员、运维工程师还是DevOps实践者,掌握Docker都是迈向云原生时代的重要一步。希望本文能够帮助你在容器化道路上走得更远!

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计